use serde::{Deserialize, Serialize};

use crate::game::{entry::GameEntry, chat_message::ChatMessage};

#[derive(Serialize, Deserialize)]
pub enum Entry {
    Weapon(Weapon),
    Consumable(Consumable),
    Spell(Spell),
}
impl GameEntry for Entry {
    fn display_name(&self) -> String {
        match self {
            Entry::Weapon(weapon) => weapon.name.clone(),
            Entry::Consumable(consumable) => consumable.name.clone(),
            Entry::Spell(spell) => spell.name.clone(),
        }
    }
    
    fn load(entry: &str) -> Option<Entry> {
        println!("loading {}", entry);
        let json = std::fs::read_to_string(format!("assets/pf2r/{}.json", entry)).ok()?;
        println!("{}", &json);
        if entry.starts_with("weapon/") {
            serde_json::from_str::<Weapon>(&json).map(|w| Entry::Weapon(w)).ok()
        }
        else if entry.starts_with("spell/") {
            serde_json::from_str::<Spell>(&json).map(|s| Entry::Spell(s)).ok()
        }
        else if entry.starts_with("consumable/") {
            serde_json::from_str::<Consumable>(&json).map(|s| Entry::Consumable(s)).ok()
        }
        else {
            None
        }
    }
    
    fn to_chat(&self) -> ChatMessage {
        let text = format!("{} - it might be a {{weapon/short_bow}} it might not", self.display_name());
        ChatMessage::new(text)
    }
    
    fn all(_filter: Option<&str>) -> Vec<String> {
        todo!()
    }

    fn categories() -> Vec<String> {
        vec![
            "weapon", "consumable", "spell"
        ]
            .iter()
            .map(|s| s.to_string())
            .collect()
    }
}

#[derive(Serialize, Deserialize, Default)]
pub struct Weapon {
    pub name: String,
    pub two_handed: bool,
    pub one_handed: bool,
    pub melee_reach: i32,
    pub ranged_reach: i32,
    // this is a weird thing but suffices for now, as it is expected as a string of `1d4 2 2d6`
    pub damage: String,
}
#[derive(Serialize, Deserialize, Default)]
pub struct Consumable  {
    name: String,
    traits: Vec<String>,
    /// Price in copper
    price: i32,
    bulk: i32,
    desc: String,
}
#[derive(Serialize, Deserialize, Default)]
pub struct Spell {
    name: String,
    actions: i32,
    damage: String,
    damage_type: String,
}

