pub const CONTROL_PACKET_SIZE: usize = 20;

pub fn make_control_packet(
    head_magic: u32,
    tail_magic: u32,
    conv: u32,
    token: u32,
    data: u32,
) -> [u8; CONTROL_PACKET_SIZE] {
    let mut buf = Vec::with_capacity(CONTROL_PACKET_SIZE);

    buf.extend(head_magic.to_be_bytes());
    buf.extend(conv.to_be_bytes());
    buf.extend(token.to_be_bytes());
    buf.extend(data.to_be_bytes());
    buf.extend(tail_magic.to_be_bytes());

    buf.try_into().unwrap()
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum ControlPacketType {
    Connect,
    SendBackConv,
    Disconnect,
}

#[allow(dead_code)]
pub fn make_connect_packet(conv: u32, token: u32, data: u32) -> [u8; CONTROL_PACKET_SIZE] {
    make_control_packet(0xFF, 0xFFFFFFFF, conv, token, data)
}

pub fn make_send_back_conv_packet(conv: u32, token: u32, data: u32) -> [u8; CONTROL_PACKET_SIZE] {
    make_control_packet(0x145, 0x14514545, conv, token, data)
}

pub fn make_disconnect_packet(conv: u32, token: u32, data: u32) -> [u8; CONTROL_PACKET_SIZE] {
    make_control_packet(0x194, 0x19419494, conv, token, data)
}

pub fn get_conv_from_control_packet(data: &[u8]) -> u32 {
    u32::from_be_bytes(data[4..8].try_into().unwrap())
}

pub fn get_token_from_control_packet(data: &[u8]) -> u32 {
    u32::from_be_bytes(data[8..12].try_into().unwrap())
}

pub fn get_data_from_control_packet(data: &[u8]) -> u32 {
    u32::from_be_bytes(data[12..16].try_into().unwrap())
}

pub fn get_control_packet_type(data: &[u8]) -> Option<ControlPacketType> {
    let head_magic = u32::from_be_bytes(data[0..4].try_into().unwrap());
    let tail_magic = u32::from_be_bytes(data[16..20].try_into().unwrap());

    match (head_magic, tail_magic) {
        (0xFF, 0xFFFFFFFF) => Some(ControlPacketType::Connect),
        (0x145, 0x14514545) => Some(ControlPacketType::SendBackConv),
        (0x194, 0x19419494) => Some(ControlPacketType::Disconnect),
        _ => None,
    }
}
