text: import { DicePoolFFG, RollFFG } from "./dice-pool-ffg.js";
  import PopoutEditor from "./popout-editor.js";
  
  /**
   * Extend the base Combat entity.
   * @extends {Combat}
   */
  export class CombatFFG extends Combat {
    /** @override */
    _getInitiativeRoll(combatant, formula) {
      const cData = duplicate(combatant.actor.data.data);
  
      if (combatant.actor.data.type === "vehicle") {
        return new RollFFG("0");
      }
  
      if (formula === "Vigilance") {
        formula = _getInitiativeFormula(cData.skills.Vigilance, parseInt(cData.characteristics.Willpower.value));
      } else if (formula === "Cool") {
        formula = _getInitiativeFormula(cData.skills.Cool, parseInt(cData.characteristics.Presence.value));
      }
  
      const rollData = combatant.actor ? combatant.actor.getRollData() : {};
  
      let roll = new RollFFG(formula, rollData).roll();
  
      const total = roll.ffg.success + roll.ffg.advantage * 0.01;
      roll._result = total;
      roll._total = total;
  
      return roll;
    }
  
    /** @override */
    _getInitiativeFormula(combatant) {
      return CONFIG.Combat.initiative.formula || game.system.data.initiative;
    }
  
    /** @override */
    async rollInitiative(ids, { formula = null, updateTurn = true, messageOptions = {} } = {}) {
      let initiative = this;
  
      let promise = new Promise(async function (resolve, reject) {
        const id = randomID();
  
        let whosInitiative = initiative.combatant.name;
        let dicePools = [];
        let vigilanceDicePool = new DicePoolFFG({});
        let coolDicePool = new DicePoolFFG({});
        let addDicePool = new DicePoolFFG({});
  
        const defaultInitiativeFormula = formula || initiative._getInitiativeFormula();
        if (Array.isArray(ids) && ids.length > 1) {
          whosInitiative = "Multiple Combatants";
        } else {
          // Make sure we are dealing with an array of ids
          ids = typeof ids === "string" ? [ids] : ids;
          const c = initiative.getCombatant(ids[0]);
          const data = c.actor.data.data;
  
          vigilanceDicePool = _buildInitiativePool(data, "Vigilance");
          coolDicePool = _buildInitiativePool(data, "Cool");
  
          const initSkills = Object.keys(data.skills).filter((skill) => data.skills[skill].useForInitiative);
  
          initSkills.forEach((skill) => {
            if (dicePools.find((p) => p.name === skill)) return;
  
            const skillPool = _buildInitiativePool(data, skill);
            skillPool.label = data.skills[skill].label;
            skillPool.name = skill;
            dicePools.push(skillPool);
          });
        }
  
        if (dicePools.findIndex((p) => p.name === "Vigilance") < 0) {
          vigilanceDicePool.label = "SWFFG.SkillsNameVigilance";
          vigilanceDicePool.name = "Vigilance";
          dicePools.push(vigilanceDicePool);
        }
        if (dicePools.findIndex((p) => p.name === "Cool") < 0) {
          coolDicePool.label = "SWFFG.SkillsNameCool";
          coolDicePool.name = "Cool";
          dicePools.push(coolDicePool);
        }
  
        const title = game.i18n.localize("SWFFG.InitiativeRoll") + ` ${whosInitiative}...`;
        const content = await renderTemplate("systems/starwarsffg/templates/dialogs/ffg-initiative.html", {
          id,
          dicePools,
          addDicePool,
          defaultInitiativeFormula,
        });
  
        new Dialog({
          title,
          content,
          buttons: {
            one: {
              icon: '<i class="fas fa-check"></i>',
              label: game.i18n.localize("InitiativeRoll"),
              callback: async () => {
                const container = document.getElementById(id);
                const currentId = initiative.combatant._id;
  
                const baseFormulaType = container.querySelector('input[name="skill"]:checked').value;
  
                // Iterate over Combatants, performing an initiative roll for each
                const [updates, messages] = ids.reduce(
                  (results, id, i) => {
                    let [updates, messages] = results;
  
                    // Get Combatant data
                    const c = initiative.getCombatant(id);
                    if (!c || !c.owner) return resolve(results);
  
                    // Detemine Formula
                    let pool = _buildInitiativePool(c.actor.data.data, baseFormulaType);
  
                    const addPool = DicePoolFFG.fromContainer(container.querySelector(`.addDicePool`));
                    pool.success += +addPool.success;
                    pool.advantage += +addPool.advantage;
                    pool.failure += +addPool.failure;
                    pool.threat += +addPool.threat;
                    pool.boost += +addPool.boost;
                    pool.setback += +addPool.setback;
  
                    const rollData = c.actor ? c.actor.getRollData() : {};
                    let roll = new RollFFG(pool.renderDiceExpression(), rollData, { success: pool.success, advantage: pool.advantage, failure: pool.failure, threat: pool.threat }).roll();
                    const total = roll.ffg.success + roll.ffg.advantage * 0.01;
                    roll._result = total;
                    roll._total = total;
  
                    // Roll initiative
                    updates.push({ _id: id, initiative: roll.total });
  
                    // Determine the roll mode
                    let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
                    if ((c.token.hidden || c.hidden) && rollMode === "roll") rollMode = "gmroll";
  
                    // Construct chat message data
                    let messageData = mergeObject(
                      {
                        speaker: {
                          scene: canvas.scene._id,
                          actor: c.actor ? c.actor._id : null,
                          token: c.token._id,
                          alias: c.token.name,
                        },
                        flavor: `${c.token.name} ${game.i18n.localize("SWFFG.InitiativeRoll")} (${game.i18n.localize(`SWFFG.SkillsName${baseFormulaType.replace(/[: ]/g, "")}`)})`,
                        flags: { "core.initiativeRoll": true },
                      },
                      messageOptions
                    );
                    const chatData = roll.toMessage(messageData, { create: false, rollMode });
  
                    // Play 1 sound for the whole rolled set
                    if (i > 0) chatData.sound = null;
                    messages.push(chatData);
  
                    // Return the Roll and the chat data
                    return results;
                  },
                  [[], []]
                );
                if (!updates.length) return initiative;
  
                // Update multiple combatants
                await initiative.updateEmbeddedEntity("Combatant", updates);
  
                // Ensure the turn order remains with the same combatant
                if (updateTurn) {
                  await initiative.update({ turn: initiative.turns.findIndex((t) => t._id === currentId) });
                }
  
                // Create multiple chat messages
                await CONFIG.ChatMessage.entityClass.create(messages);
  
                resolve(initiative);
              },
            },
            two: {
              icon: '<i class="fas fa-times"></i>',
              label: game.i18n.localize("SWFFG.Cancel"),
            },
          },
        }).render(true);
      });
  
      return await promise;
    }
  }
  
  function _getInitiativeFormula(skill, ability) {
    const dicePool = new DicePoolFFG({
      ability: ability,
      boost: parseInt(skill.boost),
      setback: parseInt(skill.setback),
      force: parseInt(skill.force),
    });
    dicePool.upgrade(parseInt(skill.rank));
    return dicePool.renderDiceExpression();
  }
  
  function _buildInitiativePool(data, skill) {
    const pool = new DicePoolFFG({
      ability: Math.max(data.characteristics[data.skills[skill].characteristic].value, data.skills[skill].rank),
      boost: data.skills[skill].boost,
      advantage: data.skills[skill].advantage,
      success: data.skills[skill].success,
    });
    pool.upgrade(Math.min(data.characteristics[data.skills[skill].characteristic].value, data.skills[skill].rank));
  
    return pool;
  }
  