use libpso::PacketParseError;
use libpso::crypto::PSOCipher;

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ClientId(pub usize);

pub enum OnConnect<S: SendServerPacket> {
    Packet(S),
    Cipher((Box<dyn PSOCipher + Send + Sync>, Box<dyn PSOCipher + Send + Sync>)),
}

pub trait RecvServerPacket: Sized + Sync {
    fn from_bytes(data: &[u8]) -> Result<Self, PacketParseError>;
}

pub trait SendServerPacket: Sized + Sync {
    fn as_bytes(&self) -> Vec<u8>;
}

// TODO: rename this trait, this isn't the state but the actionability of the state re: the client
#[async_trait::async_trait]
pub trait ServerState {
    type SendPacket: SendServerPacket;
    type RecvPacket: RecvServerPacket;
    type PacketError;
    
    fn on_connect(&mut self, id: ClientId) -> Vec<OnConnect<Self::SendPacket>>;
    async fn handle(&mut self, id: ClientId, pkt: &Self::RecvPacket)
                    -> Result<Box<dyn Iterator<Item = (ClientId, Self::SendPacket)> + Send>, Self::PacketError>;
    fn on_disconnect(&mut self, id: ClientId) -> Vec<(ClientId, Self::SendPacket)>;
}