use core_types::{BufferId, ErrorCode, ErrorDomain, RtError};
use memmap2::MmapMut;

pub(super) const HEADER_SIZE: usize = 16;
const HEADER_MAGIC: [u8; 4] = *b"RTSM";

pub(super) fn write_header(
    mmap: &mut MmapMut,
    buffer_id: BufferId,
    payload_len: usize,
) -> Result<(), RtError> {
    if mmap.len() < HEADER_SIZE {
        return Err(RtError::new(
            ErrorCode::InvalidState,
            ErrorDomain::Core,
            false,
            "segment file too small for header",
        ));
    }
    mmap[0..4].copy_from_slice(&HEADER_MAGIC);
    mmap[4..12].copy_from_slice(&buffer_id.0.to_le_bytes());
    mmap[12..16].copy_from_slice(&(payload_len as u32).to_le_bytes());
    Ok(())
}

pub(super) fn read_header(mmap: &[u8]) -> Result<(BufferId, usize), RtError> {
    if mmap.len() < HEADER_SIZE {
        return Err(RtError::new(
            ErrorCode::InvalidState,
            ErrorDomain::Core,
            false,
            "segment file too small for header",
        ));
    }
    if mmap[0..4] != HEADER_MAGIC {
        return Err(RtError::new(
            ErrorCode::NotFound,
            ErrorDomain::Core,
            true,
            "segment has no valid payload",
        ));
    }

    let mut id_buf = [0u8; 8];
    id_buf.copy_from_slice(&mmap[4..12]);
    let id = BufferId::new(u64::from_le_bytes(id_buf));

    let mut len_buf = [0u8; 4];
    len_buf.copy_from_slice(&mmap[12..16]);
    let len = u32::from_le_bytes(len_buf) as usize;
    Ok((id, len))
}
