use std::collections::{BTreeSet, HashMap};

use data::tables::{quick_access_template_tb, QuickFuncID, UnlockConfigID};
use proto::{LockModelBin, QuickAccessData, QuickAccessType, UnlockData};

#[derive(Default)]
pub struct LockModel {
    unlock_list: BTreeSet<UnlockConfigID>,
    quick_access_list: HashMap<u32, QuickFuncID>,
}

impl LockModel {
    pub fn from_bin(bin: LockModelBin) -> Self {
        Self {
            unlock_list: bin
                .unlock_list
                .into_iter()
                .map(|id| UnlockConfigID::new_unchecked(id as u32))
                .collect(),
            quick_access_list: bin
                .quick_access_list
                .into_iter()
                .map(|(k, v)| (k, QuickFuncID::new_unchecked(v)))
                .collect(),
        }
    }

    pub fn to_bin(&self) -> LockModelBin {
        LockModelBin {
            unlock_list: self
                .unlock_list
                .clone()
                .into_iter()
                .map(|i| i.value() as i32)
                .collect(),
            quick_access_list: self
                .quick_access_list
                .iter()
                .map(|(k, v)| (k.clone(), v.value()))
                .collect(),
        }
    }

    pub fn quick_access_to_client(&self) -> Vec<QuickAccessData> {
        let mut quick_access_data_list: Vec<QuickAccessData> = vec![];
        for quick_access in quick_access_template_tb::iter() {
            quick_access_data_list.push(QuickAccessData {
                r#type: QuickAccessType::Direct.into(),
                quick_access_index: quick_access.quick_access_index,
                btn_id: quick_access.quick_func_id.value(),
            });
        }
        for quick_access_index in 1..8 {
            let mut btn_id = 0;
            if let Some(id) = self.quick_access_list.get(&quick_access_index) {
                btn_id = id.value();
            }
            quick_access_data_list.push(QuickAccessData {
                r#type: QuickAccessType::QuickMenu.into(),
                quick_access_index,
                btn_id,
            });
        }
        quick_access_data_list
    }

    pub fn to_client(&self) -> UnlockData {
        UnlockData {
            unlock_id_list: self
                .unlock_list
                .clone()
                .into_iter()
                .map(|i| i.value() as i32)
                .collect(),
            quick_access_data_list: self.quick_access_to_client(),
            ..Default::default()
        }
    }

    pub fn add_unlock(&mut self, id: UnlockConfigID) {
        self.unlock_list.insert(id);
    }

    pub fn is_unlock(&self, id: UnlockConfigID) -> bool {
        self.unlock_list.contains(&id)
    }

    pub fn mod_quick_access(&mut self, index: u32, id: Option<QuickFuncID>) {
        match id {
            Some(quick_access_id) => self.quick_access_list.insert(index, quick_access_id),
            None => self.quick_access_list.remove(&index),
        };
    }
}
