package me.msoucy.ptures.model

import com.badlogic.gdx.math.MathUtils.random

data class SkillChoice (val skill : Skill, val target : List<Creature>)

@DslMarker
annotation class SkillMarker

enum class Target {
    Selected,
    Self,
    Others,
    Opponents,
    All
}

enum class Attribute {
    Neutral,
    Stone,
    Fire,
    Water,
    Air,
    Wood
}

class Damage(val power: Int, val attribute: Attribute = Attribute.Neutral) {
    var target = Target.Selected
    var accuracy = 100

    var status: () -> Status? = { null }
    var statusChance = 0

    fun applyStatus(creature: Creature) {
        val appStatus = status()
        if (appStatus != null && random(100) < statusChance) {
            creature.addStatus(appStatus)
        }
    }
}

class StatusApplier(val target: Target, val apply: (Creature) -> Unit)

@SkillMarker
open class Skill(open val name: String, val attribute: Attribute) {
    val damageSteps = mutableListOf<Damage>()
    val postSteps = mutableListOf<StatusApplier>()

    fun damage(power: Int, block: Damage.() -> Unit = {}) {
        val d = Damage(power, attribute)
        d.block()
        damageSteps.add(d)
    }

    fun addStatus(status: Status, target: Target = Target.Selected) {
        postSteps.add(StatusApplier(target) { c -> c.addStatus(status) })
    }

    fun removeStatus(status: Status, target: Target = Target.Selected) {
        postSteps.add(StatusApplier(target) { c -> c.removeStatus(status) })
    }

    // Assume that the first damage step is the one that provides the target
    val target: Target
        get() = if (damageSteps.isNotEmpty()) {
            damageSteps[0].target
        } else {
            Target.Self
        }
}

class AdvancedSkill(name: String, attribute: Attribute) : Skill(name, attribute) {
    override val name: String get() = super.name + "+"
    val baseName: String get() = super.name
}

fun skill(name: String, attribute: Attribute = Attribute.Neutral, block: Skill.() -> Unit): Skill {
    val ret = Skill(name, attribute)
    ret.block()
    return ret
}

object Skills {

    val Ignore = skill("Ignore") {
    }

    val Tackle = skill("Tackle") {
        damage(20)
    }

    val DoubleKick = skill("Double Kick") {
        repeat(2) {
            damage(35) {
                accuracy = 85
            }
        }
    }

    val DoubleEdge = skill("Double Edge") {
        damage(80)
        damage(15) {
            target = Target.Self
        }
    }

    val Fly = skill("Fly") {
        addStatus(Flying(), Target.Self)
    }
    val Fly2 = skill("Fly", Attribute.Air) {
        damage(60)
    }

    val Ember = skill("Ember", Attribute.Fire) {
        damage(40) {
            status = { Burned }
            statusChance = 10
        }
    }
}