use serde::{Deserialize, Serialize};

use crate::{AssetAmount, AssetId, BlockHeight};

/// Deposit
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct DepositIdentifier {
    /// The asset id
    pub asset_id: AssetId,

    /// The block height
    /// Any chain does not have a block height? we use the timestamp instead? (TBD)
    pub block_height: BlockHeight,

    /// The block chain transaction id
    /// For UTXO, it is the transaction id + tx index
    pub tx_id: Option<String>,
}

/// Deposit
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
pub struct Deposit {
    /// The deposit identifier
    pub identifier: DepositIdentifier,

    /// The amount
    pub amount: AssetAmount,
}

#[cfg(test)]
mod tests {
    use ex3_serde::bincode;

    use super::*;

    #[test]
    fn test_serde() {
        let deposit_identifier = DepositIdentifier {
            asset_id: 1u64.into(),
            block_height: 2u64.into(),
            tx_id: Some("tx_id".to_string()),
        };
        let deposit = Deposit {
            identifier: deposit_identifier.clone(),
            amount: 3u64.into(),
        };
        //bincode
        let encoded = bincode::serialize(&deposit).unwrap();
        let decoded: Deposit = bincode::deserialize(&encoded).unwrap();
        assert_eq!(deposit, decoded);

        // cbor
        let encoded = ex3_serde::cbor::serialize(&deposit).unwrap();
        let decoded: Deposit = ex3_serde::cbor::deserialize(&encoded).unwrap();
        assert_eq!(deposit, decoded);
    }
}
