import {LiturgyData} from "../data/miracle/liturgyData.mjs";
import {Talent} from "../data/talent.mjs";
import {evaluateRoll} from "../globals/DSARoll.mjs";

const {
    ApplicationV2, 
    HandlebarsApplicationMixin
} = foundry.applications.api

export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {

    static DEFAULT_OPTIONS = {
        classes: ['dsa41', 'dialog', 'liturgy'],
        tag: "form",
        position: {
            width: 480,
            height: 800
        },
        window: {
            resizable: false,
            title: "Liturgie wirken"
        },
        form: {
            submitOnChange: true,
            closeOnSubmit: false,
            handler: LiturgyDialog.#onSubmitForm
        },
        actions: {
            selectVariant: LiturgyDialog.#selectVariant,
            addMod: LiturgyDialog.#addModification,
            removeMod: LiturgyDialog.#removeModification,
            castLiturgy: LiturgyDialog.#castLiturgy,
        }
    }


    static PARTS = {
        form: {
            template: 'systems/DSA_4-1/templates/dialog/liturgy-dialog.hbs',
        }
    }

    static data = {}
    static naming = {
        "range": "Reichweite",
        "strength": "Wirkung",
        "target": "Ziele",
        "castduration": "Wirkzeit",
        "duration": "Wirkdauer"
    }
    static #romanNumerals = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"]
    /**
     *
     * @type {Actor}
     * @private
     */
    _actor = null

    constructor(actor, liturgyValue, liturgyId, deity) {
        super()
        this._actor = actor
        this._liturgy = this._actor.itemTypes["Liturgy"].find(p => p._id === liturgyId)
        this._deity = deity
        this._maxmods = Math.round(liturgyValue / 3)
        this._variations = []
        Object.entries(this._liturgy.system.auswirkung).forEach(([rank, text]) => {

            if (text) {
                this._variations.push({
                    level: LiturgyDialog.#romanNumerals.findIndex(p => p === rank) + 1,
                    rank: rank,
                    effect: text
                })
            }

        })
        this._variation = this._variations[0]
        this._mods = []
        this._blessing = this._actor.itemTypes["Blessing"].find(p => p.system.gottheit === this._deity)
        this._initialRank = 0
        this._circumstance = 0
    }

    static async #onSubmitForm(event, form, formData) {
        event.preventDefault()

        this._circumstance = formData.object["circumstance"]
        this.render({parts: ["form"]})
    }

    static #selectVariant(event, target) {
        if (target.checked) {
            this._variation = this._variations.find(p => p.rank === target.dataset['rank']);
            this._mods = [];
        }
        this.render({parts: ["form"]})
        event.stopPropagation()
        event.preventDefault()
        return false
    }

    static #addModification(event, target) {
        event.stopPropagation()
        event.preventDefault()
        if (game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien")) {
            const value = this.element.querySelector('select[name="mod"]').value

            if (value === '') return
            const currentRank = this._mods.length + (this._variation?.level ?? 0)
            this._mods.push({
                rank: currentRank,
                displayRank: LiturgyDialog.#romanNumerals.findIndex(p => p === currentRank),
                mod: value,
            })
            this.render({parts: ["form"]})
        }
        return false
    }

    static #removeModification(event, target) {
        event.stopPropagation()
        event.preventDefault()
        if (game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien")) {
            const {index} = target.dataset
            this._mods.splice(index, 1)
            this.render({parts: ["form"]})
        }
        return false
    }

    static async #castLiturgy(event, target) {

        const lkp = context.lkp = this._blessing.system.wert
        const resultingLiturgy = this.#getLiturgyData()
        const circumstance = this._circumstance

        const mod = 0 + lkp + resultingLiturgy.castPenalty - circumstance

        const castingTime = this.#normalizeCastingTime(this._liturgy)

        if (castingTime > 0) {
            const cooldowns = this._actor.system.cooldowns
            let m = (queue, data) => {

                new game.DSA41.Talent({
                    name: data.title,
                    taw: data.taw,
                    mod: data.mod,
                    owner: data.actor,
                    eigenschaften: {
                        mu: data.eigenschaften.mu,
                        in: data.eigenschaften.in,
                        ch: data.eigenschaften.ch,
                    },
                    eigenschaft1: "mu",
                    eigenschaft2: "in",
                    eigenschaft3: "ch"
                }).evaluate("publicroll").then(result => {
                    const context = {
                        ...data,
                        liturgy: data.title,
                        lkw: data.taw,
                        mod: data.mod,
                        owner: data.actor,
                        lkp: result.tap,
                        meisterlich: result.meisterlich,
                        patzer: result.patzer
                    }

                    if(result.tap>0) {
                        context.remaining = Math.abs(result.tap)
                    } else if (result.tap===0) {
                        context.remaining = 1
                    } else {
                        context.missing = Math.abs(result.tap)
                    }
                    game.DSA41.displayRoll(
                        result.evaluated,
                        game.user,
                        data.actor,
                        false,
                        false,
                        'systems/DSA_4-1/templates/chat/liturgy-chat-message.hbs',
                        context
                    )

                })
            }

            let currentCooldown = 0
            if (game.combats.size === 0) { // no combat started
                currentCooldown = castingTime
            }
            cooldowns.push({
                start: castingTime,
                current: currentCooldown,
                data: {
                    cssClass: "Karmal",
                    title: this._liturgy.name,
                    taw: lkp,
                    mod: mod,
                    owner: this._actor._id,
                    actorId: this._actor._id,
                    variant: this._variation.effect,
                    eigenschaften: {
                        mu: this._actor.system.attribute.mu.aktuell,
                        in: this._actor.system.attribute.in.aktuell,
                        ch: this._actor.system.attribute.ch.aktuell,
                    },
                    eigenschaft1: "mu",
                    eigenschaft2: "in",
                    eigenschaft3: "ch",
                    circumstance: circumstance,
                    castingTime: castingTime,
                    maneuver: m.toString()
                }

            })
            await this._actor.update({"system.cooldowns": cooldowns})
            ui.notifications.info(`Neue Aktion für ${this._liturgy.name} mit Abklingzeit von ${castingTime} Aktionen hinzugefügt`);
        } else {
        const result = await new Talent({
            name: this._liturgy.name,
            taw: lkp,
            mod: mod,
            eigenschaften: {
                mu: this._actor.system.attribute.mu.aktuell,
                in: this._actor.system.attribute.in.aktuell,
                ch: this._actor.system.attribute.ch.aktuell,
            },
            eigenschaft1: "mu",
            eigenschaft2: "in",
            eigenschaft3: "ch"
        }).evaluate("publicroll")

        result.evaluatedRoll.toMessage({
            speaker: ChatMessage.getSpeaker({actor: this._actor}),
            flavor: `Liturgie: ${this._liturgy.name}<br/>Zauberdauer: ${castingTime > 0 ? castingTime + " Aktionen" : resultingLiturgy.castduration}<br/>LkP*: ${result.tap}<br/>${result.meisterlich ? "Meisterlich" : ""}${result.patzer ? "Petzer" : ""}<br/>${this._variation.effect}`,
        })
        }

        this.close()
    }

    #normalizeCastingTime(liturgy) {

        const castingTime = liturgy.system.zauberdauer

        // direct actions
        const stoßgebetRegExp = /(.*) Aktionen \(Stoßgebet\)/
        const gebetRegExp = /(.*) Spielrunden? \(Gebet\)/
        const invalidForCooldownRegExp = /Andacht|Zeremonie|Zyklus/

        if (castingTime.match(stoßgebetRegExp)) {
            const [_, actions] = castingTime.match(stoßgebetRegExp)
            return actions
        } else if (castingTime.match(gebetRegExp)) {
            const [_, actions] = castingTime.match(gebetRegExp)
            return actions * 20
        } else if (castingTime.match(invalidForCooldownRegExp)) {
            return -1
        }
        return -1
    }

    _configureRenderOptions(options) {
        super._configureRenderOptions(options)

        if (options.window) {
            if (this._liturgy) {
                options.window.title = `${this._liturgy.name} wirken`
            }
            if (game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien")) {
                options.position.height = 800
            } else {
                options.position.height = 640
            }
        }


        return options
    }

    #getLiturgyData() {

        let baseline = this._liturgy.system

        baseline.name = this._liturgy.name

        if (game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien")) {


            let upgradeDuration = false
            let upgradeCastDuration = false
            let upgradeStrength = false

            this._mods.forEach(({mod}) => {
                switch (mod) {
                    case "range":
                        break;
                    case "strength":
                        upgradeStrength = true
                        break;
                    case "target":
                        break;
                    case "castduration":
                        upgradeCastDuration = true
                        break;
                    case "duration":
                        upgradeDuration = true
                        break;
                }
            })

            baseline.effectiveLevel = (this._variation?.level ?? 0) + this._mods.length
            baseline.costKaP = LiturgyData.getModifiedRank(baseline.effectiveLevel).costKaP
            baseline.costKaPPermanent = LiturgyData.getModifiedRank(baseline.effectiveLevel).costKaPPermanent
            //baseline.mod = LiturgyData.getModifiedRank(baseline.effectiveLevel).mod
            baseline.rank = LiturgyData.getModifiedRank(baseline.effectiveLevel).name

            // estimate duration rank


            // insert mods into text
            baseline.text = this._variation.effect

            const strengthRegexp = /(LkP\*.*?)[ .]/g

            //baseline.text = baseline.text.replace(strengthRegexp, LiturgyData.getModifiedRank((baseline.effectiveLevel ?? 0) + upgradeStrength).strength)

            const durationRegexp = /(LkP\*?.*?)(\*10 KR| Stunden| Tage| Wochen| Monate| Jahre oder permanent)/g

            const effectiveDuration = LiturgyData.getModifiedDuration(baseline.duration, upgradeDuration + upgradeStrength)

            baseline.duration = baseline.duration.replace(effectiveDuration.durationText, effectiveDuration.adjustedDurationText)
        } else {
            baseline.rank = this._variation.rank
            baseline.text = this._variation.effect
            baseline.target = baseline.ziel
            baseline.duration = baseline.wirkungsdauer
            baseline.castduration = baseline.zauberdauer
            baseline.costKaP = LiturgyData.getModifiedRank(this._variation.level).costKaP
            baseline.costKaPPermanent = LiturgyData.getModifiedRank(this._variation.level).costKaPPermanent


            if (this._variation.level > this._liturgy.system.herkunft.find(p => p.name === this._deity).grad) {
                baseline.castPenalty = LiturgyData.getModifiedRank(this._liturgy.system.herkunft.find(p => p.name === this._deity).grad).mod
            } else {
                baseline.castPenalty = LiturgyData.getModifiedRank(this._variation.level).mod
            }

        }
        return baseline

    }

    async _prepareContext(options) {
        const context = await super._prepareContext(options)
        context.actor = this._actor
        context.liturgy = this._liturgy
        context.mods = this._mods
        context.variation = this._variation
        context.maxmods = this._maxmods
        context.variations = this._variations
        context.colorfulDice = game.settings.get('DSA_4-1', 'optional_colorfuldice')
        context.mu = {wert: this._actor.system.attribute.mu.aktuell, name: "MU", tooltip: "Mut"}
        context.in = {wert: this._actor.system.attribute.in.aktuell, name: "IN", tooltip: "Intuition"}
        context.ch = {wert: this._actor.system.attribute.ch.aktuell, name: "CH", tooltip: "Charisma"}
        context.moddingEnabled = game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien")
        context.canMod = game.settings.get("DSA_4-1", "optional_aufstufen_von_liturgien") && (this._maxmods - (this._variation?.level ?? 0) - this._mods.length) >= 0
        context.addingModRank = LiturgyDialog.#romanNumerals[(context._variation?.level ?? 0) + this._mods.length + 1]
        context.lkp = this._blessing.system.wert
        context.deity = this._blessing.system.name
        context.resultingLiturgy = this.#getLiturgyData()
        context.resultingCastPenalty = 0
        context.circumstance = this._circumstance
        if (context.resultingLiturgy.castPenalty > 0) {
            context.resultingCastPenalty = `+${context.resultingLiturgy.castPenalty}`
        } else {
            context.resultingCastPenalty = context.resultingLiturgy.castPenalty
        }

        context.modResult = 0 + context.lkp + context.resultingLiturgy.castPenalty - this._circumstance

        context.displayModResult = context.modResult > 0 ? "+" + context.modResult : context.modResult

        return context
    }
}