
export default class RMFRPToolsDiceRoller extends FormApplication {
  
  constructor(item, actor) {
    super();
    this.item = foundry.utils.duplicate(item);
    this.actor = actor;
    this.itemName = item.name;
    this.characterBonus = Number(item.system.total_bonus);
    this.stunnedModifier = actor.getStunnedModifier()
    this.rollType = [
      { value: "one_to_onehundred", text: "1-100", selected: false },
      { value: "open_ended", text: "Open-Ended", selected: true },
      { value: "high_open_ended", text: "High Open-Ended", selected: false },
      { value: "low_open_ended", text: "Low Open-Ended", selected: false }
    ];

    // Process weapon case
    if (this.item.type == "skill" && this.item.system.category.includes("Weapon"))  {
      let weapon = this.actor.items.find(i =>  i.type == "weapon" && this.item._id == i.system.skill);
      if ( !weapon ) {
        ui.notifications.error("Weapon not found for skill: " + this.item.name);  
        return
      }
      this.weapon = weapon
      this.characterBonus += Number(weapon.system.weapon_bonus);
    }

  }

  static get defaultOptions() {
    return foundry.utils.mergeObject(super.defaultOptions, {
      classes: ["form"],
      title: "Rolemaster Dice Roller",
      popOut: true,
      width: 480,
      height: 440,
      template: "systems/fvtt-rolemaster-frp/templates/sheets/apps/app_dice_roller.html"
    });
  }

  getData() {

    // Send data to the template
    return {
      itemName: this.itemName,
      characterBonus: this.characterBonus,
      selectOptions: this.rollType,
      woundsModifier: this.actor.system.modifiers.woundsModifier,
      weapon: this?.weapon,
      targetArmorClass: 1,
      config: CONFIG.rmfrp,
      difficulty: 0,
      combatSituation: 0,
      lightningModifier: 0,
      darknessModifier: 0,
      hitsPerRound: 0,
      isStunned: this.actor.system.state.stunned,
      stunnedModifier: this.stunnedModifier
    };
  }

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

  async _updateObject(event, formData) {
    console.log("Rolling Dice");
    console.log(formData);
    console.log(event);
    this.roll(event.submitter?.dataset?.value, formData);
  }

  /* -------------------------------------------- */
  async showDiceSoNice(roll, rollMode) {
    if (game.modules.get("dice-so-nice")?.active) {
      if (game.dice3d) {
        let whisper = null;
        let blind = false;
        rollMode = rollMode ?? game.settings.get("core", "rollMode");
        switch (rollMode) {
          case "blindroll": //GM only
            blind = true;
          case "gmroll": //GM + rolling player
            whisper = this.getUsers(user => user.isGM);
            break;
          case "roll": //everybody
            whisper = this.getUsers(user => user.active);
            break;
          case "selfroll":
            whisper = [game.user.id];
            break;
        }
        await game.dice3d.showForRoll(roll, game.user, true, whisper, blind);
      }
    }
  }

  /* -------------------------------------------- */
  async roll(rollKey, formData) {
    let baseRoll = await new Roll("1d100").roll();
    await this.showDiceSoNice(baseRoll, game.settings.get("core", "rollMode"))
    let rollType = this.rollType.find(r => r.value == rollKey)?.text;
    let rollData = {
      name: this.itemName,
      weapon: this?.weapon,
      rollKey: rollKey,
      rollType: rollType,
      difficulty: Number(formData.difficulty),
      targetArmorClass: Number(formData?.targetArmorClass || 1),
      combatSituation: Number(formData?.combatSituation || 0),
      lightningModifier: Number(formData?.lightningModifier || 0),
      darknessModifier: Number(formData?.darknessModifier || 0),
      characterBonus: Number(this.characterBonus),
      woundsModifier: Number(this.actor.system.modifiers.woundsModifier),
      hitsPerRound: Number(formData.hitsPerRound),
      isStunned: this.actor.system.state.stunned,
      stunnedModifier: this.stunnedModifier,
      rolls: [baseRoll],
    }
    if (baseRoll.result == 66) {
      rollData.content = "You rolled a 66!";
    }
    // Process the for low open ended rolls
    if (rollKey === "open_ended" || rollKey === "low_open_ended") {
      if (baseRoll.result < 6) {
        rollData.lowopen = true
        let newRoll = await new Roll("-1d100").roll();
        await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
        rollData.rolls.push(newRoll);
        while (newRoll.result > 95) {
          newRoll = await new Roll("-1d100").roll();
          await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
          rollData.rolls.push(newRoll);
        }
      }
    }
    // Process the for high open ended rolls
    if (rollKey === "open_ended" || rollKey === "high_open_ended") {
      if (baseRoll.result > 95) {
        rollData.highopen = true
        let newRoll = await new Roll("1d100").roll();
        await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
        rollData.rolls.push(newRoll);
        while (newRoll.result > 95) {
          newRoll = await new Roll("1d100").roll();
          await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
          rollData.rolls.push(newRoll);
        }
      }
    }
    // Compute total of rolls
    rollData.totalRolls = rollData.rolls.reduce((acc, roll) => Number(acc) + Number(roll.result), 0);
    rollData.totalFinal = rollData.totalRolls + Number(rollData.combatSituation) +  
      Number(rollData.lightningModifier) +
      Number(rollData.darknessModifier) +
      Number(this.actor.system.modifiers.woundsModifier) + 
      Number(formData.difficulty) + 
      Number(rollData.hitsPerRound) +
      Number(rollData.stunnedModifier) +
      Number(this.characterBonus);
    console.log(">>> Roll Data: ", rollData);

    // Manage weapon table 

    if (this.weapon) {
      let hasFumble = false
      if ( rollData.totalRolls <= this.weapon.system.fumble_value ) {
        hasFumble = true
      } 

      let attackResult = game.rmfrp.attackTables.getAttackRollResult(this.weapon.system.attack_table, rollData.totalFinal, rollData.targetArmorClass)
      if ( !attackResult) {
        ui.notifications.error("Attack table not found: " + this.weapon.system.attack_table);
        return
      }
      if (typeof attackResult == "object") { // Why ?????
        attackResult = attackResult[String(rollData.targetArmorClass)];
      }
      console.log("Attack Result: ", attackResult); 
      rollData.attackResult = attackResult;
      // Is it a a critical ?
      let critical = attackResult.match(/(\d+)(\w)?(\w)?/);
      if (critical && critical[2]) {
        if ( critical[2] === "F") {
          hasFumble = true 
        } else {
          let criticalTable = this.weapon.system.critical_table
          if ( !criticalTable ) {
            ui.notifications.error("Critical table not found for weapon: " + this.weapon.name);
            return
          }
          let criticalResult = await game.rmfrp.attackTables.getCriticalResult(criticalTable, critical[2]);
          rollData.criticalResult = criticalResult;
          console.log("Critical Result: ", criticalResult);
        }
      }

      if (hasFumble) {
        let fumbleResult = await game.rmfrp.attackTables.getFumbleRollResult(this.weapon.system.fumble_table, this.weapon.system.fumble_column)
        if ( !fumbleResult) {
          ui.notifications.error("Fumble table not found: " + this.weapon.system.attack_table);
          return
        }
        rollData.fumbleResult = fumbleResult;
      }

    }

    // Define the Chat Message Template
    let chatTemplate = "systems/fvtt-rolemaster-frp/templates/chat/chat_dice_roll.html";
    console.log("Final rollData", rollData)

    // Pass the Data through to be used in the Chat Message
    let chatData = rollData
    // Render the Rolls to the Chat Window
    renderTemplate(chatTemplate, chatData).then((html) => {
      let chatOptions = {
        flavor: rollType,
        rollMode: game.settings.get("core", "rollMode"),
        content: html,
      };
      ChatMessage.create(chatOptions);
    });
  }

}
