use std::collections::HashMap;

use data::tables::{self, BattleEventConfigID, VariableDataID, VariableValueType};
use proto::FightVariable;

pub struct LogicVariableTable {
    variable_map: HashMap<String, LogicVariable>,
}

impl LogicVariableTable {
    pub fn new(battle_event_id: BattleEventConfigID) -> Self {
        let event_id = battle_event_id.value();

        Self {
            variable_map: tables::variable_data_template_tb::iter()
                .filter(|tmpl| tmpl.battle_event_id == event_id)
                .map(|tmpl| (tmpl.variable_name.clone(), LogicVariable::new(tmpl.id)))
                .collect(),
        }
    }

    pub fn to_client(&self) -> HashMap<String, FightVariable> {
        self.variable_map
            .iter()
            .map(|(name, var)| (name.clone(), var.to_client()))
            .collect()
    }
}

pub enum LogicVariable {
    Int(i64),
    Float(f64),
    Bool(bool),
}

impl LogicVariable {
    pub fn new(id: VariableDataID) -> Self {
        let template = id.template();

        match template.value_type {
            VariableValueType::Int => Self::Int(template.initial_value.parse().unwrap_or_default()),
            VariableValueType::Bool => Self::Bool(
                template
                    .initial_value
                    .to_lowercase()
                    .parse()
                    .unwrap_or_default(),
            ),
            VariableValueType::Float => {
                Self::Float(template.initial_value.parse().unwrap_or_default())
            }
        }
    }

    pub fn to_client(&self) -> FightVariable {
        match self {
            Self::Int(val) => FightVariable {
                r#type: 1,
                int_value: *val,
                ..Default::default()
            },
            Self::Bool(val) => FightVariable {
                r#type: 4,
                int_value: *val as i64,
                ..Default::default()
            },
            Self::Float(val) => FightVariable {
                r#type: 2,
                float_value: *val,
                ..Default::default()
            },
        }
    }
}
