mod availability;
mod catalogs;
mod overrides;
mod save_profile;
mod world_restore;

use std::collections::BTreeMap;

use crate::inspect::smp::save_load::SmpLoadedSaveSlice;
use crate::state::{
    RuntimeCargoCatalogEntry, RuntimeLocomotiveCatalogEntry, RuntimeSaveProfileState,
    RuntimeWorldRestoreState,
};

pub(super) struct ProfileWorldProjection {
    pub(super) save_profile: RuntimeSaveProfileState,
    pub(super) world_restore: RuntimeWorldRestoreState,
    pub(super) candidate_availability: BTreeMap<String, u32>,
    pub(super) named_locomotive_availability: BTreeMap<String, u32>,
    pub(super) locomotive_catalog: Option<Vec<RuntimeLocomotiveCatalogEntry>>,
    pub(super) cargo_catalog: Option<Vec<RuntimeCargoCatalogEntry>>,
    pub(super) named_locomotive_cost: BTreeMap<String, u32>,
    pub(super) all_cargo_price_override: Option<u32>,
    pub(super) named_cargo_price_overrides: BTreeMap<String, u32>,
    pub(super) all_cargo_production_override: Option<u32>,
    pub(super) factory_cargo_production_override: Option<u32>,
    pub(super) farm_mine_cargo_production_override: Option<u32>,
    pub(super) named_cargo_production_overrides: BTreeMap<String, u32>,
    pub(super) cargo_production_overrides: BTreeMap<u32, u32>,
    pub(super) world_scalar_overrides: BTreeMap<String, i64>,
    pub(super) special_conditions: BTreeMap<String, u32>,
}

use availability::{AvailabilityProjection, project_availability};
use catalogs::{CatalogProjection, project_catalogs};
use overrides::{OverrideProjection, project_overrides};
use save_profile::project_save_profile;
use world_restore::project_world_restore;

pub(super) fn project_profile_world(
    save_slice: &SmpLoadedSaveSlice,
    metadata: &mut BTreeMap<String, String>,
) -> ProfileWorldProjection {
    let save_profile = project_save_profile(save_slice, metadata);
    let world_restore = project_world_restore(save_slice);
    let AvailabilityProjection {
        candidate_availability,
        named_locomotive_availability,
        special_conditions,
    } = project_availability(save_slice, metadata);
    let CatalogProjection {
        locomotive_catalog,
        cargo_catalog,
    } = project_catalogs(save_slice, metadata);
    let OverrideProjection {
        named_locomotive_cost,
        all_cargo_price_override,
        named_cargo_price_overrides,
        all_cargo_production_override,
        factory_cargo_production_override,
        farm_mine_cargo_production_override,
        named_cargo_production_overrides,
        cargo_production_overrides,
        world_scalar_overrides,
    } = project_overrides(save_slice, metadata);

    ProfileWorldProjection {
        save_profile,
        world_restore,
        candidate_availability,
        named_locomotive_availability,
        locomotive_catalog,
        cargo_catalog,
        named_locomotive_cost,
        all_cargo_price_override,
        named_cargo_price_overrides,
        all_cargo_production_override,
        factory_cargo_production_override,
        farm_mine_cargo_production_override,
        named_cargo_production_overrides,
        cargo_production_overrides,
        world_scalar_overrides,
        special_conditions,
    }
}
