use num_bigint::BigUint;
use serde::{Deserialize, Serialize};

use crate::impl_from_uint_for;

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
pub enum Version {
    /// Transaction version 0, which is the only version currently supported
    V0 = 0,
}

impl Version {
    pub fn encode(&self) -> u8 {
        let big_uint: BigUint = self.clone().into();
        let bytes = big_uint.to_bytes_le();
        assert_eq!(bytes.len(), 1, "Version should be encoded as a single byte");
        bytes[0].clone()
    }

    pub fn decode(bytes: &[u8]) -> Result<Self, String> {
        let big_uint = BigUint::from_bytes_le(bytes);
        Ok(big_uint.into())
    }
}

impl From<BigUint> for Version {
    fn from(v: BigUint) -> Self {
        match v {
            v if v == BigUint::from(0u8) => Version::V0,
            _ => panic!("unknown version"),
        }
    }
}

impl Into<BigUint> for Version {
    fn into(self) -> BigUint {
        match self {
            Version::V0 => BigUint::from(0u32),
        }
    }
}

impl_from_uint_for!(Version, u8, u16, u32, u64, u128);
