/* -------------------------------------------- */
import { VadentisUtility } from "./vadentis-utility.js";

/* -------------------------------------------- */
const MIN_PV = -50;
const MIN_PE = -50;

/* -------------------------------------------- */
/**
 * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system.
 * @extends {Actor}
 */
export class VadentisActor extends Actor {

  /* -------------------------------------------- */
  /**
   * Override the create() function to provide additional SoS functionality.
   *
   * This overrided create() function adds initial items 
   * Namely: Basic skills, money, 
   *
   * @param {Object} data        Barebones actor data which this function adds onto.
   * @param {Object} options     (Unused) Additional options which customize the creation workflow.
   *
   */

  static async create(data, options) {

    // Case of compendium global import
    if (data instanceof Array) {
      return super.create(data, options);
    }
    // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic
    if (data.items) {
      let actor = super.create(data, options);
      return actor;
    }

    return super.create(data, options);
  }

  /* -------------------------------------------- */
  async prepareData() {
    super.prepareData();
  }

  /* -------------------------------------------- */
  getCompetences() {
    return this.data.items.filter( item => item.type == 'competence');
  }

  /* -------------------------------------------- */
  getDonnees()   {
    return this.data.items.filter( item => item.type == 'donnee');
  }
  /* -------------------------------------------- */
  getEglises()   {
    return this.data.items.filter( item => item.type == 'eglise');
  }
  /* -------------------------------------------- */
  getSorts() {
    return this.data.items.filter( item => item.type == 'sort');
  }
  /* -------------------------------------------- */
  getAttributs() {
    return this.data.items.filter( item => item.type == 'attribut');
  }
  /* -------------------------------------------- */
  getTechniques() {
    return this.data.items.filter( item => item.type == 'technique');
  }
  /* -------------------------------------------- */
  getDevotions() {
    return this.data.items.filter( item => item.type == 'devotion');
  }
  /* -------------------------------------------- */
  getEquipements() {
    return this.data.items.filter( item => item.type == 'equipement'  );
  }
  /* -------------------------------------------- */
  getArmes() {
    return this.data.items.filter( item => item.type == 'armecc' || item.type == 'tir' );
  }
  /* -------------------------------------------- */
  getArmures() {
    return this.data.items.filter( item => item.type == 'armurebouclier' );
  }
  
  /* -------------------------------------------- */
  async updateCompetence( name, field, value) {
    let competence = this.data.items.find( item => item.type == 'competence' && item.name == name);
    if (competence) {
      let dataPath = 'data.'+field;
      await this.updateOwnedItem( { _id: competence._id, [dataPath]:value });
    }
  }
  
  /* -------------------------------------------- */
  async equiperObject( equipementId ) {    
    let item = this.getOwnedItem(equipementId);
    if (item && item.data.data) {
      let update = { _id: item._id, "data.equipee": !item.data.data.equipee };
      await this.updateEmbeddedEntity("OwnedItem", update);
    }
  }

  /* -------------------------------------------- */
  calculerSommeStats( ) {
    for (const key in this.data.data.combat) {
      let combatData  = this.data.data.combat[key];
      combatData.total = combatData.base + combatData.malus + combatData.bonus;      
    }
    for (const key in this.data.data.magie) {
      let magieData  = this.data.data.magie[key];
      magieData.total = magieData.base + magieData.malus + magieData.bonus;      
    }
  }

  /* -------------------------------------------- */
  async processSortDevotion( name, devotionSort ) {
    if ( this.data.data.stats.pointsenergie.value == 0) { // Vérification du ~ de points d'énergie
      ChatMessage.create({ content: `${this.name} n'a pas assez de Points d'Energie pour lancer ${name} ${devotionSort.name}` } );        
      return;
    }
    
    let scores = this.data.data.magie[(name =="devotion") ? 'devotion': 'matriseelementaire'];
    let statValue = scores.base + scores.malus + scores.bonus;
    let formulaFull = this.buildTexteFormula( scores );
    let myRoll = await VadentisUtility.processRoll("1d20+"+statValue );
    let msgData = {
      alias: this.name, 
      title: `Sort ${devotionSort.name}`,
      isSort: true
    }

    if (myRoll.results[0] > 1 && myRoll.total >= devotionSort.data.difficulty) {
      msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_sort_réussi.webp';
      msgData.msg =  `${this.name} a réussi son ${name} et perd ${devotionSort.data.pe} Points d'Energie (lancer : ${formulaFull} => <strong>${myRoll.total} / ${devotionSort.data.difficulty}</strong>).`;  

      let maintain = (devotionSort.data.ismaintain)?"Oui":"Non";
      let complex  = (devotionSort.data.complexactions)?"Oui":"Non";
      msgData.msg += `<br>Peut être maintenu: ${maintain}<br>Actions complexes : ${complex}`;
      msgData.msg += `<br><strong>Description : </strong>${devotionSort.data.notes.replace(/<\/?[^>]+(>|$)/g, "")}`;
      let newEnergie = this.data.data.stats.pointsenergie.value - devotionSort.data.pe;
      await this.update( {'data.stats.pointsenergie.value': newEnergie });
      if (myRoll.results[0] >= devotionSort.data.valuecritical ) { // Critique ?
        msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_réussite_critique.webp';
        msgData.msg += "<br>C'est une <strong>réussite critique</strong> !";
        msgData.msg += `<br><strong>Effet critique : </strong>${devotionSort.data.criticaleffect.replace(/<\/?[^>]+(>|$)/g, "")}`;
      } else {
        msgData.msg += `<br><strong>Effet : </strong>${devotionSort.data.effect.replace(/<\/?[^>]+(>|$)/g, "")}`;
      }

      if ( devotionSort.data.damage != "") {
        let formula = devotionSort.data.damage;
        if (myRoll.results[0] >= devotionSort.data.valuecritical ) { // Critique ?
          msgData.msg += `<br>Et provoque les dégats critiques suivants : `;
          formula = devotionSort.data.damagecritical;
        } else {
          msgData.msg += `<br>Et provoque les dégats suivants : `;
        }
      }
      if ( newEnergie < 0) {
        msgData.msg += `<br><strong>Attention</strong> : Les Points d'Energie de ${this.name} sont négatifs ! Il convient d'éditer ses Points de Vie en conséquence.`;
      }
    } else {
      msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_sort_échoué.webp';
      if (myRoll.results[0] == 1 ) { // Critique ?
        msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_échec_critique.webp';
        msgData.msg = `${this.name} a fait un <strong>échec critique</strong> à son lancer de ${name}`;
      } else {
        msgData.msg = `${this.name} a échoué son lancer de ${name}`;
      }
    }
    console.log(devotionSort.data.description, msgData);
    ChatMessage.create({
      //whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
      content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
    });
}

  /* -------------------------------------------- */
  async rollDamage( weapon, damageType ) {
    let formula = VadentisUtility.processDamageString( weapon.data.data[damageType], this );
    let degatsRoll = await VadentisUtility.processRoll( formula );
    let msgData = {
      alias: this.name, 
      img: "systems/foundryvtt-vadentis/images/icons/tchat_dégâts_infligés.webp",
      title: `Dégâts de ${weapon.name}`,
      msg: `${this.name} frappe avec ${weapon.name} et produit <strong>${degatsRoll.total} Points de Dégâts</strong> (${formula}).`
    }
    ChatMessage.create({
      //whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
      content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
    });
  }

  /* -------------------------------------------- */
  async applyDamage( damageValue ) {
    let pvData = this.data.data.stats.pointsvie;
    let newValue = Math.max( pvData.value - damageValue, MIN_PV);
    await this.update( {'data.stats.pointsvie.value': newValue });

    let msgData = {
      alias: this.name, 
      img: "systems/foundryvtt-vadentis/images/icons/tchat_dégâts_infligés.webp",
      title: `${this.name} encaisse des dégâts !`,
      msg: `${this.name} vient de perdre ${damageValue} Points de Vie. Ses Points de Vie actuels sont désormais de ${newValue}.`
    }
    ChatMessage.create({
      //whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
      content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
    });
  }

  /* -------------------------------------------- */
  _getCombatValue(mydata) {
    if ( typeof mydata.base == 'number' ) {
      return mydata.base + mydata.malus + mydata.bonus;
    } else {
      return Number(mydata.base[0]) + Number(mydata.malus[0]) + Number(mydata.bonus[0]);
    }
  }

  /* -------------------------------------------- */
  getInitiativeScore(  ) {
    let initData = this.data.data.combat.initiative;
    return this._getCombatValue( initData);
  }
  /* -------------------------------------------- */
  getDefenseScore(  ) {
    let defenseData = this.data.data.combat.defense;
    return this._getCombatValue( defenseData);
  }
  /* -------------------------------------------- */
  getForceScore(  ) {
    let forceData = this.data.data.combat.force;
    return this._getCombatValue( forceData);
  }
  /* -------------------------------------------- */
  getAttaqueScore(  ) {
    let attaqueData = this.data.data.combat.attaque;
    return this._getCombatValue( attaqueData);
  }

  /* -------------------------------------------- */
  buildTexteFormula( stat) {
    let signMalus = (stat.malus < 0) ? "" : "+";
    return `1d20+ ${stat.base} ${signMalus} ${stat.malus} + ${stat.bonus}`;
  }

  /* -------------------------------------------- */
  async rollSort( sortId ) {
    let sort = this.data.items.find( item => item.type == 'sort' && item._id == sortId );
    if ( sort ) {
      this.processSortDevotion( "sort", sort);
    }
  }

  /* -------------------------------------------- */
  async rollDevotion( devotionId ) {
    let devotion = this.data.items.find( item => item.type == 'devotion' && item._id == devotionId );
    if ( devotion ) {
      this.processSortDevotion( "devotion", devotion);
    }
  }

  /* -------------------------------------------- */
  async rollTechnique( techniqueId ) {
    let technique = this.data.items.find( item => item.type == 'technique' && item._id == techniqueId );
    if (technique) {
      let msgData = {
        alias: this.name, 
        img: technique.img,
        title: `Technique ${technique.name}` 
      }
      if ( this.data.data.stats.pointsadrenaline.value < technique.data.pacost) { // Vérification du ~ de points d'adrénaline
        msgData.msg = `${this.name} n'a pas assez de Points d'Adrénaline pour éxecuter sa technique ${technique.name}`;
      } else {
        let newAdrenaline = this.data.data.stats.pointsadrenaline.value - technique.data.pacost;
        await this.update( {'data.stats.pointsadrenaline.value': newAdrenaline });
        msgData.msg = `${this.name} execute sa technique ${technique.name}, pour un côut de ${technique.data.pacost} Points d'Adrénaline<br>
            Les effets sont : ${technique.data.effect}`;
      }
      ChatMessage.create({
        //whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
        content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
      });
    } else {
      ui.notifications.warn("Technique non trouvée");
    }
  }

  /* -------------------------------------------- */
  async rollCompetence( competenceId ) {
    let competence = this.data.items.find( item => item.type == 'competence' && item._id == competenceId);
    if ( competence) {
      let msgData = {
        alias: this.name, 
        img: competence.img,
        title: `Compétence ${competence.name}` 
      }

      let statValue = competence.data.base + competence.data.malus + competence.data.bonus;
      let formulaFull = this.buildTexteFormula( competence.data );
      let myRoll = await VadentisUtility.processRoll("1d20+"+statValue );
      msgData.msg = `${formulaFull} => <strong>${myRoll.total}</strong>`; 
      
      if (myRoll.results[0] == 1 ) { // Critique ?
        msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_échec_critique.webp';
        msgData.msg += `<br>C'est un <strong>échec critique</strong> !`;
      }
      if (myRoll.results[0] == 20 ) { // Critique ?
        msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_réussite_critique.webp';
        msgData.msg += `<br>C'est une <strong>réussite critique</strong> !`;
      }

      ChatMessage.create({
        //whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
        content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
      });
    } else {
      ui.notifications.warn("Compétence non trouvée");
    }
  }

  /* -------------------------------------------- */
  async genericRoll( stat, key ) {
    let statValue = this._getCombatValue( stat );
    let formulaFull = this.buildTexteFormula( stat );
    
    
    let myRoll = await VadentisUtility.processRoll("1d20+"+statValue );
    let msgData = {
      alias: this.name, 
      img: `systems/foundryvtt-vadentis/images/icons/feuille_perso_${key}.webp`,
      title: VadentisUtility.buildJetText( stat),
      msg: `${formulaFull} => <strong>${myRoll.total}</strong>` 
    }

    if (myRoll.results[0] == 1 ) { // Critique ?
      msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_échec_critique.webp';
      msgData.msg += `<br>C'est un <strong>échec critique</strong> !`;
    }
    if (myRoll.results[0] == 20 ) { // Critique ?
      msgData.img = 'systems/foundryvtt-vadentis/images/icons/tchat_réussite_critique.webp';
      msgData.msg += `<br>C'est une <strong>réussite critique</strong> !`;
    }

    ChatMessage.create({
      //whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
      content: await renderTemplate(`systems/foundryvtt-vadentis/templates/chat-generic-result.html`, msgData)
    });
  }

  /* -------------------------------------------- */
  async rollCombat( combatName ) {
    let stat = this.data.data.combat[combatName];
    this.genericRoll( stat, combatName );
}

  /* -------------------------------------------- */
  rollMagie( magieName ) {
    let stat = this.data.data.magie[magieName];
    this.genericRoll( stat, magieName );
  }
  
  /* -------------------------------------------- */
  rollArme(armeId) {
    let target = VadentisUtility.getTarget();

    if ( target ) {
      let arme = this.data.items.find( item => (item.type == 'armecc' || item.type == 'tir') && item._id == armeId);
      if (arme) {
        let combatData = { 
          attackerActorId: this._id,
          targetActorId: target.actor._id,
          arme: duplicate(arme) 
        }
        if (game.user.isGM) {
          VadentisUtility.performAttack( combatData);
        } else {
          game.socket.emit("system.foundryvtt-vadentis", { name: "msg_attack", data: { combatData } } );
        }
      }
    } else {
      ui.notifications.warn("Vous devez désigner une cible pour attaquer avec une arme.")
    }
  }
  
}
