use serde::{Serialize, Deserialize, de::DeserializeOwned};

#[derive(Serialize, Deserialize, PartialEq, Eq)]
pub enum CrudMessageType {
    Create,
    Delete,
}

#[derive(Serialize, Deserialize, PartialEq, Eq)]
pub enum PacketType {
    /// A regular check to ensure the connection is still alive.
    Ping,
    /// General text which can be ignored.
    Text,
    /// A CRUD operation.
    Crud(CrudMessageType),
    /// A text key which identifies the socket.
    Key,
}

#[derive(Serialize, Deserialize, PartialEq, Eq)]
pub enum SocketMethod {
    /// Authentication and channel identification.
    Headers,
    /// A message was sent in the channel.
    Message,
    /// A message was deleted in the channel.
    Delete,
    /// Forward message from server to client. (Redis pubsub to ws)
    Forward(PacketType),
    /// A general packet from client to server. (ws to Redis pubsub)
    Misc(PacketType),
    /// A general packet from client to server. (ws to Redis pubsub)
    Packet(PacketType),
}

#[derive(Serialize, Deserialize)]
pub struct SocketMessage {
    pub method: SocketMethod,
    pub data: String,
}

impl SocketMessage {
    pub fn data<T: DeserializeOwned>(&self) -> T {
        serde_json::from_str(&self.data).unwrap()
    }
}

/// [`PacketType::Text`]
#[derive(Serialize, Deserialize, PartialEq, Eq)]
pub struct TextMessage {
    pub text: String,
}
