use super::context_targets::{
    lower_condition_true_company_target_in_company_target,
    lower_condition_true_player_target_in_player_target,
};
use crate::documents::RuntimeImportBlocker;
use crate::event::effects::RuntimeEffect;
use crate::event::records::RuntimeEventRecordTemplate;
use crate::event::targets::{RuntimeCompanyTarget, RuntimePlayerTarget};

pub(crate) fn lower_condition_targets_in_effect(
    effect: &RuntimeEffect,
    lowered_company_target: Option<&RuntimeCompanyTarget>,
    lowered_player_target: Option<&RuntimePlayerTarget>,
) -> Result<RuntimeEffect, RuntimeImportBlocker> {
    Ok(match effect {
        RuntimeEffect::SetWorldFlag { key, value } => RuntimeEffect::SetWorldFlag {
            key: key.clone(),
            value: *value,
        },
        RuntimeEffect::SetWorldScalarOverride { key, value } => {
            RuntimeEffect::SetWorldScalarOverride {
                key: key.clone(),
                value: *value,
            }
        }
        RuntimeEffect::SetWorldVariable { index, value } => RuntimeEffect::SetWorldVariable {
            index: *index,
            value: *value,
        },
        RuntimeEffect::SetLimitedTrackBuildingAmount { value } => {
            RuntimeEffect::SetLimitedTrackBuildingAmount { value: *value }
        }
        RuntimeEffect::SetEconomicStatusCode { value } => {
            RuntimeEffect::SetEconomicStatusCode { value: *value }
        }
        RuntimeEffect::SetCompanyVariable {
            target,
            index,
            value,
        } => RuntimeEffect::SetCompanyVariable {
            target: lower_condition_true_company_target_in_company_target(
                target,
                lowered_company_target,
            )?,
            index: *index,
            value: *value,
        },
        RuntimeEffect::SetCompanyCash { target, value } => RuntimeEffect::SetCompanyCash {
            target: lower_condition_true_company_target_in_company_target(
                target,
                lowered_company_target,
            )?,
            value: *value,
        },
        RuntimeEffect::SetPlayerVariable {
            target,
            index,
            value,
        } => RuntimeEffect::SetPlayerVariable {
            target: lower_condition_true_player_target_in_player_target(
                target,
                lowered_player_target,
            )?,
            index: *index,
            value: *value,
        },
        RuntimeEffect::SetPlayerCash { target, value } => RuntimeEffect::SetPlayerCash {
            target: lower_condition_true_player_target_in_player_target(
                target,
                lowered_player_target,
            )?,
            value: *value,
        },
        RuntimeEffect::SetCompanyGovernanceScalar {
            target,
            metric,
            value,
        } => RuntimeEffect::SetCompanyGovernanceScalar {
            target: lower_condition_true_company_target_in_company_target(
                target,
                lowered_company_target,
            )?,
            metric: *metric,
            value: *value,
        },
        RuntimeEffect::SetChairmanCash { target, value } => RuntimeEffect::SetChairmanCash {
            target: target.clone(),
            value: *value,
        },
        RuntimeEffect::DeactivatePlayer { target } => RuntimeEffect::DeactivatePlayer {
            target: lower_condition_true_player_target_in_player_target(
                target,
                lowered_player_target,
            )?,
        },
        RuntimeEffect::DeactivateChairman { target } => RuntimeEffect::DeactivateChairman {
            target: target.clone(),
        },
        RuntimeEffect::SetCompanyTerritoryAccess {
            target,
            territory,
            value,
        } => RuntimeEffect::SetCompanyTerritoryAccess {
            target: lower_condition_true_company_target_in_company_target(
                target,
                lowered_company_target,
            )?,
            territory: territory.clone(),
            value: *value,
        },
        RuntimeEffect::ConfiscateCompanyAssets { target } => {
            RuntimeEffect::ConfiscateCompanyAssets {
                target: lower_condition_true_company_target_in_company_target(
                    target,
                    lowered_company_target,
                )?,
            }
        }
        RuntimeEffect::DeactivateCompany { target } => RuntimeEffect::DeactivateCompany {
            target: lower_condition_true_company_target_in_company_target(
                target,
                lowered_company_target,
            )?,
        },
        RuntimeEffect::SetCompanyTrackLayingCapacity { target, value } => {
            RuntimeEffect::SetCompanyTrackLayingCapacity {
                target: lower_condition_true_company_target_in_company_target(
                    target,
                    lowered_company_target,
                )?,
                value: *value,
            }
        }
        RuntimeEffect::RetireTrains {
            company_target,
            territory_target,
            locomotive_name,
        } => RuntimeEffect::RetireTrains {
            company_target: company_target
                .as_ref()
                .map(|target| {
                    lower_condition_true_company_target_in_company_target(
                        target,
                        lowered_company_target,
                    )
                })
                .transpose()?,
            territory_target: territory_target.clone(),
            locomotive_name: locomotive_name.clone(),
        },
        RuntimeEffect::AdjustCompanyCash { target, delta } => RuntimeEffect::AdjustCompanyCash {
            target: lower_condition_true_company_target_in_company_target(
                target,
                lowered_company_target,
            )?,
            delta: *delta,
        },
        RuntimeEffect::AdjustCompanyDebt { target, delta } => RuntimeEffect::AdjustCompanyDebt {
            target: lower_condition_true_company_target_in_company_target(
                target,
                lowered_company_target,
            )?,
            delta: *delta,
        },
        RuntimeEffect::SetCandidateAvailability { name, value } => {
            RuntimeEffect::SetCandidateAvailability {
                name: name.clone(),
                value: *value,
            }
        }
        RuntimeEffect::SetNamedLocomotiveAvailability { name, value } => {
            RuntimeEffect::SetNamedLocomotiveAvailability {
                name: name.clone(),
                value: *value,
            }
        }
        RuntimeEffect::SetNamedLocomotiveAvailabilityValue { name, value } => {
            RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
                name: name.clone(),
                value: *value,
            }
        }
        RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
            RuntimeEffect::SetNamedLocomotiveCost {
                name: name.clone(),
                value: *value,
            }
        }
        RuntimeEffect::SetCargoPriceOverride { target, value } => {
            RuntimeEffect::SetCargoPriceOverride {
                target: target.clone(),
                value: *value,
            }
        }
        RuntimeEffect::SetTerritoryVariable {
            target,
            index,
            value,
        } => RuntimeEffect::SetTerritoryVariable {
            target: target.clone(),
            index: *index,
            value: *value,
        },
        RuntimeEffect::SetCargoProductionOverride { target, value } => {
            RuntimeEffect::SetCargoProductionOverride {
                target: target.clone(),
                value: *value,
            }
        }
        RuntimeEffect::SetCargoProductionSlot { slot, value } => {
            RuntimeEffect::SetCargoProductionSlot {
                slot: *slot,
                value: *value,
            }
        }
        RuntimeEffect::SetTerritoryAccessCost { value } => {
            RuntimeEffect::SetTerritoryAccessCost { value: *value }
        }
        RuntimeEffect::SetSpecialCondition { label, value } => RuntimeEffect::SetSpecialCondition {
            label: label.clone(),
            value: *value,
        },
        RuntimeEffect::AppendEventRecord { record } => RuntimeEffect::AppendEventRecord {
            record: Box::new(RuntimeEventRecordTemplate {
                record_id: record.record_id,
                trigger_kind: record.trigger_kind,
                active: record.active,
                marks_collection_dirty: record.marks_collection_dirty,
                one_shot: record.one_shot,
                conditions: record.conditions.clone(),
                effects: record
                    .effects
                    .iter()
                    .map(|nested| {
                        lower_condition_targets_in_effect(
                            nested,
                            lowered_company_target,
                            lowered_player_target,
                        )
                    })
                    .collect::<Result<Vec<_>, _>>()?,
            }),
        },
        RuntimeEffect::ActivateEventRecord { record_id } => RuntimeEffect::ActivateEventRecord {
            record_id: *record_id,
        },
        RuntimeEffect::DeactivateEventRecord { record_id } => {
            RuntimeEffect::DeactivateEventRecord {
                record_id: *record_id,
            }
        }
        RuntimeEffect::RemoveEventRecord { record_id } => RuntimeEffect::RemoveEventRecord {
            record_id: *record_id,
        },
    })
}
