use crate::chaindef::ScriptHash;

use crate::store::{db_decode, db_encode};
use crate::{chaindef::OutPointHash, store::Row};

use super::DBRow;
use crate::bitcoin_hashes::Hash;

const OUTTOSCRIPTHASH_CF: &str = "outtoscripthash";

/// This is a database in rostrum that is NOT write-only.
// Used to find keys when pruning updating unspent index and spent scripthash index.
// When we're done updating spent data, it's removed from this index.

#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct OutToScripthashIndex {
    pub outpointhash: [u8; 32], // key
    pub scripthash: [u8; 32],
    pub has_token: bool,
}

impl OutToScripthashIndex {
    pub fn new(scripthash: ScriptHash, oph: OutPointHash, has_token: bool) -> Self {
        Self {
            scripthash: scripthash.into_inner(),
            outpointhash: oph.into_inner(),
            has_token,
        }
    }

    pub fn to_key(oph: &OutPointHash) -> Vec<u8> {
        oph.as_inner().to_vec()
    }

    pub fn scripthash(&self) -> ScriptHash {
        ScriptHash::from_slice(&self.scripthash).unwrap()
    }

    pub fn has_token(&self) -> bool {
        self.has_token
    }
}

impl DBRow for OutToScripthashIndex {
    const CF: &'static str = OUTTOSCRIPTHASH_CF;
    fn to_row(&self) -> Row {
        Row {
            key: db_encode(&self.outpointhash).unwrap().into_boxed_slice(),
            value: db_encode(&(self.scripthash, self.has_token))
                .unwrap()
                .into_boxed_slice(),
        }
    }

    fn from_row(row: &Row) -> Self {
        let (scripthash, has_token): ([u8; 32], bool) =
            db_decode(&row.value).expect("failed to parse OutToScripthashIndex");
        Self {
            outpointhash: db_decode(&row.key).expect("failed to parse OutToScripthashIndex"),
            scripthash,
            has_token,
        }
    }
}
