use std::collections::HashMap;
use serde::{Serialize, Deserialize};
use std::fs::File;
use std::io::Read;

use crate::entity::item::armor::ArmorType;
use crate::entity::item::shield::ShieldType;
use crate::entity::item::unit::UnitType;


fn load_data_file<T: serde::de::DeserializeOwned>(path: &str) -> T {
    let mut f = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);

    toml::from_str::<T>(s.as_str()).unwrap()
}


struct WeaponStats {

}

#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
struct ArmorStats {
    stars: u32,
    dfp: i32,
    evp: i32,
    dfp_modifier: u32,
    evp_modifier: u32,
    team_points: u32,
    level_req: u32,
    efr: i32,
    eic: i32,
    eth: i32,
    elt: i32,
    edk: i32,
}

#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
struct ShieldStats {
    stars: u32,
    dfp: i32,
    evp: i32,
    dfp_modifier: u32,
    evp_modifier: u32,
    team_points: u32,
    level_req: u32,
    efr: i32,
    eic: i32,
    eth: i32,
    elt: i32,
    edk: i32,
}

#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
struct UnitStats {
    stars: u32,
    stat: u32,
    amount: u32,
    team_points: u32,
    modifier: u32,
}


fn armor_stats() -> HashMap<ArmorType, ArmorStats> {
    let armor_stats: HashMap<String, ArmorStats> = load_data_file("data/item_stats/armor_stats.toml");
    armor_stats.iter()
        .map(|(name, stats)| {
            (name.parse().unwrap(), *stats)
        }).collect()
}

fn shield_stats() -> HashMap<ShieldType, ShieldStats> {
    let shield_stats: HashMap<String, ShieldStats> = load_data_file("data/item_stats/shield_stats.toml");
    shield_stats.iter()
        .map(|(name, stats)| {
            (name.parse().unwrap(), *stats)
        }).collect()
}

fn unit_stats() -> HashMap<UnitType, UnitStats> {
    let unit_stats: HashMap<String, UnitStats> = load_data_file("data/item_stats/unit_stats.toml");
    unit_stats.iter()
        .map(|(name, stats)| {
            (name.parse().unwrap(), *stats)
        }).collect()
}

#[cfg(test)]
mod test {
    use super::*;
    
    #[test]
    fn test_armor_stats() {
        let astat = armor_stats();
        assert!(astat.get(&ArmorType::CrimsonCoat).unwrap().stars == 11);
    }

    #[test]
    fn test_shield_stats() {
        let sstat = shield_stats();
        assert!(sstat.get(&ShieldType::RedRing).unwrap().stars == 11);
    }

    #[test]
    fn test_unit_stats() {
        let ustat = unit_stats();
        assert!(ustat.get(&UnitType::ElfArm).unwrap().stars == 5);
    }
}