use data::gacha::gacha_config::*;
use data::tables::ItemID;

use proto::{GachaExtraItemBin, GachaRecordBin};
use std::collections::HashMap;

use super::stat::*;

#[derive(Debug, Clone)]
pub struct GachaExtraResources {
    pub extra_item_id: ItemID,
    pub extra_item_count: u32,
}

impl GachaExtraResources {
    pub fn from_bin_opt(bin_opt: Option<GachaExtraItemBin>) -> Option<Self> {
        match bin_opt {
            None => None,
            Some(bin) => {
                let item_id_opt = ItemID::new(bin.extra_item_id);
                match item_id_opt {
                    None => None,
                    Some(extra_item_id) => Some(Self {
                        extra_item_id,
                        extra_item_count: bin.extra_item_count,
                    }),
                }
            }
        }
    }

    pub fn to_bin_opt(opt: &Option<Self>) -> Option<GachaExtraItemBin> {
        match opt {
            None => None,
            Some(this) => Some(GachaExtraItemBin {
                extra_item_id: this.extra_item_id.value(),
                extra_item_count: this.extra_item_count.clone(),
                ..Default::default()
            }),
        }
    }
}

#[derive(Debug, Clone)]
pub struct GachaRecord {
    pub pull_timestamp: i64,
    pub obtained_item_id: ItemID,
    pub gacha_id: u32,
    /// The progress BEFORE this gacha is performed. key is rarity.
    pub progress_map: HashMap<u32, GachaProgress>,
    pub extra_resources: Option<GachaExtraResources>,
    pub item_type: GachaAddedItemType,
}

impl GachaRecord {
    pub fn from_bin(bin: GachaRecordBin) -> Self {
        Self {
            pull_timestamp: bin.pull_timestamp,
            obtained_item_id: ItemID::new_unchecked(bin.obtained_item_id),
            gacha_id: bin.gacha_id,
            progress_map: bin
                .progress_map
                .into_iter()
                .map(|(k, v)| (k, GachaProgress::from_bin(v)))
                .collect(),
            extra_resources: GachaExtraResources::from_bin_opt(bin.extra_item_bin),
            item_type: GachaAddedItemType::from(bin.item_type),
        }
    }

    pub fn to_bin(&self) -> GachaRecordBin {
        GachaRecordBin {
            pull_timestamp: self.pull_timestamp.clone(),
            obtained_item_id: self.obtained_item_id.value(),
            gacha_id: self.gacha_id.clone(),
            progress_map: self
                .progress_map
                .iter()
                .map(|(k, v)| (k.clone(), v.to_bin()))
                .collect(),
            extra_item_bin: GachaExtraResources::to_bin_opt(&self.extra_resources),
            item_type: self.item_type.clone().into(),
        }
    }
}
