/************************************************************************************/
import statParserFR from "./modules/import-stat-2.js";

/************************************************************************************/
var compmod = "wfrp4e";
const vo_conditions = {     
    "ablaze": "Ablaze",
    "bleeding": "Bleeding",
    "blinded": "Blinded",
    "broken": "Broken",
    "deafened": "Deafened",
    "entangled": "Entangled",
    "fatigued": "Fatigued",
    "poisoned": "Poisoned",
    "prone": "Prone",
    "stunned": "Stunned",
    "surprised": "Surprised",
    "unconscious": "Unconscious",
    "grappling": "Grappling",
    "fear": "Fear",
    "defeated": "Defeated"
}

/************************************************************************************/
Hooks.once('init', () => {

  // Check various settings in the installation  
  game.modules.forEach((module, name) => {
    if ( name == "wfrp4e-core" && module.active) {
      compmod = "wfrp4e-core";
    }
  } );
  game.wfrp4efr = { compmod: compmod,
    vo_conditions: vo_conditions }
  
  game.wfrp4e.apps.StatBlockParser.parseStatBlock = async function( statString, type = "npc") {
      return statParserFR( statString, type);
    }
    
  /*---------------------------------------------------------------------*/
  game.wfrp4e.utility.handleConditionClick = function(event) {
    let cond = $(event.currentTarget).attr("data-cond")
    if (!cond)
      cond = event.target.text;
    cond = cond.trim();
    let condkey
    // En vo, les noms d'états sont égaux aux clés en minuscules
    if ( game.wfrp4e.config.conditions[cond.toLowerCase()] ) {
      condkey = cond.toLowerCase();
    } else {
      try {
        condkey = game.wfrp4e.utility.findKey(cond.toLowerCase(), game.wfrp4e.config.conditions, {caseInsensitive: true});
      }
      catch {
        ui.notifications.error("L'état est inconnu : " + cond);
      }
    } 
    let condName = game.wfrp4e.config.conditions[condkey];
    let condDescr = game.wfrp4e.config.conditionDescriptions[condkey];
    let messageContent = `<b>${condName}</b><br>${condDescr}`

    let chatData = game.wfrp4e.utility.chatDataSetup(messageContent)
    ChatMessage.create(chatData);
  }

  /*---------------------------------------------------------------------*/
  game.wfrp4e.entities.ItemWfrp4e.prototype.computeSpellDamage = function(formula, isMagicMissile) {
    try {

      formula = formula.toLowerCase();

      if (isMagicMissile) // If it's a magic missile, damage includes willpower bonus
      {
        formula += "+ " + this.actor.characteristics["wp"].bonus
      }

      // Specific case, to avoid wrong matching with "Force"
      if (formula.includes("toughness bonus"))  {
        formula = formula.replace( "toughness bonus", this.actor.characteristics["t"].bonus);
      }

      // Specific case, to avoid wrong matching with "Force"
      if (formula.includes("force mentale")) 
      {
        // Determine if it's looking for the bonus or the value
        if (formula.includes('bonus')) {
          formula = formula.replace( "bonus de force mentale", this.actor.characteristics["wp"].bonus);
          formula = formula.replace( "force mentale bonus", this.actor.characteristics["wp"].bonus);
        } else
          formula = formula.replace("force mentale",  this.actor.characteristics["wp"].value);
      }

      // Iterate through characteristics
      for(let ch in this.actor.characteristics)
      { 
        // If formula includes characteristic name
        while (formula.includes(this.actor.characteristics[ch].label.toLowerCase()))
        {
          // Determine if it's looking for the bonus or the value
          if (formula.includes('bonus')) {
            formula = formula.replace("bonus de " + game.wfrp4e.config.characteristics[ch].toLowerCase(),  this.actor.characteristics[ch].bonus);
            formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase() + " bonus",  this.actor.characteristics[ch].bonus);
          }
          else
            formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase(),  this.actor.characteristics[ch].value);
        }
      }

      return eval(formula);
    }
    catch (e) {
      throw ui.notifications.error("Error: could not parse spell damage. See console for details")
    }
  }

  /*---------------------------------------------------------------------*/
  game.wfrp4e.entities.ItemWfrp4e.prototype.computeSpellPrayerFormula = function(type, aoe=false, formulaOverride) {
    let formula = formulaOverride || this[type]?.value
    if (Number.isNumeric(formula))
      return formula

    //console.log("Compute FR")
    formula = formula.toLowerCase();

    // Do not process these special values
    if (formula != game.i18n.localize("You").toLowerCase() && formula != game.i18n.localize("Special").toLowerCase() && formula != game.i18n.localize("Instant").toLowerCase())
    {
      // Specific case, to avoid wrong matching with "Force"
      if (formula.includes("force mentale")) 
      {
        // Determine if it's looking for the bonus or the value
        if (formula.includes('bonus')) {
          formula = formula.replace( "bonus de force mentale",  this.actor.characteristics["wp"].bonus);
          formula = formula.replace( "force mentale bonus",  this.actor.characteristics["wp"].bonus);
        }
        else
          formula = formula.replace("force mentale",  this.actor.characteristics["wp"].value);
      }
      if (formula.includes("yard") )
        formula = formula.replace('yard', "mètre" );
      if (formula.includes("yds") )
        formula = formula.replace('yds', "m." );
      // Iterate through remaining characteristics
      for(let ch in this.actor.characteristics)
      {
        // If formula includes characteristic name
        //console.log("Testing :", ch, WFRP4E.characteristics[ch].toLowerCase());
        if (formula.includes(game.wfrp4e.config.characteristics[ch].toLowerCase()))
        {
          // Determine if it's looking for the bonus or the value
          if (formula.includes('bonus')) {
            formula = formula.replace("bonus de " + game.wfrp4e.config.characteristics[ch].toLowerCase(),  this.actor.characteristics[ch].bonus);
            formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase() + " bonus",  this.actor.characteristics[ch].bonus);
          }
          else
            formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase(),  this.actor.characteristics[ch].value);
        }
      }
    }

    // If AoE - wrap with AoE ( )
    if (aoe)
      formula = "AoE (" + formula.capitalize() + ")";
    
    //console.log("calculateSpellAttributes -> " + formula );
    return formula.capitalize();
  }

  /*---------------------------------------------------------------------*/
  // Converters area
  if(typeof Babele !== 'undefined') {
		
		Babele.get().register({
			module: 'WH4-fr-translation',
			lang: 'fr',
			dir: 'compendium'
		});
        
    Babele.get().registerConverters({

      "career_skills": (skills_list) => {
        //console.log( "Thru here ...", compendium, skills_list);
        if ( skills_list ) { 
          var i;
          var len = skills_list.length;
          var re  = /(.*)\((.*)\)/i;
          for (i = 0; i < len; i++) {
            skills_list[i] = skills_list[i].trim();
            var transl = game.babele.translate(compmod+'.skills', { name: skills_list[i] }, true ).name;
            //console.log("List ...", skills_list[i]);
            if ( transl == skills_list[i] ) {            
              var res = re.exec( skills_list[i] );
              if (res) { 
                //console.log("Matched/split:", res[1], res[2]);
                var subword = game.i18n.localize(res[2].trim() );
                var s1 = res[1].trim() + " ()";
                var translw = game.babele.translate(compmod+'.skills', { name: s1}, true ).name;              
                if (translw != s1) {
                  var res2 = re.exec(translw);
                  transl = res2[1] + "(" + subword  + ")";
                } else {
                  s1 = res[1].trim() + " ( )";
                  translw = game.babele.translate(compmod+'.skills', { name: s1}, true ).name;
                  var res2 = re.exec(translw);
                  transl = res2[1] + "(" + subword  + ")";
                }  
              }
            }
            skills_list[i] = transl;
          }
        }
        return skills_list;  
      },
      
      "npc_details": (details) => {
        //console.log("DETAILS: ", details);
        let newDetails = duplicate(details);
        if (details.species && details.species.value )
          newDetails.species.value = game.i18n.localize(details.species.value);
        if (details.gender && details.gender.value )
          newDetails.gender.value  = game.i18n.localize(details.gender.value);
        if (details.class && details.class.value )
          newDetails.class.value   = game.i18n.localize(details.class.value);
        return newDetails;
      },

      "career_talents": (talents_list) => { 
        var compendium = game.packs.find(p => p.collection === compmod+'.talents');
        var i;
        if ( talents_list ) {
          var len = talents_list.length;
          var re  = /(.*)\((.*)\)/i;
          for (i = 0; i < len; i++) {
            var transl = game.babele.translate(compmod+'.talents', { name: talents_list[i]}, true ).name;
            if ( transl == talents_list[i] ) {            
              var res = re.exec( talents_list[i]);
              if (res) { 
                //console.log("Matched/split:", res[1], res[2]);
                var subword = game.i18n.localize(res[2].trim() );
                var s1 = res[1].trim(); // No () in talents table
                var translw = game.babele.translate(compmod+'.talents', { name: s1 }, true ).name;
                if (translw != s1) {
                  transl = translw + " (" + subword  + ")";
                } else {
                  s1 = res[1].trim() + " ( )";
                  translw = game.babele.translate(compmod+'.talents', { name: s1 }, true ).name;
                  var res2 = re.exec(translw);
                  transl = res2[1] + " (" + subword  + ")";
                }  
              }
            }
            talents_list[i] = transl;
          }
        }
        return talents_list;      
      },
      "npc_characteristics": (chars) => { // Auto-convert char names in the sheet
        for (var key in chars) {
          var char  = chars[key];
          //console.log("Was here !", key, char ); 
          var abrev = char["abrev"];
          let toTransl = "CHAR." + abrev;
          if ( game.i18n.localize( toTransl ) != toTransl) { // Manages unknown language
            char["label"] = game.i18n.localize( "CHAR." + abrev );
            char["abrev"] = game.i18n.localize( "CHARAbbrev." + abrev );
          }
        }
        return chars;
      },
      "bestiary_traits": (beast_traits, translations) => {        
        
        for (let trait_en of beast_traits)
        { 
          var special = "";
          var nbt = "";
          var name_en = trait_en.name.trim(); // strip \r in some traits name
            
          if ( trait_en.type == "trait") {
            if ( name_en.includes("Tentacles") ) { // Process specific Tentacles case
              var re  = /(.d*)x Tentacles/i;
              var res = re.exec( name_en );
              if ( res && res[1] ) 
                nbt = res[1] + "x ";
              name_en = "Tentacles";
            } else if ( name_en.includes("(") && name_en.includes(")") ) { // Then process specific traits name with (xxxx) inside
              var re  = /(.*) \((.*)\)/i;
              var res = re.exec( name_en );          
              name_en = res[1]; // Get the root traits name
              special = " (" + game.i18n.localize( res[2].trim() ) + ")"; // And the special keyword
            }
            var trait_fr = game.babele.translate( compmod+'.traits', { name: name_en }, true );
            //console.log(">>>>> Trait ?", name_en, nbt, trait_fr, trait_fr.name, special);
            trait_en.name = nbt + trait_fr.name + special;
            if ( trait_fr.data && trait_fr.data.description && trait_fr.data.description.value ) {
                trait_en.data.description.value = trait_fr.data.description.value;
            } else if ( game.modules.get( 'wfrp4e-eis') ) { // No description in the FR compendium -> test other compendium if presenr
                trait_fr = game.babele.translate( 'wfrp4e-eis.eisitems', { name: name_en }, true);
                trait_en.name = nbt + trait_fr.name + special;
                if ( trait_fr.data && trait_fr.data.description && trait_fr.data.description.value )
                  trait_en.data.description.value = trait_fr.data.description.value;              
              }
              if ( trait_en.data && trait_en.data.specification && isNaN(trait_en.data.specification.value) ) { // This is a string, so translate it
                //console.log("Translating : ", trait_en.data.specification.value);            
                trait_en.data.specification.value = game.i18n.localize( trait_en.data.specification.value.trim() );            
              }
          } else if ( trait_en.type == "skill") {
            if ( name_en.includes("(") && name_en.includes(")") ) { // Then process specific skills name with (xxxx) inside
              var re  = /(.*) +\((.*)\)/i;
              var res = re.exec( name_en );
              name_en = res[1].trim(); // Get the root skill name
              special = " (" + game.i18n.localize( res[2].trim() ) + ")"; // And the special keyword
            }
            var trait_fr = game.babele.translate( compmod+'.skills', { name: name_en }, true );
            //console.log(">>>>> Skill ?", name_en, special, trait_fr.name, trait_fr);
            if (trait_fr.name != name_en) { // Translation OK
              trait_en.name = trait_fr.name + special;
              if ( trait_fr.data ) {
                trait_en.data.description.value = trait_fr.data.description.value;
              }
            }
          
          } else if ( trait_en.type == "prayer") {
            var trait_fr = game.babele.translate( compmod+'.prayers', { name: name_en }, true);
            //console.log(">>>>> Prayer ?", name_en, special, trait_fr.name );
            trait_en.name = trait_fr.name + special;
            if ( trait_fr.data && trait_fr.data.description && trait_fr.data.description.value )
              trait_en.data.description.value = trait_fr.data.description.value;                                      
          
          } else if ( trait_en.type == "spell") {
            var trait_fr = game.babele.translate( compmod+'.spells', { name: name_en }, true);
            if ( trait_fr.name == name_en  ) { // If no translation, test eisspells
              trait_fr = game.babele.translate( 'wfrp4e-eis.eisspells', { name: name_en }, true); 
            }
            if ( trait_fr.name == name_en ) { // If no translation, test unofficial grimoire
              trait_fr = game.babele.translate( 'wfrp4e-unofficial-grimoire.ug-spells', { name: name_en }, true);  
            }
            //console.log(">>>>> Spell ?", name_en, special, trait_fr.name );
            trait_en.name = trait_fr.name + special;
            if ( trait_fr.data && trait_fr.data.description && trait_fr.data.description.value )
              trait_en.data.description.value = trait_fr.data.description.value;                          
          } else if ( trait_en.type == "talent") {
            if ( name_en.includes("(") && name_en.includes(")") ) { // Then process specific skills name with (xxxx) inside
              var re  = /(.*) +\((.*)\)/i;
              var res = re.exec( name_en );
              name_en = res[1].trim(); // Get the root talent name, no parenthesis this time...
              special = " (" + game.i18n.localize( res[2].trim() ) + ")"; // And the special keyword
            }
            var trait_fr = game.babele.translate( compmod+'.talents', { name: name_en }, true );
            //console.log(">>>>> Talent ?", name_en, special, trait_fr.name);
            if ( trait_fr.name == name_en) { // If no translation, test ugtalents
              trait_fr = game.babele.translate( 'wfrp4e-unofficial-grimoire.ug-careerstalentstraits', { name: name_en }, true );
            }
            if ( trait_fr.name != name_en)  { // Talent translated!
              trait_en.name = trait_fr.name.trim() + special;
              if ( trait_fr.data ) { // Why ???
                trait_en.data.description.value = trait_fr.data.description.value;
              }
            }
          } else if ( trait_en.type == "career") {
            var career_fr = game.babele.translate( compmod+'.careers', trait_en, true );
            console.log(">>>>> Career ?", name_en, career_fr.name );
            trait_en.name = career_fr.name;
            trait_en.data = duplicate(career_fr.data);
          } else if ( trait_en.type == "trapping" || trait_en.type == "weapon" || trait_en.type == "armour" || trait_en.type == "container" || trait_en.type == "money") {
            var trapping_fr = game.babele.translate( compmod+'.trappings',  trait_en, true );
            //console.log(">>>>> Trapping ?", name_en, trapping_fr.name);
            trait_en.name = trapping_fr.name;
            if ( trapping_fr.data) {
              trait_en.data.description  = trapping_fr.data.description;
            }
          }
        }
        return beast_traits;
      },
      // To avoid duplicateing class for all careers
      "generic_localization": (value) => { 
        if ( value )
          return game.i18n.localize( value.trim() );
      },      
      "trapping_qualities_flaws": (value) => {
        if ( value ) { 
          let newQF = [];
          //console.log("ATOUTS", value);
          var i=0;
          //var re  = /(.*) (\d+)/i;        
          for (i=0; i<value.length; i++) {
            newQF[i] = duplicate(value[i]);
            if ( newQF[i].name == "Trap Blade") {
              newQF[i].name = "TrapBlade"; // Auto-patch, without space!
              //console.log("PATCHED", trim);
            }
            newQF[i].name = game.i18n.localize( newQF[i].name ) ;
          }
          return newQF;
        }
      },
      // Search back in careers the translated name of the groupe (as it is the name of the level career itself)
      "career_careergroup": (value) => { 
        // Manage exception - Dirty hack
        if ( value == 'Slayer' ) {
          return "Tueur";
        }
        if ( value == 'Druidic Priest' ) {
          return "Druide";
        }
        // Per default
        var compendium = game.packs.find(p => p.collection === compmod+'.careers');
        if ( compendium )
          return game.babele.translate(compmod+'.careers', { name: value } ).name;
        else 
          ui.notifications.error("Impossible de trouver la carrière " + value + ". Elle n'est probablement pas traduite.", { permanent: true })
      },
      "mutations_modifier": (value) => { // This is really UGLYYYY i know, but i started like this and discovered afterward that many strings were not easy to automate... Sorry :)
        //console.log("Parsing mutation :", value);
        value = value.toLowerCase();        
        value = value.replace("gain a broken condition if you fail a test derived from ", "Gagnez un état Brisé si vous échouez à un test dérivé de ");
        value = value.replace("weapon skill" ,"Capacité de Combat");
        value = value.replace("ballistic skill", "Capacité de Tir");
        value = value.replace("strength", "Force");
        value = value.replace("toughness", "Endurance");
        value = value.replace("agility", "Agilité");
        value = value.replace("dexterity", "Dextérité");
        value = value.replace("willpower", "Force Mentale");
        value = value.replace("fellowship", "Sociabilité");
        value = value.replace("initiative", "Initiative");
        value = value.replace("intelligence", "Intelligence");
        value = value.replace("armor points to the head", "PA à la Tête");
        value = value.replace("subject to frenzy", "Sujet à la Frénésie");
        value = value.replace("you do not scar", "Aucune cicatrice");
        value = value.replace("movement", "Mouvement");
        value = value.replace("armor points to all locations", "PA sur tout le corps");
        value = value.replace("to any test when alone", "à tout les tests lorsque seul");
        value = value.replace("track", "Pistage");
        value = value.replace("to any test not hurting another", "à tout les Tests n'aggressant pas autrui");
        value = value.replace("on tests to hurt", "pour les tests impliquant une agression")
        value = value.replace("to all language tests when speaking", "à tout les Tests de Langue lorsque vous parlez");
        value = value.replace("on perception tests involving sight", "aux Tests de Perception impliquant la Vue");
        value = value.replace("to all Sociabilité tests", "à tout les Tests de Sociabilité");
        return value;
      },
      "talent_name": (name, translation) => {
        console.log("NAME !!!", name, translation);
      },
      "effects": (effects, translations) => {         
        if ( !effects) return;
        if ( !translations) return;
        for (let i=0; i<effects.length; i++) {
          let effect = effects[i];
          //console.log("EFFECT LABEL1:", effect );
          effect.label = translations['label'+i];
        }
        return effects
      },
      "diseases_effects": (effects, translations) => { 
        if ( !effects) return;
        for (let i=0; i<effects.length; i++) {
          let effect = effects[i];
          let label = effect.label;
          let gravity = "";
          if ( label.includes("(") && label.includes(")") ) { // Then process specific skills name with (xxxx) inside
            var re  = /(.*) +\((.*)\)/i;
            var res = re.exec( label );
            label = res[1].trim(); // Get the gravity
            gravity = " (" + game.i18n.localize( res[2].trim() ) + ")"; // And the special keyword
          }
          effect.label = game.i18n.localize( label ) + gravity;
        }
      },
      // Auto-translate duration
      "spells_duration_range_target_damage": (value) => {
        //console.log("Spell duration/range/damage/target :", value);
        if ( value == "" ) return ""; // Hop !
        if ( value == "Touch" ) return "Contact"; // Hop !
        if ( value == "You" ) return "Vous"; // Hop !        
        if ( value == "Instant" ) return "Instantané"; // Hop !
        var translw = value;
        var re  = /(.*) Bonus (\w*)/i;
        var res = re.exec( value );
        var unit = "";
        if ( res ) { // Test "<charac> Bonus <unit>" pattern
          if ( res[1] ) { // We have char name, then convert it
            translw = "Bonus de " + game.i18n.localize(  res[1].trim()  );
          }           
          unit = res[2];
        } else { 
          re = /(\d+) (\w+)/i;
          res = re.exec( value );
          if (res) { // Test : "<number> <unit>" pattern
            translw  = res[1];
            unit = res[2];
          } else { // Test 
            re = /(\w+) (\w+)/i;
            res = re.exec( value );
            if (res) { // Test : "<charac> <unit>" pattern
              translw  = game.i18n.localize( res[1].trim() );
              unit = res[2];
            } 
          }
        } 
        if ( unit == "hour") unit = "heure";
        if ( unit == "hours") unit = "heures";
        if ( unit == "days") unit = "jours";            
        if ( unit == "yard") unit = "mètre";            
        if ( unit == "yards") unit = "mètres";            
        translw += " " + unit;
        return translw; 
      }
    });      
  }
  
} );

