pub mod action;
pub mod event;
pub mod gacha;
pub mod tables;

use std::{collections::HashMap, sync::OnceLock};

use jsonc_parser::errors::ParseError;
use serde::{Deserialize, Serialize};
use thiserror::Error;

#[derive(Serialize, Deserialize)]
pub struct AssetsConfig {
    pub filecfg_path: String,
    pub event_config_path: String,
    pub usm_keys_path: String,
    pub gacha_config_path: String,
}

#[derive(Error, Debug)]
pub enum DataLoadError {
    #[error("I/O error: {0}")]
    IoError(#[from] std::io::Error),
    #[error("from_json failed for type {0}, error: {1}")]
    FromJsonError(String, serde_json::Error),
    #[error("jsonc_parser parse as json error: {0}")]
    JsoncParseError(#[from] ParseError),
}

static USM_KEY_MAP: OnceLock<HashMap<u32, u64>> = OnceLock::new();

pub fn init_data(config: &AssetsConfig) -> Result<(), DataLoadError> {
    tables::load_tables(&config.filecfg_path)?;
    event::load_event_graphs(&config.event_config_path)?;
    if let Err(err) = load_usm_keys(&config.usm_keys_path) {
        tracing::warn!("failed to load USM keys, in-game cutscenes will not work! Reason: {err}");
        USM_KEY_MAP.set(HashMap::new()).unwrap();
    }
    gacha::load_gacha_config(&config.gacha_config_path)?;

    Ok(())
}

pub fn usm_key_map() -> &'static HashMap<u32, u64> {
    USM_KEY_MAP.get().unwrap()
}

fn load_usm_keys(path: &str) -> Result<(), DataLoadError> {
    let data = std::fs::read_to_string(path).map_err(|err| DataLoadError::IoError(err))?;
    let map = serde_json::from_str::<HashMap<u32, u64>>(&data)
        .map_err(|err| DataLoadError::FromJsonError(String::from("USMKeyMap"), err))?;

    USM_KEY_MAP.set(map).unwrap();
    Ok(())
}
