
/* -------------------------------------------- */
export class LethalFantasyCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker {

  static PARTS = {
    "header": {
      "template": "systems/fvtt-lethal-fantasy/templates/combat-tracker-header-v2.hbs"
    },
    "tracker": {
      "template": "systems/fvtt-lethal-fantasy/templates/combat-tracker-v2.hbs"
    },
    "footer": {
      "template": "systems/fvtt-lethal-fantasy/templates/combat-tracker-footer-v2.hbs"
    }
  }

  static DEFAULT_OPTIONS = foundry.utils.mergeObject(super.DEFAULT_OPTIONS, {
    actions: {
      initiativePlus: LethalFantasyCombatTracker.#initiativePlus,
      initiativeMinus: LethalFantasyCombatTracker.#initiativeMinus,
    },
  });

  async _prepareContext(options) {
    let data = await super._prepareContext(options);
    console?.log("Combat Tracker Data", data);
    /*for (let u of data.turns) {
      let c = game.combat.combatants.get(u.id);
      u.progressionCount = c.system.progressionCount
      u.isMonster = c.actor.type === "monster"
    }
    console.log("Combat Data", data);*/
    return data;
  }

  static #initiativePlus(ev) {
    ev.preventDefault();
    let cId = ev.target.closest(".combatant").dataset.combatantId;
    let c = game.combat.combatants.get(cId);
    c.update({ 'initiative': c.initiative + 1 });
    console.log("Initiative Plus");
  }

  static #initiativeMinus(ev) {
    ev.preventDefault();
    let cId = ev.target.closest(".combatant").dataset.combatantId;
    let c = game.combat.combatants.get(cId);
    let newInit = Math.max(c.initiative - 1, 0);
    c.update({ 'initiative': newInit });
  }

  activateListeners(html) {
    super.activateListeners(html);
    // Display Combat settings
    html.find(".initiative-plus").click(ev => {
      ev.preventDefault();
      let cId = ev.currentTarget.closest(".combatant").dataset.combatantId;
      let c = game.combat.combatants.get(cId);
      c.update({ 'initiative': c.initiative + 1 });
    });

    html.find(".initiative-minus").click(ev => {
      ev.preventDefault();
      let cId = ev.currentTarget.closest(".combatant").dataset.combatantId;
      let c = game.combat.combatants.get(cId);
      c.update({ 'initiative': c.initiative - 1 });
      console.log("Initiative Minus");
    });
  }

  /* -------------------------------------------- */
  static get defaultOptions() {
    let path = "systems/fvtt-lethal-fantasy/templates/combat-tracker.hbs";
    return foundry.utils.mergeObject(super.defaultOptions, {
      template: path,
    });
  }
}

export class LethalFantasyCombat extends Combat {

  /**
 * Return the Array of combatants sorted into initiative order, breaking ties alphabetically by name.
 * @returns {Combatant[]}
 */
  setupTurns() {
    console?.log("Setup Turns....");
    this.turns ||= [];

    // Determine the turn order and the current turn
    const turns = this.combatants.contents.sort(this.sortCombatantsLF);
    if (this.turn !== null) this.turn = Math.clamp(this.turn, 0, turns.length - 1);

    // Update state tracking
    let c = turns[this.turn];
    this.current = this._getCurrentState(c);
    if (!this.previous) this.previous = this.current;

    // Return the array of prepared turns
    return this.turns = turns;
  }

  async rollInitiative(ids, options) {
    console.log("%%%%%%%%% Roll Initiative", ids, options);

    ids = typeof ids === "string" ? [ids] : ids;
    let messages = [];
    let rollMode = game.settings.get("core", "rollMode");

    let updates = [];
    for (let cId of ids) {
      const c = this.combatants.get(cId);
      let user = game.users.find(u => u.active && u.character && u.character.id === c.actor.id);
      if (user?.hasPlayerOwner) {
        console.log("Rolling initiative for", c.actor.name);
        game.socket.emit(`system.${SYSTEM.id}`, { type: "rollInitiative", actorId: c.actor.id, combatId: this.id, combatantId: c.id });
      } else {
        user = game.users.find(u => u.active && u.isGM);
        c.actor.system.rollInitiative(this.id, c.id);
      }
    }

    return this;
  }

  resetProgression(cId) {
    let c = this.combatants.get(cId);
    c.update({ 'system.progressionCount': 0 });
  }

  setCasting(cId) {
    let c = this.combatants.get(cId);
    c.setFlag(SYSTEM.id, "casting", true);
  }

  resetCasting(cId) {
    let c = this.combatants.get(cId);
    c.setFlag(SYSTEM.id, "casting", false);
  }

  isCasting(cId) {
    let c = this.combatants.get(cId);
    return c.getFlag(SYSTEM.id, "casting");
  }

  async nextTurn() {
    console.log("NEXT TURN");

    let turn = this.turn ?? -1;
    let skipDefeated = this.settings.skipDefeated;

    // Determine the next turn number
    let next = null;
    for (let [i, t] of this.turns.entries()) {
      console.log("Turn", t);
      if (i <= turn) continue;
      if (skipDefeated && t.isDefeated) continue;
      next = i;
      break;
    }

    // Maybe advance to the next round
    let round = this.round;
    if ((this.round === 0) || (next === null) || (next >= this.turns.length)) {
      return this.nextRound();
    }

    // Update the document, passing data through a hook first
    const updateData = { round, turn: next };
    const updateOptions = { advanceTime: CONFIG.time.turnTime, direction: 1 };
    Hooks.callAll("combatTurn", this, updateData, updateOptions);
    return this.update(updateData, updateOptions);
  }

  async nextRound() {
    this.turnsDone = false

    let turn = this.turn === null ? null : 0; // Preserve the fact that it's no-one's turn currently.
    console.log("ROUND", this);

    let advanceTime = Math.max(this.turns.length - this.turn, 0) * CONFIG.time.turnTime;
    advanceTime += CONFIG.time.roundTime;
    let nextRound = this.round + 1;

    let initOK = true;
    for (let c of this.combatants) {
      if (c.initiative === null) {
        initOK = false;
        break;
      }
    }
    if (!initOK) {
      ui.notifications.error("All combatants must have initiative rolled before the round can advance.");
      return this;
    }

    for (let c of this.combatants) {
      if (nextRound >= c.initiative) {
        let user = game.users.find(u => u.active && u.character && u.character.id === c.actor.id);
        if (user?.hasPlayerOwner) {
          game.socket.emit(`system.${SYSTEM.id}`, { type: "rollProgressionDice", progressionCount: c.system.progressionCount + 1, actorId: c.actor.id, combatId: this.id, combatantId: c.id });
        } else {
          user = game.users.find(u => u.active && u.isGM);
          c.actor.system.rollProgressionDice(this.id, c.id);
        }
      }
    }

    // Update the document, passing data through a hook first
    const updateData = { round: nextRound, turn };
    const updateOptions = { advanceTime, direction: 1 };
    Hooks.callAll("combatRound", this, updateData, updateOptions);
    return this.update(updateData, updateOptions);
  }


  sortCombatantsLF(a, b) {
    return a.initiative - b.initiative;
  }
}
