use alloc::vec::Vec;
use super::{
    ByteReader, ByteWriter, Deserializable, DeserializationError, Digest, Felt, NoteId,
    NoteMetadata, Serializable, Word,
};
use crate::Hasher;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct NoteHeader {
    note_id: NoteId,
    note_metadata: NoteMetadata,
}
impl NoteHeader {
    pub fn new(note_id: NoteId, note_metadata: NoteMetadata) -> Self {
        Self { note_id, note_metadata }
    }
    pub fn id(&self) -> NoteId {
        self.note_id
    }
    pub fn metadata(&self) -> &NoteMetadata {
        &self.note_metadata
    }
    pub fn hash(&self) -> Digest {
        compute_note_hash(self.id(), self.metadata())
    }
}
pub fn compute_note_hash(id: NoteId, metadata: &NoteMetadata) -> Digest {
    Hasher::merge(&[id.inner(), Word::from(metadata).into()])
}
impl From<NoteHeader> for [Felt; 8] {
    fn from(note_header: NoteHeader) -> Self {
        (¬e_header).into()
    }
}
impl From<NoteHeader> for [Word; 2] {
    fn from(note_header: NoteHeader) -> Self {
        (¬e_header).into()
    }
}
impl From<NoteHeader> for [u8; 64] {
    fn from(note_header: NoteHeader) -> Self {
        (¬e_header).into()
    }
}
impl From<&NoteHeader> for [Felt; 8] {
    fn from(note_header: &NoteHeader) -> Self {
        let mut elements: [Felt; 8] = Default::default();
        elements[..4].copy_from_slice(note_header.note_id.as_elements());
        elements[4..].copy_from_slice(&Word::from(note_header.metadata()));
        elements
    }
}
impl From<&NoteHeader> for [Word; 2] {
    fn from(note_header: &NoteHeader) -> Self {
        let mut elements: [Word; 2] = Default::default();
        elements[0].copy_from_slice(note_header.note_id.as_elements());
        elements[1].copy_from_slice(&Word::from(note_header.metadata()));
        elements
    }
}
impl From<&NoteHeader> for [u8; 64] {
    fn from(note_header: &NoteHeader) -> Self {
        let mut elements: [u8; 64] = [0; 64];
        let note_metadata_bytes = Word::from(note_header.metadata())
            .iter()
            .flat_map(|x| x.as_int().to_le_bytes())
            .collect::<Vec<u8>>();
        elements[..32].copy_from_slice(¬e_header.note_id.as_bytes());
        elements[32..].copy_from_slice(¬e_metadata_bytes);
        elements
    }
}
impl Serializable for NoteHeader {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        self.note_id.write_into(target);
        self.note_metadata.write_into(target);
    }
}
impl Deserializable for NoteHeader {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let note_id = NoteId::read_from(source)?;
        let note_metadata = NoteMetadata::read_from(source)?;
        Ok(Self { note_id, note_metadata })
    }
}