use std::fmt::{Display, Formatter};

use crate::parameter::{parameter_find, ParameterList};

#[derive(Debug)]
pub struct ResponseChannel {
    pub cid: i32,
    pub pid: i32,
    pub channel_order: i32,
    pub channel_name: String,
    pub channel_topic: String,
    pub channel_flag_are_subscribed: bool,
}

impl Display for ResponseChannel {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{} ({})", self.channel_name, self.cid)
    }
}

impl From<ParameterList> for ResponseChannel {
    fn from(value: ParameterList) -> Self {
        ResponseChannel {
            cid: parameter_find(&value, "cid")
                .unwrap_or_default()
                .to_i32(-1),
            pid: parameter_find(&value, "pid")
                .unwrap_or_default()
                .to_i32(-1),
            channel_order: parameter_find(&value, "channel_order")
                .unwrap_or_default()
                .to_i32(-1),
            channel_name: parameter_find(&value, "channel_name")
                .unwrap_or_default()
                .value,
            channel_topic: parameter_find(&value, "channel_topic")
                .unwrap_or_default()
                .value,
            channel_flag_are_subscribed: parameter_find(&value, "channel_flag_are_subscribed")
                .unwrap_or_default()
                .to_i32(0) == 1,
        }
    }
}

impl ResponseChannel {
    pub fn is_spacer(&self) -> bool {
        self.channel_name.starts_with("[spacer")
            || self.channel_name.starts_with("[*spacer")
            || self.channel_name.starts_with("[lspacer")
            || self.channel_name.starts_with("[cspacer")
            || self.channel_name.starts_with("[rspacer")
    }

    fn list_find_next(list: &mut Vec<ResponseChannel>, order: i32, pid: i32) -> Option<ResponseChannel> {
        let index = list.iter().position(|a| a.channel_order == order && a.pid == pid)?;
        Some(list.swap_remove(index))
    }

    pub fn sort_list(mut list: Vec<ResponseChannel>) -> Vec<ResponseChannel> {
        let mut list_sorted: Vec<ResponseChannel> = Vec::new();
        let mut pids: Vec<i32> = Vec::new();
        let mut pid = 0;
        let mut order = 0;

        while !list.is_empty() {
            match ResponseChannel::list_find_next(&mut list, order, pid) {
                None => {
                    order = pid;
                    pid = pids.pop().unwrap_or(0);
                }
                Some(elem) => {
                    pids.push(pid);
                    pid = elem.cid;
                    order = 0;
                    list_sorted.push(elem);
                }
            }
        }

        list_sorted
    }
}