DefaultMutationApplier.kt

package io.github.lishangbu.avalon.game.battle.engine.core.runtime.apply

import io.github.lishangbu.avalon.game.battle.engine.core.event.StandardHookNames
import io.github.lishangbu.avalon.game.battle.engine.core.model.FieldState
import io.github.lishangbu.avalon.game.battle.engine.core.model.SideState
import io.github.lishangbu.avalon.game.battle.engine.core.model.UnitState
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.AddVolatileMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ApplyConditionMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ApplyFieldConditionMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ApplySideConditionMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.BattleMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.BoostMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ChangeTypeMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ClearBoostsMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ClearProbeMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ClearTerrainMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ClearWeatherMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ConsumeItemMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.DamageMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ForceSwitchMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.HealMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.RemoveConditionMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.RemoveFieldConditionMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.RemoveSideConditionMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.RemoveStatusMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.RemoveVolatileMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.RestorePpMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.SetBoostsMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.SetProbeMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.SetStatusMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.SetSwitchBoostCarryMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.SetTerrainMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.SetWeatherMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.TriggerEventMutation

/**
 * 默认 mutation 应用器。
 *
 * 设计意图:
 * - 以不可变回写方式提交 mutation;
 * - 自身只负责 mutation 类型分发与 triggered hook 聚合;
 * - 具体 unit / side / field 写回细节交给独立 helper,避免继续堆成超大文件。
 */
class DefaultMutationApplier : MutationApplier {
    override fun apply(
        mutations: List<BattleMutation>,
        context: MutationApplicationContext,
    ): MutationApplicationResult {
        var currentUnits: Map<String, UnitState> = context.units
        var currentField: FieldState = context.field
        var currentSides: Map<String, SideState> = context.sides
        val triggeredHooks = mutableListOf<io.github.lishangbu.avalon.game.battle.engine.core.type.HookName>()

        for (mutation in mutations) {
            when (mutation) {
                is DamageMutation -> {
                    currentUnits = UnitMutationStateApplier.applyDamage(mutation, context, currentUnits)
                }

                is HealMutation -> {
                    currentUnits = UnitMutationStateApplier.applyHeal(mutation, context, currentUnits)
                }

                is SetStatusMutation -> {
                    currentUnits = UnitMutationStateApplier.applySetStatus(mutation, context, currentUnits)
                }

                is RemoveStatusMutation -> {
                    currentUnits = UnitMutationStateApplier.applyRemoveStatus(mutation, context, currentUnits)
                }

                is AddVolatileMutation -> {
                    currentUnits = UnitMutationStateApplier.applyAddVolatile(mutation, context, currentUnits)
                }

                is RemoveVolatileMutation -> {
                    currentUnits = UnitMutationStateApplier.applyRemoveVolatile(mutation, context, currentUnits)
                }

                is BoostMutation -> {
                    currentUnits = UnitMutationStateApplier.applyBoost(mutation, context, currentUnits)
                }

                is ClearBoostsMutation -> {
                    currentUnits = UnitMutationStateApplier.applyClearBoosts(mutation, context, currentUnits)
                }

                is SetBoostsMutation -> {
                    currentUnits = UnitMutationStateApplier.applySetBoosts(mutation, context, currentUnits)
                }

                is SetWeatherMutation -> {
                    currentField = FieldMutationStateApplier.applySetWeather(mutation, currentField)
                    triggeredHooks += StandardHookNames.ON_WEATHER_CHANGE
                }

                is ClearWeatherMutation -> {
                    currentField = currentField.copy(weatherState = null)
                    triggeredHooks += StandardHookNames.ON_WEATHER_CHANGE
                }

                is SetTerrainMutation -> {
                    currentField = FieldMutationStateApplier.applySetTerrain(mutation, currentField)
                    triggeredHooks += StandardHookNames.ON_TERRAIN_CHANGE
                }

                is ClearTerrainMutation -> {
                    currentField = currentField.copy(terrainState = null)
                    triggeredHooks += StandardHookNames.ON_TERRAIN_CHANGE
                }

                is ConsumeItemMutation -> {
                    currentUnits = UnitMutationStateApplier.applyConsumeItem(mutation, context, currentUnits)
                }

                is RestorePpMutation -> {
                    currentUnits = UnitMutationStateApplier.applyRestorePp(mutation, context, currentUnits)
                }

                is ChangeTypeMutation -> {
                    currentUnits = UnitMutationStateApplier.applyChangeType(mutation, context, currentUnits)
                }

                is ForceSwitchMutation -> {
                    currentUnits = UnitMutationStateApplier.applyForceSwitch(mutation, context, currentUnits)
                }

                is SetSwitchBoostCarryMutation -> {
                    currentUnits = UnitMutationStateApplier.applySetSwitchBoostCarry(mutation, context, currentUnits)
                }

                is ApplyConditionMutation -> {
                    currentUnits = UnitMutationStateApplier.applyAddCondition(mutation, context, currentUnits)
                }

                is ApplySideConditionMutation -> {
                    currentSides = SideMutationStateApplier.applyAddSideCondition(mutation, context, currentSides)
                }

                is ApplyFieldConditionMutation -> {
                    currentField = FieldMutationStateApplier.applyAddCondition(mutation, currentField)
                }

                is RemoveConditionMutation -> {
                    currentUnits = UnitMutationStateApplier.applyRemoveCondition(mutation, context, currentUnits)
                }

                is RemoveSideConditionMutation -> {
                    currentSides = SideMutationStateApplier.applyRemoveSideCondition(mutation, context, currentSides)
                }

                is RemoveFieldConditionMutation -> {
                    currentField = FieldMutationStateApplier.applyRemoveCondition(mutation, currentField)
                }

                is SetProbeMutation -> {
                    currentUnits = UnitMutationStateApplier.applySetProbe(mutation, context, currentUnits)
                }

                is ClearProbeMutation -> {
                    currentUnits = UnitMutationStateApplier.applyClearProbe(mutation, context, currentUnits)
                }

                is TriggerEventMutation -> {
                    triggeredHooks += mutation.hookName
                }
            }
        }

        return MutationApplicationResult(
            battle = context.battle,
            field = currentField,
            units = currentUnits,
            sides = currentSides,
            triggeredHooks = triggeredHooks,
        )
    }
}