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

if ( canvas.tokens.controlled[0]===undefined && Array.from(game.user.targets)[0]===undefined ) {
  ui.notifications.error("Please, select or target a token."); // No Token is Selected
} else {
  main();
}

async function main() {
    let tokens = [];
    tokens = tokens.concat(Array.from(game.user.targets));
    tokens = tokens.concat(canvas.tokens.controlled);

    let groups = {
        "Attributes": [
            "Agility",
            "Smarts",
            "Spirit",
            "Strength",
            "Vigor"
        ],
        "Skills": [],
    }
    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"
        }
    };

    for (var 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]`
            };
            groups.Skills.push(name)
        }
    }

    var traitoptions = `<select id="select-trait" name="select-trait">`;
    for (const group in groups) {
        traitoptions += `<optgroup label="${group}">`;
        for (const trait of groups[group]) {
            traitoptions += `<option value="${trait}">${trait}</option>`;
        }
        traitoptions += '</optgroup>';
    }
    traitoptions += `</select>`;

    var applyChanges = false;
    var raise = false;
    new Dialog({
        title: `Boost/Lower Trait - ${version}`,
        content: `
      <style>
        div.blueTable {
          width: 100%;
          text-align: center;
          border-collapse: collapse;
        }
        .divTable.blueTable .divTableCell, .divTable.blueTable .divTableHead {
        }
        .blueTable .tableFootStyle {
          font-size: 14px;
        }
        .blueTable .tableFootStyle .links {
           text-align: right;
        }
        .blueTable .tableFootStyle .links a{
          display: inline-block;
          background: #1C6EA4;
          color: #FFFFFF;
          padding: 2px 8px;
          border-radius: 5px;
        }
        .blueTable.outerTableFooter {
          border-top: none;
        }
        .blueTable.outerTableFooter .tableFootStyle {
          padding: 3px 5px; 
        }
        /* DivTable.com */
        .divTable{ display: table; }
        .divTableRow { display: table-row; }
        .divTableHeading { display: table-header-group;}
        .divTableCell, .divTableHead { display: table-cell;}
        .divTableHeading { display: table-header-group;}
        .divTableFoot { display: table-footer-group;}
        .divTableBody { display: table-row-group;}
      </style>      
      
        <div class="divTable blueTable">
        <div class="divTableBody">
        <div class="divTableRow">
        <div class="divTableCell"><b>Which Trait?</b></div>
        <div class="divTableCell"><b>Boost or Lower?</b></div>
        </div>
        <div class="divTableRow">
        <div class="divTableCell">${traitoptions}</div>
        <div class="divTableCell">
            <select id="select-direction" name="select-direction">
                <option value="Boost">Boost</option>
                <option value="Lower">Lower</option>
            </select        
        </div>
        </div>
        </div>
        </div>
        </br>
      `,
        buttons: {
            apply: {
                label: "Apply",
                callback: () => { applyChanges = true; raise }
            },
            raise: {
                label: "Apply with raise",
                callback: () => { applyChanges = true; raise = true }
            },
            cancel: {
                label: "Cancel"
            }
        },
        default: "apply",
        close: html => {
            if (applyChanges) {
                let direction = html.find('[name="select-direction"]')[0].value;
                let trait = html.find('[name="select-trait"]')[0].value;
                createEffect(tokens, traits, direction, trait, raise);
            }
        }
    }).render(true);
} // end main

async function createEffect(tokens, traits, direction, trait, raise) {
  trait = traits[trait];
  for (var tokenD of tokens) {
    let currentdie = 0;
    let currentmod = 0;
    if (trait["type"] == "attribute") {
      var part;
      let value = tokenD.actor.data;
      for (part of trait["diekey"].split(".")) {
          value = value[part];
      }
      currentdie = value
      value = tokenD.actor.data
      for (part of trait["modkey"].split(".")) {
          value = value[part];
      }
      currentmod = value;
    } else {
      let skill = tokenD.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;
      } 
    }
    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;
    }
    var effectData = {
      label: `${direction} ${trait.name}${raise ? " with raise" : ""}`,
      id: `${direction}${trait.name}${raise ? "raise" : ""}`,
      icon: direction == "Lower" ? DOWNICON : UPICON,
      changes: [{                    
        "key": trait["diekey"],
        "mode": 2,
        "value": diemod,
        "priority": 0
      },{
        "key": trait["modkey"],
        "mode": 2,
        "value": modmod,
        "priority": 0
      }]
    };
    if (direction == "Boost") {
        effectData["duration"] = {rounds: 5}
    }
    let spellEffect = game.macros.getName("ApplySpellEffect");
    spellEffect.execute(effectData, [tokenD])
  }
}
