package me.msoucy.ptures.model

class Engine(private vararg val creatures : Pair<Creature, Int>) {
    init {
        assert(creatures.isNotEmpty())
    }

    private var currentCreature = 0

    val attacker : Creature get() {
        return creatures[currentCreature].first
    }

    fun resolveTurn() {
        val activeCreatures = creatures.withIndex()
                .filter { (_, c) -> !c.first.hasStatus<KnockedOut>() }
                .sortedBy { (_, c) -> c.first.spd }
        // Get the moves each creature will use this turn
        val moves = activeCreatures.map { (_, c) -> Pair(c.first.skills[0], 0) }
        val wasHit = mutableListOf<Pair<Creature, Int>>()
        for ((i, c) in activeCreatures) {
            // Resolve move
            val (skill, target) = moves[i]
            currentCreature = i
            for (step in skill.damageSteps) {
                val targets = getTargetList(step.target, target)
                for (t in targets) {
                    val (targetCreature, _) = creatures[t]
                    if (attacker.hits(targetCreature, step)) {
                        targetCreature.apply(step, c.first)
                        if (wasHit.any { it.first == targetCreature }) {
                            wasHit.add(Pair(targetCreature, t))
                        }
                    }
                }
            }
            for(step in skill.statusSteps) {
                for ((targetCreature, t) in wasHit) {
                    if (t in getTargetList(step.target, t)) {
                        step.applier(targetCreature)
                    }
                }
            }
        }
    }

    private fun getTargetList(target : Target, selected : Int) : List<Int> {
        return when(target) {
            Target.Self -> listOf(currentCreature)
            Target.Selected -> listOf(selected)
            Target.Others -> creatures.indices.filter { it != currentCreature }
            Target.Opponents -> creatures.indices.filter { creatures[it].second != creatures[currentCreature].second }
            Target.All -> creatures.indices.toList()
        }
    }
}