/* -------------------------------------------- */  
import { VadentisCombat } from "./vadentis-combat.js";

/* -------------------------------------------- */  
export class VadentisUtility  {
  
  /* -------------------------------------------- */  
  static async preloadHandlebarsTemplates() {
    
    const templatePaths = [
      'systems/foundryvtt-vadentis/templates/actor-sheet.html',
      'systems/foundryvtt-vadentis/templates/item-sheet.html',
      'systems/foundryvtt-vadentis/templates/editor-notes-gm.html',
      'systems/foundryvtt-vadentis/templates/hud-actor-attaque.html',
      'systems/foundryvtt-vadentis/templates/hud-actor-sort.html'
    ]
    return loadTemplates(templatePaths);    
  }

  /* -------------------------------------------- */
  static updateCombat( combat, round, diff, id ) {
    if (game.user.isGM && combat.round != 0 && combat.turns && combat.active) {
      let turn = combat.turns.find(t => t.tokenId == combat.current.tokenId);
      ChatMessage.create( { content: `Round ${combat.round} : C'est au tour de ${turn.actor.name}<br>` } );

      canvas.tokens.get(turn.token._id).control();
      canvas.tokens.cycleTokens(1, true);
    }    
  }

  /* -------------------------------------------- */
  static createOptionList( min, max) {
    let options = ""
    for(let i=min; i<=max; i++) {
      options += `<option value="${i}">${i}</option>\n`;
    }
    return options;
  }

  /* -------------------------------------------- */
  static createDirectOptionList( min, max) {
    let options = {};
    for(let i=min; i<=max; i++) {
      options[`${i}`] = `${i}`;
    }
    return options;
  }
  /* -------------------------------------------- */
  static createDirectIntegerOptionList( min, max) {
    let options = {};
    for(let i=min; i<=max; i++) {
      options[i] = `${i}`;
    }
    return options;
  }
  /* -------------------------------------------- */
  static createDirectReverseOptionList( min, max) {
    let options = {};
    for(let i=max; i>=min; i--) {
      options[`${i}`] = `${i}`;
    }
    return options;
  }
  
  /* -------------------------------------------- */
  static getTarget() {
    if (game.user.targets && game.user.targets.size == 1) {
    for (let target of game.user.targets) {
      return target;
      }
    }
    return undefined;
  }
  
  /* -------------------------------------------- */
  static processDamageString( formula, actor ) {
    let workFormula = formula.toLowerCase();
    if ( workFormula.includes('bonus de force')) {
      workFormula = workFormula.replace('bonus de force', actor.getForceScore());
    }
    return workFormula;
  } 

  /* -------------------------------------------- */
  static async processRoll( formula, rollMode ) {
    let myRoll = new Roll(formula);
    myRoll.roll( { async: false} );
    if (game.modules.get("dice-so-nice")?.active) {
      await game.dice3d.showForRoll(myRoll, game.user, true);
    }
    return myRoll;
  }

  /* -------------------------------------------- */
  static async performAttack( combatData) {
    let attacker = game.actors.get(combatData.attackerActorId);
    let defender = game.actors.get(combatData.targetActorId);
    console.log("ATTACK !!", attacker, defender);
    if( attacker && defender) {
      let defense = defender.getDefenseScore();      
      let attaque = attacker.getAttaqueScore();

      let msgData = {
        alias: this.name, 
        title: `${attacker.name} attaque ${defender.name}`
      }
      
      let tirMsg = "";
      if ( combatData.arme.type == 'tir') {
        attacker.decrementeMunition(combatData.arme);
        tirMsg += `<br>C'est un tir, les munitions de l'attaquant ont été décrémentées`;
      }

      let formulaTouche = "1d20+"+attaque;
      let formulaFull = attacker.buildTexteFormula( attacker.system.combat.attaque );
      let myRoll = await this.processRoll(formulaTouche);
      if (myRoll.dice[0].results[0].result > 1 && myRoll.total >= defense) { // Success !
        let degats = `normaux : ${combatData.arme.system.damage}`;
        let formula = combatData.arme.system.damage.toLowerCase();
        msgData.msg = `${attacker.name} a réussi son attaque sur ${defender.name} (${formulaFull} => ${myRoll.total} / ${defense}) !<br> Les dégâts sont ${degats}.`;
        
        msgData.msg += tirMsg;
        if ( myRoll.dice[0].results[0].result >= combatData.arme.system.valuecritical ) {
          degats = `critiques : ${combatData.arme.system.criticaldamage}`;
          formula = combatData.arme.system.criticaldamage.toLowerCase();
          msgData.msg += `<br>C'est une <strong>réussite critique</strong> !`;
        }        
        msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_attaque_réussie.webp'
        
        formula = this.processDamageString( formula, attacker );        
        let degatsRoll = await this.processRoll(formula);
        msgData.msg +=`<br>Les dégats infligés sont de <strong>${degatsRoll.total}</strong> (${formula}).`;
        defender.applyDamage( degatsRoll.total );
      } else { //Echec
        msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_attaque_échouée.webp';
        if ( myRoll.dice[0].results[0].result == 1) {
          msgData.msg = `${attacker.name} a fait un <strong>échec critique</strong> et a raté son attaque sur ${defender.name} (${myRoll.total} / ${defense}) !`;
        } else {
          msgData.msg = `${attacker.name} a raté son attaque sur ${defender.name} (${myRoll.total} / ${defense}) !`;
        }
        msgData.msg += tirMsg;
      }
      ChatMessage.create({
        //whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
        content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
      });  
    } else {
      ui.notifications.warn("Impossible de trouver l'attaquant et le défenseur.")
    }
  }

  /* -------------------------------------------- */
  static buildJetText( stat) {
    let name = stat.label;
    let title = `Jet de ${name}`;
    if ( name.toLowerCase().substr(0,1).match(/[aeoiou]/g) ) {
      title = `Jet d'${name}`;
    } 
    return title;
  }
  
  /* -------------------------------------------- */
  static registerChatCallbacks( ) {

  }
  
  /* -------------------------------------------- */
  static fillRange (start, end) {
    return Array(end - start + 1).fill().map((item, index) => start + index);
  }
  
  /* -------------------------------------------- */
  static onSocketMesssage( msg ) {
    if( !game.user.isGM ) return; // Only GM

    if (msg.name == 'msg_attack' ) {
      this.performAttack( msg.data );
    }
  }

  /* -------------------------------------------- */
  static async loadCompendiumNames(compendium) {
    const pack = game.packs.get(compendium);
    let competences;
    await pack.getIndex().then(index => competences = index);
    return competences;
  }
  
  /* -------------------------------------------- */
  static async loadCompendium(compendium, filter = item => true) {
    let compendiumItems = await SoSUtility.loadCompendiumNames(compendium);

    const pack = game.packs.get(compendium);
    let list = [];
    for (let compendiumItem of compendiumItems) {
      await pack.getEntity(compendiumItem._id).then(it => {
        const item = it.data;
        if (filter(item)) {
          list.push(item);
        }
      });
    };
    return list;
  }

  /* -------------------------------------------- */
  static getDonnees( ) {
    return this.loadCompendiumNames('foundryvtt-vadentis.donnees');
  }
  /* -------------------------------------------- */
  static getEglises( ) {
    return this.loadCompendiumNames('foundryvtt-vadentis.eglises');
  }

  /* -------------------------------------------- */
  static async confirmDelete(actorSheet, li) {
    let itemId = li.data("item-id");
    let msgTxt = "<p>Etes vous certain de souhaiter supprimer cet item ?";
    let buttons = {
      delete: {
          icon: '<i class="fas fa-check"></i>',
          label: "Oui, à supprimer",
          callback: () => {
            actorSheet.actor.deleteEmbeddedDocuments('Item', [ itemId] );
            li.slideUp(200, () => actorSheet.render(false));
          }
        },
        cancel: {
          icon: '<i class="fas fa-times"></i>',
          label: "Annuler"
        }
      }
      msgTxt += "</p>";
      let d = new Dialog({
        title: "Confirmer la suppression",
        content: msgTxt,
        buttons: buttons,
        default: "cancel"
      });
      d.render(true);
  }

}