use crate::derived::{
    runtime_decode_packed_calendar_tuple, runtime_selected_year_bucket_bands_from_scalar,
    runtime_world_selected_year_bucket_scalar_from_year_word,
    runtime_world_selected_year_gap_scalar_from_year_word,
};
use crate::state::RuntimeState;

impl RuntimeState {
    pub fn refresh_derived_world_state(&mut self) {
        self.world_restore
            .linked_site_removal_follow_on_gate_enabled = self
            .world_restore
            .linked_site_removal_follow_on_gate_raw_u8
            .map(|raw| raw != 0);
        self.world_restore.all_steam_locomotives_available_enabled = self
            .world_restore
            .all_steam_locomotives_available_raw_u8
            .map(|raw| raw != 0);
        self.world_restore.all_diesel_locomotives_available_enabled = self
            .world_restore
            .all_diesel_locomotives_available_raw_u8
            .map(|raw| raw != 0);
        self.world_restore
            .all_electric_locomotives_available_enabled = self
            .world_restore
            .all_electric_locomotives_available_raw_u8
            .map(|raw| raw != 0);
        if let Some(&lane_0_raw_u32) = self.world_restore.economic_tuning_lane_raw_u32.first() {
            self.world_restore.economic_tuning_mirror_raw_u32 = Some(lane_0_raw_u32);
            self.world_restore.economic_tuning_mirror_value_f32_text =
                Some(format!("{:.6}", f32::from_bits(lane_0_raw_u32)));
        }
        let year_word = self
            .world_restore
            .packed_year_word_raw_u16
            .map(u32::from)
            .or_else(|| {
                self.world_restore
                    .current_calendar_tuple_word_raw_u32
                    .zip(self.world_restore.current_calendar_tuple_word_2_raw_u32)
                    .map(|(word_0, word_1)| {
                        u32::from(runtime_decode_packed_calendar_tuple(word_0, word_1).year_word)
                    })
            })
            .unwrap_or(self.calendar.year);
        if let Some(value) = runtime_world_selected_year_bucket_scalar_from_year_word(year_word) {
            self.world_restore.selected_year_bucket_scalar_raw_u32 = Some(value.to_bits());
            self.world_restore
                .selected_year_bucket_scalar_value_f32_text = Some(format!("{value:.6}"));
            if let Some(bands) = runtime_selected_year_bucket_bands_from_scalar(value) {
                self.world_restore.selected_year_bucket_direct_lane_raw_u32 =
                    bands.direct.iter().map(|lane| lane.to_bits()).collect();
                self.world_restore
                    .selected_year_bucket_direct_lane_value_f32_text = bands
                    .direct
                    .iter()
                    .map(|lane| format!("{lane:.6}"))
                    .collect();
                self.world_restore
                    .selected_year_bucket_complement_lane_raw_u32 =
                    bands.complement.iter().map(|lane| lane.to_bits()).collect();
                self.world_restore
                    .selected_year_bucket_complement_lane_value_f32_text = bands
                    .complement
                    .iter()
                    .map(|lane| format!("{lane:.6}"))
                    .collect();
                self.world_restore
                    .selected_year_bucket_scaled_companion_lane_raw_u32 = bands
                    .scaled_companion
                    .iter()
                    .map(|lane| lane.to_bits())
                    .collect();
                self.world_restore
                    .selected_year_bucket_scaled_companion_lane_value_f32_text = bands
                    .scaled_companion
                    .iter()
                    .map(|lane| format!("{lane:.6}"))
                    .collect();
            }
        }
        if let Some(value) = runtime_world_selected_year_gap_scalar_from_year_word(year_word) {
            self.world_restore.selected_year_gap_scalar_raw_u32 = Some(value.to_bits());
            self.world_restore.selected_year_gap_scalar_value_f32_text =
                Some(format!("{value:.6}"));
        }
        for (key, value) in [
            (
                "world.all_steam_locos_available",
                self.world_restore.all_steam_locomotives_available_enabled,
            ),
            (
                "world.all_diesel_locos_available",
                self.world_restore.all_diesel_locomotives_available_enabled,
            ),
            (
                "world.all_electric_locos_available",
                self.world_restore
                    .all_electric_locomotives_available_enabled,
            ),
        ] {
            if let Some(enabled) = value {
                self.world_flags.insert(key.to_string(), enabled);
            } else {
                self.world_flags.remove(key);
            }
        }
    }
}
