const UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'
const DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'

let tokens = [];
let targets = Array.from(game.user.targets);
if (targets.length > 0) {
    tokens = targets;
} else if (canvas.tokens.controlled.length > 0) {
    tokens = canvas.tokens.controlled;
}
if (tokens.length > 0) {
    main(tokens);
} else {
    ui.notifications.error("Please select or target a token");
}

async function main(tokens) {
    let traitOptions = [
        "Agility",
        "Smarts",
        "Spirit",
        "Strength",
        "Vigor"
    ];
    let allSkills = [];
    let traits = {
        "Agility": {
            type: "attribute",
            name: "Agility",
            modkey: "data.attributes.agility.die.modifier",
            diekey: "data.attributes.agility.die.sides"
        },
        "Smarts": {
            type: "attribute",
            name: "Smarts",
            modkey: "data.attributes.smarts.die.modifier",
            diekey: "data.attributes.smarts.die.sides"
        },
        "Spirit": {
            type: "attribute",
            name: "Spirit",
            modkey: "data.attributes.spirit.die.modifier",
            diekey: "data.attributes.spirit.die.sides"
        },
        "Strength": {
            type: "attribute",
            name: "Strength",
            modkey: "data.attributes.strength.die.modifier",
            diekey: "data.attributes.strength.die.sides"
        },
        "Vigor": {
            type: "attribute",
            name: "Vigor",
            modkey: "data.attributes.vigor.die.modifier",
            diekey: "data.attributes.vigor.die.sides"
        }
    };
    let tokenList = tokens.map(t => t.name).join(", ");
    for (const token of tokens) {
        let skills = token.actor.items.filter(e => e.type == "skill");
        for (const skill of skills) {
            let name = skill.data.name
            traits[name] = {
                type: "skill",
                name: name,
                modkey: `@Skill{${name}}[data.die.modifier]`,
                diekey: `@Skill{${name}}[data.die.sides]`
            };
            if (name != 'Unskilled' && !allSkills.find(v => v == name)) {
                allSkills.push(name);
            }
        }
    }
    traitOptions = traitOptions.concat(allSkills.sort());
    let menuOptions = {
        title: 'Boost/Lower Trait',
        defaultButton: "Cancel",
        options: {}
    };
    let menuData = {
        inputs: [
           {type: 'header', label: 'Boost/Lower Trait'},
           {type: 'info', label: `Affected Tokens: ${tokenList}`}, 
           {type: 'select', label: 'Trait', options: traitOptions},
           {type: 'info', label: "Boost or Lower?"},
           {type: 'radio', label: 'Boost', options: ['boostlower', true]},
           {type: 'radio', label: 'Lower', options: ['boostlower', false]},
        ],
        buttons: [
            {label: "Apply", value: "apply"},
            {label: "Apply with raise", value: "raise"},
            {label: "Cancel", value: "cancel"}
        ]
    }
    let {buttons, inputs} = await warpgate.menu(menuData, menuOptions);
    if (buttons != "cancel") {
        let trait = inputs[2];
        let direction = inputs[4] || inputs[5];
        createEffect(tokens, traits[trait], direction, buttons);
    }
}

function getDottedPart(obj, key) {
    let value = obj;
    for (const part of key.split(".")) {
        value = value[part];
    }
    return value;
}

async function createEffect(tokens, trait, direction, buttons) {
    const raise = (buttons == 'raise');
    const effectName = `${raise ? "Major" : "Minor"} ${direction} ${trait.name}`;
    const effectId = `${raise ? "Major" : "Minor"}${direction}${trait.name}`;
    const effectIcon = (direction == 'Boost' ? UPICON : DOWNICON)
    for (const token of tokens) {
        let tokenDoc = token.document;
        let currentDie = 0;
        let currentMod = 0;
        if (trait.type == 'attribute') {
            currentDie = getDottedPart(token.actor.data, trait.diekey);
            currentMod = getDottedPart(token.actor.data, trait.modkey);
        } else {
            let skill = token.actor.items.filter(s => s.type == 'skill').find(
                s => s.data.name == trait.name)
            if (skill) {
                currentDie = skill.data.data.die.sides;
                currentMod = skill.data.data.die.modifier;
            } else {
                currentDie = 4;
                currentMod = -2;
            }
        }
        if (currentDie == 0) {
            continue;
        }
        if (currentDie == 4 && direction == "Lower") {
            continue;
        }
        let diemod = 2;
        let modmod = 0;
        if (direction == "Lower") {
            diemod = -2;
        }
        if (currentDie == 6 && direction == "Lower" && raise) {
            diemod = -1
        } else if (currentDie == 12 && direction == "Boost") {
            diemod = 0;
            modmod = 1;
        }
        if (raise) {
            diemod *= 2;
            modmod *= 2;
        }
        if (currentDie == 10 && direction == "Boost" && raise) {
            diemod = 2;
            modmod = 1;
        }
        if (currentDie == 4 && currentMod == -2 && direction == "Boost") {
            diemod = (raise ? 2 : 0);
            modmod = 2;
        }
        let effectData = {
            icon: effectIcon,
            id: effectId,
            label: effectName,
            flags: {
                swade: {
                    expiration: 3,
                    loseTurnOnHold: true
                }
            },
            changes: []
        };
        let mode = foundry.CONST.ACTIVE_EFFECT_MODES.ADD;
        if (diemod != 0) {
            effectData.changes.push({ key: trait.diekey, mode: mode, value: diemod, priority: 0 });
        }
        if (modmod != 0) {
            effectData.changes.push({ key: trait.modkey, mode: mode, value: modmod, priority: 0 });
        }
        if (direction == "Boost") {
            effectData.duration = { rounds: 5 };
        }
        let mutate = {
            embedded: {
                ActiveEffect: {
                }
            }
        };
        mutate.embedded.ActiveEffect[effectName] = effectData;
        let mutateOptions = {
            comparisonKeys: { 'ActiveEffect': 'label' },
            name: effectName,
            permanent: false,
            description: effectName,
        }
        if (trait.type == 'skill' && direction == 'Boost' && !token.actor.items.getName(trait.name)) {
            let itemmutate = { embedded: { Item: {} } }
            itemmutate.embedded.Item[trait.name] = {
                "name": trait.name,
                "type": "skill",
                "img": "systems/swade/assets/icons/skills/uncertainty.svg",
                "data": {
                    "description": "See SWADE. Auto added as untrained for Boost Trait.",
                    "notes": "",
                    "additionalStats": {},
                    "attribute": trait.attribute,
                    "isCoreSkill": false,
                    "die": {
                        "sides": 4,
                        "modifier": -2
                    },
                    "wild-die": {
                        "sides": 6
                    }
                }
            }
            await warpgate.mutate(token.document, itemmutate, {}, mutateOptions);
        }
        mutateOptions.permanent = true;
        await warpgate.mutate(token.document, mutate, {}, mutateOptions);
    }
}