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

export class RestingDialog extends HandlebarsApplicationMixin(ApplicationV2) {

    static DEFAULT_OPTIONS = {
        classes: ['dsa41', 'dialog', 'resting'],
        tag: "form",
        position: {
            width: 480,
            height: 800
        },
        window: {
            resizable: false,
            title: "Rasten und Regenerieren"
        },
        form: {
            submitOnChange: true,
            closeOnSubmit: false,
            handler: RestingDialog.#onSubmitForm
        },
        actions: {
            regenerate: RestingDialog.#regenerate
        }
    }

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

    /**
     * @type {Character}
     * @private
     */
    _actor = null

    /**
     * @typedef RestingCircumstance
     * @property {String} name Displaytext of this circumstance modifier
     * @property {Number|[Number]} aspMod modifier to AsP regeneration
     * @property {Number|[Number]} lepMod modifier to LeP regeneration
     * @property {Boolean|Number} active indicates if this modifier is active and or which index of aspMod/lepMod to be used
     */

    /**
     * @typedef RestingOptions
     * @property {Number} length the time of this rest, will be used for reducing exhaustion and overexertion
     * @property {Number} wounds the amount of wounds the actor has suffered
     * @property {Number|Boolean} treated if the wounds have been treated with the Skill "Heilkunde: Wunden" the Value is the Modificator for the wound regeneration
     * @property {RestingCircumstance} circumstances the circumstances of this Rest
     */

    #type = {
        DRAUßEN: "draußen",
        SCHLAFSAAL: "schlafsaal",
        EINZELZIMMER: "einzelzimmer",
        SUITE: "suite",
    }

    /**
     * @type {[RestingCircumstance]}
     * @private
     */
    #circumstances = [
        {
            name: "Ruhestörung",
            display: "boolean",
            lepMod: -1,
            aspMod: -1,
            group: "interrupted",
            active: false,
            value: "on"
        },
        {
            name: "Wache gehalten",
            display: "boolean",
            lepMod: -1,
            aspMod: -1,
            group: "watch",
            active: false,
            value: "on"
        },
        {
            name: "Unter freiem Himmel",
            display: "radio",
            aspMod: 0,
            lepMod: 0,
            active: false,
            value: this.#type.DRAUßEN,
            group: "type"
        },
        {
            name: "Schlechtes Wetter",
            aspMod: [-1, -2, -3, -4, -5],
            lepMod: [-1, -2, -3, -4, -5],
            display: "range",
            noLabel: "Gutes Wetter",
            nestingLevel: 1,
            labels: [
                "Schlechtes Wetter I",
                "Schlechtes Wetter II",
                "Schlechtes Wetter III",
                "Schlechtes Wetter IV",
                "Schlechtes Wetter V",
            ],
            group: "bad_weather",
            active: -1,
        },
        {
            name: "Schlechter Lagerplatz",
            aspMod: -1,
            lepMod: -1,
            display: "boolean",
            nestingLevel: 1,
            group: "bad_camp",
            active: false,
            value: "on"
        },
        {
            name: "Magere Lagerstätte (Schlafsaal, Heuboden)",
            aspMod: 0,
            lepMod: 0,
            display: "radio",
            group: "type",
            value: this.#type.SCHLAFSAAL,
            active: false,
        },
        {
            name: "Komfortable Schlafstätte",
            aspMod: 1,
            lepMod: 1,
            display: "radio",
            group: "type",
            value: this.#type.EINZELZIMMER,
            active: false,
        },
        {
            name: "Luxuriöse Schlafstätte (Suite)",
            aspMod: 2,
            lepMod: 2,
            display: "radio",
            group: "type",
            value: this.#type.SUITE,
            active: false,
        }

    ]


    constructor(actor) {
        super();
        this._actor = actor;
        this.restDuration = 6
        this.restingType = this.#circumstances.find(p => p.value === this.#type.DRAUßEN)
        this.badWeather = -1
        this.woundTreated = false
        this.woundRegenerationModifier = 0
        this.wounds = this._actor.getWoundModel().current
        this.badCamp = false
        this.watch = false
        this.interrupted = false

        this.lepModifier = this._actor.system.regeneration.lep.split("d6")[1]
        this.aspModifier = this._actor.system.regeneration.asp.split("d6")[1]


        this.regKoMod = this._actor.system.regeneration.ko
        this.regInMod = this._actor.system.regeneration.in


    }

    static async #regenerate() {
        const context = this.#updateData()
        const rollData = this._actor.system

        // regenerate LeP

        const targetBonusLep = rollData.attribute.ko.aktuell + context.koRoll
        const targetBonusAsp = rollData.attribute.in.aktuell + context.inRoll

        // TODO: needs to be situational (not every character has AsP for example) and not a compound roll statement
        const regenerationRoll = await new Roll("1d20[Konstitution]+1d20[Intuition]+1d20[Konstitution] + 2d6").evaluate()

        const [koRoll, _, inRoll, __, woundRoll, ___, lepAndAsp] = regenerationRoll.terms // the 3d20s
        const plusLep = koRoll.results[0].result <= targetBonusLep ? 1 : 0
        const plusAsp = inRoll.results[0].result <= targetBonusAsp ? 1 : 0
        const woundHealed = woundRoll.results[0].result <= rollData.attribute.ko.aktuell + (context.woundMod * -1)
        const [regLep, regAsp] = lepAndAsp.results // the 2d6s

        // TODO: message needs to be better structured, and also include Buttons to heal LeP and restore AsP
        await regenerationRoll.toMessage({
            speaker: ChatMessage.getSpeaker({actor: this.actor}),
            flavor:
                `Regeneration in der Nacht:<br/>
 LE: ${regLep.result} ${context.lepMod > 0 ? ("+" + context.lepMod) : ""} ${plusLep > 0 ? "+1" : ""}<br/>
 AE: ${regAsp.result}  ${context.aspMod > 0 ? ("+" + context.aspMod) : ""} ${plusAsp > 0 ? "+1" : ""}<br/>
 Wunde: ${woundHealed ? "geheilt" : "nicht geheilt"}`,
            rollMode: game.settings.get('core', 'rollMode'),
        })
        this.close()
    }

    static async #onSubmitForm(event, form, formData) {
        event.preventDefault()
        this.restDuration = formData.object.length
        this.restingType = formData.object.type
        this.badWeather = formData.object.bad_weather
        this.woundTreated = formData.object.wound_treated
        this.woundRegenerationModifier = formData.object.wound_treat_modifier
        this.wounds = formData.object.wounds
        this.badCamp = formData.object.bad_camp === "on"
        this.watch = formData.object.watch === "on"
        this.interrupted = formData.object.interrupted === "on"


        const elementLepMod = this.element.querySelector('output[name="lepMod"]')
        const elementKoMod = this.element.querySelector('output[name="koMod"]')
        const elementAspMod = this.element.querySelector('output[name="aspMod"]')
        const elementInMod = this.element.querySelector('output[name="inMod"]')
        const elementWoundMod = this.element.querySelector('output[name="woundMod"]')

        if (this.restingType === this.#type.DRAUßEN) {
            this.element.querySelector('input[name="bad_weather"]').removeAttribute('disabled')
            this.element.querySelector('input[name="bad_camp"]').removeAttribute('disabled')
        } else {
            this.element.querySelector('input[name="bad_weather"]').setAttribute('disabled', 'disabled')
            this.element.querySelector('input[name="bad_camp"]').setAttribute('disabled', 'disabled')
        }

        const context = this.#updateData()
        elementLepMod.value = context.lepModDisplay
        elementKoMod.value = context.koRollDisplay
        elementAspMod.value = context.aspModDisplay
        elementInMod.value = context.inRollDisplay
        elementWoundMod.value = context.woundModDisplay
    }

    #updateData(context = {}) {
        context.circumstances = this.#circumstances
        context.actorId = this._actor._id
        context.hasWounds = true
        context.hasAsP = true
        context.wounds = this.wounds

        let lepRestModifier = 0
        let aspRestModifier = 0

        if (this.restingType) {
            const circ = this.#circumstances.find(p => p.value === this.restingType)
            if (circ) {
                lepRestModifier += Number(circ.lepMod)
                aspRestModifier += Number(circ.aspMod)
            }
        }

        if (this.restingType === this.#type.DRAUßEN && this.badWeather !== -1) {
            const circ = this.#circumstances.find(p => p.group === "bad_weather")
            if (circ) {

                if (circ["lepMod"][this.badWeather] !== 0) {
                    lepRestModifier += circ["lepMod"][this.badWeather]
                }

                if (circ["aspMod"][this.badWeather] !== 0) {
                    aspRestModifier += circ["aspMod"][this.badWeather]
                }

            }
        }

        if (this.woundTreated) {
            context.woundModDisplay = `1w20-${this.woundRegenerationModifier ?? 0}`
            context.woundMod = this.woundRegenerationModifier ?? 0
        } else {
            if (context.hasWounds) {
                context.woundModDisplay = `1w20+${context.wounds * 3}`
                context.woundMod = context.wounds * 3
            }
        }

        if (this.restingType === this.#type.DRAUßEN && this.badCamp) {
            const circ = this.#circumstances.find(p => p.group === "bad_camp")
            if (circ) {
                lepRestModifier += Number(circ.lepMod)
                aspRestModifier += Number(circ.aspMod)
            }
        }

        if (this.watch) {
            const circ = this.#circumstances.find(p => p.group === "watch")
            if (circ) {
                lepRestModifier += Number(circ.lepMod)
                aspRestModifier += Number(circ.aspMod)
            }
        }

        if (this.interrupted) {
            const circ = this.#circumstances.find(p => p.group === "interrupted")
            if (circ) {
                lepRestModifier += Number(circ.lepMod)
                aspRestModifier += Number(circ.aspMod)
            }
        }

        const lepMod = (Number(this.lepModifier) + (lepRestModifier)) ?? 0
        const aspMod = (Number(this.aspModifier) + (aspRestModifier)) ?? 0

        context.lepMod = lepMod

        if (lepMod == 0) {
            context.lepModDisplay = "1w6"
        } else if (lepMod > 0) {
            context.lepModDisplay = "1w6+" + lepMod
        } else {
            context.lepModDisplay = "1w6" + lepMod
        }

        context.aspMod = aspMod
        if (aspMod == 0) {
            context.aspModDisplay = "1w6"
        } else if (lepMod > 0) {
            context.aspModDisplay = "1w6+" + aspMod
        } else {
            context.aspModDisplay = "1w6" + aspMod

        }

        context.koRoll = this.regKoMod
        if (this.regKoMod < 0) {
            context.koRollDisplay = `1w20${this.regKoMod}`
        } else {
            context.koRollDisplay = `1w20+${this.regKoMod}`
        }

        context.inRoll = this.regInMod
        if (this.regInMod < 0) {
            context.inRollDisplay = `1w20${this.regInMod}`
        } else {
            context.inRollDisplay = `1w20+${this.regInMod}`
        }

        return context
    }

    async _prepareContext(options) {
        const context = await super._prepareContext(options)
        return this.#updateData(context)
    }

    _onRender(context, options) {

    }
}