use std::str::FromStr;

use thiserror::Error;

#[derive(Error, Debug)]
pub enum CfgError {
    #[error("Unknown client type: '{0}'")]
    UnkownClientType(String),
    #[error("Missing cookie: '{0}'")]
    MissingCookie(String),
    #[error("Invalid cookie value: '{0}'")]
    InvalidCookie(String),
}

#[derive(Debug, Clone)]
pub enum ClientType {
    Host,
    Player,
}

impl FromStr for ClientType {
    type Err = CfgError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "host" => Ok(Self::Host),
            "player" => Ok(Self::Player),
            _ => Err(CfgError::UnkownClientType(s.to_string())),
        }
    }
}

pub struct Cfg {
    pub token: String,
    pub username: String,
    pub user_id: u64,
    pub game_code: String,
    pub client_type: ClientType,
}

impl Cfg {
    pub fn load_from_cookies() -> Result<Self, CfgError> {
        let client_type = wasm_cookies::get_raw("play_of_the_game/client_type")
            .ok_or(CfgError::MissingCookie("client_type".to_string()))?;
        let token = wasm_cookies::get_raw("play_of_the_game/token")
            .ok_or(CfgError::MissingCookie("token".to_string()))?;
        let user_id = wasm_cookies::get_raw("play_of_the_game/user_id")
            .ok_or(CfgError::MissingCookie("user_id".to_string()))?
            .parse()
            .map_err(|_| CfgError::InvalidCookie("user_id".to_string()))?;
        let game_id = wasm_cookies::get_raw("play_of_the_game/game_code")
            .ok_or(CfgError::MissingCookie("game_id".to_string()))?;
        let username = wasm_cookies::get_raw("play_of_the_game/username")
            .ok_or(CfgError::MissingCookie("username".to_string()))?;

        let client_type: ClientType = ClientType::from_str(&client_type)?;

        Ok(Self {
            token,
            username,
            user_id,
            game_code: game_id,
            client_type,
        })
    }
}
