use std::{convert::AsRef, fmt::Debug, io::Write};

use conduwuit::arrayvec::ArrayVec;
use serde::Serialize;

use crate::{keyval::KeyBuf, ser, util::or_else};

impl super::Map {
	#[inline]
	pub fn del<K>(&self, key: K)
	where
		K: Serialize + Debug,
	{
		let mut buf = KeyBuf::new();
		self.bdel(key, &mut buf);
	}

	#[inline]
	pub fn adel<const MAX: usize, K>(&self, key: K)
	where
		K: Serialize + Debug,
	{
		let mut buf = ArrayVec::<u8, MAX>::new();
		self.bdel(key, &mut buf);
	}

	#[tracing::instrument(skip(self, buf), level = "trace")]
	pub fn bdel<K, B>(&self, key: K, buf: &mut B)
	where
		K: Serialize + Debug,
		B: Write + AsRef<[u8]>,
	{
		let key = ser::serialize(buf, key).expect("failed to serialize deletion key");
		self.remove(key);
	}

	#[tracing::instrument(skip(self, key), fields(%self), level = "trace")]
	pub fn remove<K>(&self, key: &K)
	where
		K: AsRef<[u8]> + ?Sized + Debug,
	{
		let write_options = &self.write_options;
		self.db
			.db
			.delete_cf_opt(&self.cf(), key, write_options)
			.or_else(or_else)
			.expect("database remove error");

		if !self.db.corked() {
			self.db.flush().expect("database flush error");
		}
	}
}
