use std::collections::BTreeMap;

use crate::inspect::smp::save_load::SmpLoadedSaveSlice;

pub(super) struct AvailabilityProjection {
    pub(super) candidate_availability: BTreeMap<String, u32>,
    pub(super) named_locomotive_availability: BTreeMap<String, u32>,
    pub(super) special_conditions: BTreeMap<String, u32>,
}

pub(super) fn project_availability(
    save_slice: &SmpLoadedSaveSlice,
    metadata: &mut BTreeMap<String, String>,
) -> AvailabilityProjection {
    let mut candidate_availability = BTreeMap::new();
    if let Some(table) = &save_slice.candidate_availability_table {
        metadata.insert(
            "save_slice.candidate_table_source_kind".to_string(),
            table.source_kind.clone(),
        );
        metadata.insert(
            "save_slice.candidate_table_semantic_family".to_string(),
            table.semantic_family.clone(),
        );
        metadata.insert(
            "save_slice.candidate_table_entry_count".to_string(),
            table.observed_entry_count.to_string(),
        );
        metadata.insert(
            "save_slice.candidate_table_zero_count".to_string(),
            table.zero_availability_count.to_string(),
        );
        for entry in &table.entries {
            candidate_availability.insert(entry.text.clone(), entry.availability_dword);
        }
    }

    let mut special_conditions = BTreeMap::new();
    if let Some(table) = &save_slice.special_conditions_table {
        metadata.insert(
            "save_slice.special_conditions_source_kind".to_string(),
            table.source_kind.clone(),
        );
        metadata.insert(
            "save_slice.special_conditions_table_offset".to_string(),
            table.table_offset.to_string(),
        );
        metadata.insert(
            "save_slice.special_conditions_enabled_visible_count".to_string(),
            table.enabled_visible_count.to_string(),
        );
        for entry in &table.entries {
            if !entry.hidden {
                special_conditions.insert(entry.label.clone(), entry.value);
            }
        }
    }

    let mut named_locomotive_availability = BTreeMap::new();
    if let Some(table) = &save_slice.named_locomotive_availability_table {
        metadata.insert(
            "save_slice.named_locomotive_availability_source_kind".to_string(),
            table.source_kind.clone(),
        );
        metadata.insert(
            "save_slice.named_locomotive_availability_semantic_family".to_string(),
            table.semantic_family.clone(),
        );
        metadata.insert(
            "save_slice.named_locomotive_availability_entry_count".to_string(),
            table.observed_entry_count.to_string(),
        );
        metadata.insert(
            "save_slice.named_locomotive_availability_zero_count".to_string(),
            table.zero_availability_count.to_string(),
        );
        if let Some(header_offset) = table.header_offset {
            metadata.insert(
                "save_slice.named_locomotive_availability_header_offset".to_string(),
                header_offset.to_string(),
            );
        }
        for entry in &table.entries {
            named_locomotive_availability.insert(entry.text.clone(), entry.availability_dword);
        }
    }

    AvailabilityProjection {
        candidate_availability,
        named_locomotive_availability,
        special_conditions,
    }
}
