pub mod utils;

use deku::prelude::*;
pub use self::utils::{
    DekuBytes,
    read_pascal_string,
    read_vec_u32,
    write_pascal_string,
    write_vec_u32,
};

#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
pub struct UserChatMessage {
    #[deku(
        reader = "read_pascal_string(deku::reader)",
        writer = "write_pascal_string(deku::writer, &self.role)"
    )]
    pub role: String,

    #[deku(
        reader = "read_pascal_string(deku::reader)",
        writer = "write_pascal_string(deku::writer, &self.content)"
    )]
    pub content: String,
}

#[deku::deku_derive(DekuRead, DekuWrite)]
#[derive(Debug, Clone, PartialEq)]
pub struct UserChatCompletionRequest {
    #[deku(
        reader = "read_vec_u32(deku::reader)",
        writer = "write_vec_u32(deku::writer, &self.messages)"
    )]
    pub messages: Vec<UserChatMessage>,
}

impl UserChatCompletionRequest {
    pub fn new(messages: Vec<UserChatMessage>) -> Self {
        Self { messages }
    }
}

#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
#[deku(id_type = "u8")]
#[repr(u8)]
pub enum UserRequest {
    #[deku(id = "0")]
    ChatCompletion(UserChatCompletionRequest),
    #[deku(id = "1")]
    ChatCompletionCancellation,
}

#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
pub struct UserResponseChatCompletion {
    #[deku(
        reader = "read_pascal_string(deku::reader)",
        writer = "write_pascal_string(deku::writer, &self.piece)"
    )]
    pub piece: String,
}

#[derive(Debug, Clone, PartialEq, DekuRead, DekuWrite)]
#[deku(id_type = "u8")]
#[repr(u8)]
pub enum UserResponse {
    #[deku(id = "0")]
    ChatCompletion(UserResponseChatCompletion),
    #[deku(id = "1")]
    ChatCompletionCancellation,
    #[deku(id = "2")]
    ChatCompletionEnd,
}

impl DekuBytes for UserChatMessage {}

impl DekuBytes for UserChatCompletionRequest {}

impl DekuBytes for UserRequest {}

impl DekuBytes for UserResponseChatCompletion {}
impl DekuBytes for UserResponse {}
