FieldMutationStateApplier.kt

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

import io.github.lishangbu.avalon.game.battle.engine.core.model.AttachedEffectState
import io.github.lishangbu.avalon.game.battle.engine.core.model.FieldState
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.ApplyFieldConditionMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.RemoveFieldConditionMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.SetTerrainMutation
import io.github.lishangbu.avalon.game.battle.engine.core.mutation.SetWeatherMutation

/**
 * field 级 mutation 写回助手。
 */
internal object FieldMutationStateApplier {
    fun applySetWeather(
        mutation: SetWeatherMutation,
        field: FieldState,
    ): FieldState {
        val nextOrder = field.weatherState?.effectOrder ?: 1
        return field.copy(
            weatherState =
                AttachedEffectState(
                    effectId = mutation.weatherEffectId,
                    sourceId = mutation.sourceId,
                    duration = mutation.duration,
                    effectOrder = nextOrder,
                ),
        )
    }

    fun applySetTerrain(
        mutation: SetTerrainMutation,
        field: FieldState,
    ): FieldState {
        val nextOrder = field.terrainState?.effectOrder ?: 1
        return field.copy(
            terrainState =
                AttachedEffectState(
                    effectId = mutation.terrainEffectId,
                    sourceId = mutation.sourceId,
                    duration = mutation.duration,
                    effectOrder = nextOrder,
                ),
        )
    }

    fun applyAddCondition(
        mutation: ApplyFieldConditionMutation,
        field: FieldState,
    ): FieldState {
        val existingState = field.conditionStates[mutation.conditionEffectId]
        val nextOrder =
            existingState?.effectOrder
                ?: ((field.conditionStates.values.maxOfOrNull(AttachedEffectState::effectOrder) ?: 0) + 1)
        val nextState =
            AttachedEffectState(
                effectId = mutation.conditionEffectId,
                sourceId = mutation.sourceId,
                duration = mutation.duration,
                effectOrder = nextOrder,
            )
        return field.copy(
            conditionStates = field.conditionStates + (mutation.conditionEffectId to nextState),
        )
    }

    fun applyRemoveCondition(
        mutation: RemoveFieldConditionMutation,
        field: FieldState,
    ): FieldState = field.copy(conditionStates = field.conditionStates - mutation.conditionEffectId)
}