pub mod channel;
pub mod client;

use std::fmt::{Debug, Display, Formatter};
use crate::parameter::*;

pub enum Response {
    Ok,
    Data(ParameterList),
    DataList(Vec<ParameterList>),
}

pub struct ResponseError {
    pub id: i32,
    pub msg: String,
}

impl TryFrom<String> for Response {
    type Error = ResponseError;

    fn try_from(response_str: String) -> Result<Self, ResponseError> {
        let mut response_str = response_str.trim_end_matches("\n\r");

        if response_str.starts_with("error ") {
            response_str = response_str.trim_start_matches("error ");
            let response_params = parameter_parse(response_str);
            Err(ResponseError::create_error(&response_params))
        }
        else {
            let mut parameter_lists: Vec<ParameterList> = Vec::new();
            for response_entry in response_str.split('|') {
                let response_params = parameter_parse(response_entry);
                parameter_lists.push(response_params);
            }
            Ok(Response::DataList(parameter_lists))
        }
    }
}

impl Debug for Response {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
           match self {
               Response::Ok => {
                   write!(f, "Ok")
               }
                Response::Data(params) => {
                    write!(f, "Data:")?;
                    write!(f, "{:?};", params)?;
                    Ok(())
                }
                Response::DataList(params_list) => {
                    write!(f, "DataList:")?;
                    for params in params_list {
                        write!(f, "{:?};", params)?;
                    }
                    Ok(())
                }
           }
    }
}

impl Display for Response {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Response::Ok => {
                write!(f, "Ok")
            }
            Response::Data(params) => {
                for param in params {
                    write!(f, "{};", param)?;
                }
                Ok(())
            }
            Response::DataList(params_list) => {
                for params in params_list {
                    write!(f, "[")?;
                    for param in params {
                        write!(f, "{};", param)?;
                    }
                    write!(f, "]")?;
                }
                Ok(())
            }
        }
    }
}

impl ResponseError {
    pub fn is_error_okay(&self) -> bool {
        self.id == 0
    }

    fn create_error(params: &Vec<Parameter>) -> ResponseError {
        ResponseError {
            id: parameter_find(params, "id")
                .unwrap_or_else(|| Parameter::new(String::from("id"), String::from("-1")))
                .to_i32(-1),
            msg: parameter_find(params, "msg")
                .unwrap_or_else(|| Parameter::new(String::from("msg"), String::from("Unknown error.")))
                .value,
        }
    }
}