export class GroupSheet extends foundry.appv1.sheets.ActorSheet {
    /**@override */
    static get defaultOptions() {
        return foundry.utils.mergeObject(super.defaultOptions, {
            classes: ['dsa41', 'sheet', 'actor', 'group'],
            width: 520,
            height: 480,
            tabs: [
                {
                    navSelector: '.sheet-tabs',
                    contentSelector: '.sheet-body',
                    initial: 'description',
                },
            ],
        });
    }

    static async onDroppedData(group, sheet, data) {
        if (data.type === "Actor") {
            const uuid = await foundry.utils.parseUuid(data.uuid);
            const character = await (game.actors.get(uuid.id))

            // check if character already is part of the group
            if (group.system.characters.includes(character._id)) {
                ui.notifications.warn(`${character.name} befindet sich bereits in der Heldengruppe ${group.name}`)
                return false;
            }


            // update group
            let settings = {...group.system.settings}
            character.items.filter((i) => i.type === "Advantage").forEach((advantage) => {
                if (!settings[sheet.#stringToKeyFieldName(advantage.name)]) {
                    settings[sheet.#stringToKeyFieldName(advantage.name)] = false
                }
            })
            character.items.filter((i) => i.type === "Skill").forEach((skill) => {
                if (!settings[sheet.#stringToKeyFieldName(skill.name)]) {
                    settings[sheet.#stringToKeyFieldName(skill.name)] = false
                }
            })

            await group.update({
                system: {
                    characters: [
                        ...group.system.characters,
                        character._id
                    ],
                    settings: settings
                }
            })
            ui.notifications.info(`${character.name} ist der Heldengruppe ${group.name} beigetreten`)
        }
        if (data.type === "Equipment") {
            const uuid = await foundry.utils.parseUuid(data.uuid);
            const equipment = await (game.actors.get(uuid.id))
            ui.notifications.info(`${equipment.name} befindet sich nun im Inventar der Heldengruppe ${group.name}`)
            return true;
        }
    }

    #stringToKeyFieldName(s) {
        return s
    }

    /** @override */
    get template() {
        return `systems/DSA_4-1/templates/actor/group-sheet.hbs`;
    }

    /** @override */
    async getData() {
        const context = super.getData();

        // Use a safe clone of the actor data for further operations.
        const groupData = context.data;

        // Add the actor's data to context.data for easier access, as well as flags.
        context.system = groupData.system;
        context.flags = groupData.flags;
        context.characters = []
        context.isGM = game.user.isGM;

        context.fields = [];

        const hiddenFields = Object.entries(groupData.system.settings)
            .sort(([key, value], [otherKey, otherValue]) => key.localeCompare(otherKey))
            .filter(([key, value]) => value === true)
            .map(([key, value]) => key)

        context.fields = {}
        context.fields["head"] = {}
        for (const field of hiddenFields) {

            context.fields[field] = {}

            for (const characterId of groupData.system.characters) {
                const character = await game.actors.get(characterId)
                context.fields[field][character.name] = "-"

            }
        }

        for (const characterId of groupData.system.characters) {
            const character = await game.actors.get(characterId)

            character.items.filter((i) => i.type === "Advantage").filter((i) => hiddenFields.includes(this.#stringToKeyFieldName(i.name))).map((advantage) => {
                const n = this.#stringToKeyFieldName(advantage.name)
                if (!context.fields[n]) {
                    context.fields[n] = {}
                }
                context.fields[n][character.name] = advantage.system.value ?? "Ja" // TODO: Allow GM roll
            })

            character.items.filter((i) => i.type === "Skill").filter((i) => hiddenFields.includes(this.#stringToKeyFieldName(i.name))).map((skill) => {
                const n = this.#stringToKeyFieldName(skill.name)
                if (!context.fields[n]) {
                    context.fields[n] = {}
                }
                const eigenschaften = Object.values(skill.system.probe);
                context.fields[n][character.name] = {
                        taw: skill.system.taw,
                        eigenschaft1: eigenschaften[0],
                        eigenschaft2: eigenschaften[1],
                        eigenschaft3: eigenschaften[2],
                        rollEigenschaft1: character.system.attribute[eigenschaften[0].toLowerCase()].aktuell,
                        rollEigenschaft2: character.system.attribute[eigenschaften[1].toLowerCase()].aktuell,
                        rollEigenschaft3: character.system.attribute[eigenschaften[2].toLowerCase()].aktuell,
                        name: skill.name,
                        actor: character._id,
                    }
                    ?? 0
            })

            context.fields.head[character.name] =
                {
                    img: character.img,
                    name: character.name,
                    id: character._id,
                    attributes: [
                        {name: "MU", value: character.system.attribute.mu.aktuell},
                        {name: "KL", value: character.system.attribute.kl.aktuell},
                        {name: "IN", value: character.system.attribute.in.aktuell},
                        {name: "CH", value: character.system.attribute.ch.aktuell},
                        {name: "FF", value: character.system.attribute.ff.aktuell},
                        {name: "GE", value: character.system.attribute.ge.aktuell},
                        {name: "KO", value: character.system.attribute.ko.aktuell},
                        {name: "KK", value: character.system.attribute.kk.aktuell},
                    ],
                    isLimited: character.isOwner || !character.limited,
                    isVisible: character.isOwner || character.visible,
                    isOwner: character.isOwner
                }
        }

        context.equipments = [];
        const actorData = context.data;
        Object.values(actorData.items).forEach((item, index) => {
            if (item.type === "Equipment") {
                context.equipments.push({
                    index: index,
                    id: item._id,
                    quantity: item.system.quantity,
                    name: item.name,
                    icon: item.img
                })
            }
        })

        context.settings = Object.fromEntries(Object.entries(groupData.system.settings)
            .sort(([key, value], [otherKey, otherValue]) => key.localeCompare(otherKey)))

        return await context;
    }

    openEmbeddedDocument(documentId) {
        this.object.items.get(documentId).sheet.render(true)
    }


    _evaluateRoll(rolledDice, {
        taw,
        lowerThreshold = 1,
        upperThreshold = 20,
        countToMeisterlich = 3,
        countToPatzer = 3,
        werte = []
    }) {
        let tap = taw;
        let meisterlichCounter = 0;
        let patzerCounter = 0;
        let failCounter = 0;

        rolledDice.forEach((rolledDie, index) => {
            if (tap < 0 && rolledDie.result > werte[index]) {
                tap -= rolledDie.result - werte[index];
                if (tap < 0) { // konnte nicht vollständig ausgeglichen werden
                    failCounter++;
                }
            } else if (rolledDie.result > werte[index]) { // taw ist bereits aufgebraucht und wert kann nicht ausgeglichen werden
                tap -= rolledDie.result - werte[index];
                failCounter++;
            }
            if (rolledDie.result <= lowerThreshold) meisterlichCounter++;
            if (rolledDie.result > upperThreshold) patzerCounter++;
        })

        return {
            tap,
            meisterlich: meisterlichCounter === countToMeisterlich,
            patzer: patzerCounter === countToPatzer,
        }
    }

    async _onTalentRoll(event) {
        event.preventDefault();
        const dataset = event.currentTarget.dataset;
        const actor = await game.actors.get(dataset.actorId);
        console.log(dataset, actor)
        if (dataset.rolleigenschaft1) {
            let roll1 = new Roll("3d20", actor.getRollData());

            let evaluated1 = (await roll1.evaluate())

            const dsaDieRollEvaluated = this._evaluateRoll(evaluated1.terms[0].results, {
                taw: dataset.taw,
                werte: [dataset.rolleigenschaft1, dataset.rolleigenschaft2, dataset.rolleigenschaft3],
            })

            if (dsaDieRollEvaluated.tap >= 0) { // erfolg
                evaluated1.toMessage({
                    speaker: ChatMessage.getSpeaker({actor: actor}),
                    flavor: ` ${dsaDieRollEvaluated.meisterlich ? 'Meisterlich geschafft' : 'Geschafft'} mit ${dsaDieRollEvaluated.tap} Punkten übrig`,
                }, {rollMode: "gmroll"})
            } else { // misserfolg
                evaluated1.toMessage({
                    speaker: ChatMessage.getSpeaker({actor: actor}),
                    flavor: ` ${dsaDieRollEvaluated.meisterlich ? 'Gepatzt' : ''} mit ${Math.abs(dsaDieRollEvaluated.tap)} Punkten daneben`,
                }, {rollMode: "gmroll"})
            }
        }
    }

    activateListeners(html) {
        super.activateListeners(html);

        html.on('click', '.owneroption.clickable', async (evt) => {
            const dataset = evt.target.dataset;
            const group = this.object;
            switch (dataset.operation) {
                case "removeFromParty":
                    const charactersWithoutMember = group.system.characters.filter(id => id !== dataset.id)
                    await group.update({
                        system: {
                            characters: charactersWithoutMember
                        }
                    })
            }
        });
        html.on('click', '.header.clickable', async (evt) => {
            const {id, operation} = evt.currentTarget.dataset;
            if (operation === "openActorSheet") {
                evt.stopPropagation();
                (await game.actors.get(id)).sheet.render(true);
            }
        })


        html.on('click', '.equipment', (evt) => {
            this.openEmbeddedDocument(evt.target.dataset.id);
            evt.stopPropagation();
        })

        html.on('click', ".rollable", (evt) => {
            this._onTalentRoll(evt)
            evt.stopPropagation()
        })

        new ContextMenu(html, '.equipment', [
            {
                name: "Aus dem Gruppeninventar entfernen",
                icon: '<i class="fa-solid fa-trash"></i>',
                callback: (event) => {
                    this.object.deleteEmbeddedDocuments('Item', [event[0].dataset.id])
                },
                condition: () => true
            }
        ]);
    }
}
