use crate::inspect::smp::special_conditions::{
    SmpLocomotivePolicyNeighborhoodProbe, SmpPostTextFieldNeighborhoodProbe,
};
use crate::inspect::smp::world::*;

pub(in crate::inspect::smp) fn derive_loaded_world_issue_37_state_from_probe(
    probe: &SmpSaveWorldIssue37Probe,
) -> SmpLoadedWorldIssue37State {
    SmpLoadedWorldIssue37State {
        source_kind: probe.source_kind.clone(),
        semantic_family: probe.semantic_family.clone(),
        issue_value: probe.issue_value_lane.raw_u32,
        issue_value_hex: probe.issue_value_lane.raw_u32_hex.clone(),
        issue_38_value: u32::from(probe.issue_38_raw_u8),
        issue_38_value_hex: probe.issue_38_raw_hex.clone(),
        issue_39_value: u32::from(probe.issue_39_raw_u8),
        issue_39_value_hex: probe.issue_39_raw_hex.clone(),
        issue_3a_value: u32::from(probe.issue_3a_raw_u8),
        issue_3a_value_hex: probe.issue_3a_raw_hex.clone(),
        multiplier_raw_u32: probe.multiplier_lane.raw_u32,
        multiplier_raw_hex: probe.multiplier_lane.raw_u32_hex.clone(),
        multiplier_value_f32_text: format!("{:.6}", probe.multiplier_lane.value_f32),
        issue_opinion_base_terms_raw_i32: probe.issue_opinion_base_terms_raw_i32.clone(),
    }
}

pub(in crate::inspect::smp) fn derive_loaded_world_economic_tuning_state_from_probe(
    probe: &SmpSaveWorldEconomicTuningProbe,
) -> SmpLoadedWorldEconomicTuningState {
    SmpLoadedWorldEconomicTuningState {
        source_kind: probe.source_kind.clone(),
        semantic_family: probe.semantic_family.clone(),
        mirror_raw_u32: probe.mirror_lane.raw_u32,
        mirror_raw_hex: probe.mirror_lane.raw_u32_hex.clone(),
        mirror_value_f32_text: format!("{:.6}", probe.mirror_lane.value_f32),
        lane_raw_u32: probe.tuning_lanes.iter().map(|lane| lane.raw_u32).collect(),
        lane_raw_hex: probe
            .tuning_lanes
            .iter()
            .map(|lane| lane.raw_u32_hex.clone())
            .collect(),
        lane_value_f32_text: probe
            .tuning_lanes
            .iter()
            .map(|lane| format!("{:.6}", lane.value_f32))
            .collect(),
    }
}

pub(in crate::inspect::smp) fn derive_loaded_world_finance_neighborhood_state_from_probe(
    probe: &SmpSaveWorldFinanceNeighborhoodProbe,
) -> SmpLoadedWorldFinanceNeighborhoodState {
    SmpLoadedWorldFinanceNeighborhoodState {
        source_kind: probe.source_kind.clone(),
        semantic_family: probe.semantic_family.clone(),
        packed_year_word_raw_u16: probe.packed_year_word_raw_u16,
        packed_year_word_raw_hex: probe.packed_year_word_raw_hex.clone(),
        partial_year_progress_raw_u8: probe.partial_year_progress_raw_u8,
        partial_year_progress_raw_hex: probe.partial_year_progress_raw_hex.clone(),
        current_calendar_tuple_word_raw_u32: probe.current_calendar_tuple_word_lane.raw_u32,
        current_calendar_tuple_word_raw_hex: probe
            .current_calendar_tuple_word_lane
            .raw_u32_hex
            .clone(),
        current_calendar_tuple_word_2_raw_u32: probe.current_calendar_tuple_word_2_lane.raw_u32,
        current_calendar_tuple_word_2_raw_hex: probe
            .current_calendar_tuple_word_2_lane
            .raw_u32_hex
            .clone(),
        absolute_counter_raw_u32: probe.absolute_counter_lane.raw_u32,
        absolute_counter_raw_hex: probe.absolute_counter_lane.raw_u32_hex.clone(),
        absolute_counter_mirror_raw_u32: probe.absolute_counter_mirror_lane.raw_u32,
        absolute_counter_mirror_raw_hex: probe.absolute_counter_mirror_lane.raw_u32_hex.clone(),
        stock_policy_raw_u8: probe.stock_policy_raw_u8,
        stock_policy_raw_hex: probe.stock_policy_raw_hex.clone(),
        bond_policy_raw_u8: probe.bond_policy_raw_u8,
        bond_policy_raw_hex: probe.bond_policy_raw_hex.clone(),
        bankruptcy_policy_raw_u8: probe.bankruptcy_policy_raw_u8,
        bankruptcy_policy_raw_hex: probe.bankruptcy_policy_raw_hex.clone(),
        dividend_policy_raw_u8: probe.dividend_policy_raw_u8,
        dividend_policy_raw_hex: probe.dividend_policy_raw_hex.clone(),
        building_density_growth_setting_raw_u32: probe.building_density_growth_setting_lane.raw_u32,
        building_density_growth_setting_raw_hex: probe
            .building_density_growth_setting_lane
            .raw_u32_hex
            .clone(),
        labels: probe
            .dword_candidates
            .iter()
            .map(|candidate| candidate.label.clone())
            .collect(),
        relative_offsets: probe
            .dword_candidates
            .iter()
            .map(|candidate| candidate.relative_offset)
            .collect(),
        relative_offset_hex: probe
            .dword_candidates
            .iter()
            .map(|candidate| candidate.relative_offset_hex.clone())
            .collect(),
        raw_u32: probe
            .dword_candidates
            .iter()
            .map(|candidate| candidate.raw_u32)
            .collect(),
        raw_hex: probe
            .dword_candidates
            .iter()
            .map(|candidate| candidate.raw_u32_hex.clone())
            .collect(),
        value_i32: probe
            .dword_candidates
            .iter()
            .map(|candidate| candidate.value_i32)
            .collect(),
        value_f32_text: probe
            .dword_candidates
            .iter()
            .map(|candidate| format!("{:.6}", candidate.value_f32))
            .collect(),
    }
}

pub(in crate::inspect::smp) fn derive_loaded_world_locomotive_policy_state_from_probes(
    post_text_probe: Option<&SmpPostTextFieldNeighborhoodProbe>,
    locomotive_policy_probe: Option<&SmpLocomotivePolicyNeighborhoodProbe>,
) -> Option<SmpLoadedWorldLocomotivePolicyState> {
    let field_by_name = |name: &str| {
        locomotive_policy_probe?
            .grounded_field_observations
            .iter()
            .find(|field| field.field_name == name)
    };
    let post_text_field_by_name = |name: &str| {
        post_text_probe?
            .grounded_field_observations
            .iter()
            .find(|field| field.field_name == name)
    };
    let selected_year_gap_scalar = field_by_name("selected-year bucket companion scalar");
    let linked_site_gate = field_by_name("linked-site removal follow-on gate");
    let auto_show_grade = post_text_field_by_name("Auto-Show Grade During Track Lay");
    let starting_building_density = post_text_field_by_name("Starting Building Density Level");
    let building_density_growth = post_text_field_by_name("Building Density Growth");
    let leftover_simulation_time = post_text_field_by_name("leftover simulation time accumulator");
    let selected_year_snapshot = post_text_field_by_name("selected-year lane snapshot");
    let all_steam = field_by_name("All Steam Locos Avail.");
    let all_diesel = field_by_name("All Diesel Locos Avail.");
    let all_electric = field_by_name("All Electric Locos Avail.");
    let cached_available_rating = field_by_name("cached available-locomotive rating");
    Some(SmpLoadedWorldLocomotivePolicyState {
        source_kind: locomotive_policy_probe
            .map(|probe| probe.source_kind.clone())
            .or_else(|| post_text_probe.map(|probe| probe.source_kind.clone()))?,
        semantic_family: "world-locomotive-policy".to_string(),
        selected_year_gap_scalar_raw_u32: selected_year_gap_scalar
            .and_then(|field| field.value_u32),
        selected_year_gap_scalar_raw_hex: selected_year_gap_scalar
            .and_then(|field| field.value_u32_hex.clone()),
        selected_year_gap_scalar_value_f32_text: selected_year_gap_scalar
            .and_then(|field| field.probable_f32_le.clone()),
        linked_site_removal_follow_on_gate_raw_u8: linked_site_gate
            .and_then(|field| field.value_u8),
        linked_site_removal_follow_on_gate_raw_hex: linked_site_gate
            .and_then(|field| field.value_u8_hex.clone()),
        auto_show_grade_during_track_lay_raw_u8: auto_show_grade.and_then(|field| field.value_u8),
        auto_show_grade_during_track_lay_raw_hex: auto_show_grade
            .and_then(|field| field.value_u8_hex.clone()),
        starting_building_density_level_raw_u8: starting_building_density
            .and_then(|field| field.value_u8),
        starting_building_density_level_raw_hex: starting_building_density
            .and_then(|field| field.value_u8_hex.clone()),
        building_density_growth_raw_u8: building_density_growth.and_then(|field| field.value_u8),
        building_density_growth_raw_hex: building_density_growth
            .and_then(|field| field.value_u8_hex.clone()),
        leftover_simulation_time_accumulator_raw_u32: leftover_simulation_time
            .and_then(|field| field.value_u32),
        leftover_simulation_time_accumulator_raw_hex: leftover_simulation_time
            .and_then(|field| field.value_u32_hex.clone()),
        leftover_simulation_time_accumulator_value_f32_text: leftover_simulation_time
            .and_then(|field| field.probable_f32_le.clone()),
        selected_year_lane_snapshot_raw_u8: selected_year_snapshot.and_then(|field| field.value_u8),
        selected_year_lane_snapshot_raw_hex: selected_year_snapshot
            .and_then(|field| field.value_u8_hex.clone()),
        all_steam_locomotives_available_raw_u8: all_steam.and_then(|field| field.value_u8),
        all_steam_locomotives_available_raw_hex: all_steam
            .and_then(|field| field.value_u8_hex.clone()),
        all_diesel_locomotives_available_raw_u8: all_diesel.and_then(|field| field.value_u8),
        all_diesel_locomotives_available_raw_hex: all_diesel
            .and_then(|field| field.value_u8_hex.clone()),
        all_electric_locomotives_available_raw_u8: all_electric.and_then(|field| field.value_u8),
        all_electric_locomotives_available_raw_hex: all_electric
            .and_then(|field| field.value_u8_hex.clone()),
        cached_available_locomotive_rating_raw_u32: cached_available_rating
            .and_then(|field| field.value_u32),
        cached_available_locomotive_rating_raw_hex: cached_available_rating
            .and_then(|field| field.value_u32_hex.clone()),
        cached_available_locomotive_rating_value_f32_text: cached_available_rating
            .and_then(|field| field.probable_f32_le.clone()),
    })
}
