export class RMSSActor extends Actor {

  /** @override */
  prepareData() {
    // Prepare data for the actor. Calling the super version of this executes
    // the following, in order: data reset (to clear active effects),
    // prepareBaseData(), prepareEmbeddedDocuments() (including active effects),
    // prepareDerivedData().
    super.prepareData();
  }

  prepareDerivedData() {
    const actorData = this;
    const systemData = actorData.system;
    const flags = actorData.flags.rmss || {};

    // Make separate methods for each Actor type (character, npc, etc.) to keep
    // things organized.
    this._prepareCharacterData(actorData);
    this._prepareNpcData(actorData);
  }

  /**
   * Prepare Character specific data.
   * @param {Actor} actorData The NPC Object to prepare data for
   */
  _prepareCharacterData(actorData) {
    if (actorData.type !== "character") return;

    console.log("*****Flag", this.getFlag("world", "importing"));
    
    if (this.getFlag("world", "importing")) {
      return; // Don't calculate skill bonuses if we are importing
    }

    this.calculateBasicStatBonus(actorData);

    // Calculate Stat Bonuses for the Actor
    this.calculateStatBonuses(actorData);

    // Calculate Resistance Rolls for the Actor
    this.calculateResistanceRolls(actorData);

    // Iterate through and apply Stat bonuses for Skill Category Items
    this.calculateSkillCategoryStatBonuses();

    // Iterate through and apply Skill Category Bonuses for Skill items
    this.calculateSkillBonuses();

    this.computeWoundsMalus();
  }
  
  getStunnedModifier() {
    if (this.system.state.stunned) {
      return Math.min(-50 + (3*this.system.stats.self_discipline.stat_bonus), 0)
    } else {
      return 0;
    }
  }

  computeWoundsMalus() {  
    // Compute % of wounds
    let percent = 100 - (this.system.attributes.hits.current*100/this.system.attributes.hits.max);
    let modifier = 0;
    if (percent > 25 && percent < 50) {
      modifier = -10;
    } else if (percent >= 51 && percent < 75) {
      modifier = -20;
    } else if (percent >= 76) {
      modifier = -30;
    }
    this.system.modifiers.woundsModifier = modifier;
    console.log(`rmss | actor.js | Wounds Malus: ${this.system.modifiers.woundsModifier} ${percent}`);
  }

  /**
   * Prepare NPC specific data.
   * @param {Actor} actorData The NPC Object to prepare data for
   */
  _prepareNpcData(actorData) {
    if (actorData.type !== "npc") return;

    // Make modifications to data here. For example:
    const data = actorData.data;
  }

  // This checks to see if you have a Rollable Table called "Basic Stat Bonus Table" and uses it to calculate the basic stat bonuses.
  calculateBasicStatBonus(actorData) {
    const systemData = actorData.system;
    for (const table of game.tables) {
      if (table.name === "Basic Stat Bonus Table") {
        for (const result of table.results) {
          if (actorData.system.stats.agility.temp >= Number(result.range[0]) && actorData.system.stats.agility.basic_bonus <= Number(result.range[1])) {
            actorData.system.stats.agility.basic_bonus = parseInt(result.text, 10);
          }

          if (actorData.system.stats.constitution.temp >= Number(result.range[0]) && actorData.system.stats.constitution.basic_bonus <= Number(result.range[1])) {
            actorData.system.stats.constitution.basic_bonus = parseInt(result.text, 10);
          }

          if (actorData.system.stats.memory.temp >= Number(result.range[0]) && actorData.system.stats.memory.basic_bonus <= Number(result.range[1])) {
            actorData.system.stats.memory.basic_bonus = parseInt(result.text, 10);
          }

          if (actorData.system.stats.reasoning.temp >= Number(result.range[0]) && actorData.system.stats.reasoning.basic_bonus <= Number(result.range[1])) {
            actorData.system.stats.reasoning.basic_bonus = parseInt(result.text, 10);
          }

          if (actorData.system.stats.self_discipline.temp >= Number(result.range[0]) && actorData.system.stats.self_discipline.basic_bonus <= Number(result.range[1])) {
            actorData.system.stats.self_discipline.basic_bonus = parseInt(result.text, 10);
          }

          if (actorData.system.stats.empathy.temp >= Number(result.range[0]) && actorData.system.stats.empathy.basic_bonus <= Number(result.range[1])) {
            actorData.system.stats.empathy.basic_bonus = parseInt(result.text, 10);
          }

          if (actorData.system.stats.intuition.temp >= Number(result.range[0]) && actorData.system.stats.intuition.basic_bonus <= Number(result.range[1])) {
            actorData.system.stats.intuition.basic_bonus = parseInt(result.text, 10);
          }

          if (actorData.system.stats.presence.temp >= Number(result.range[0]) && actorData.system.stats.presence.basic_bonus <= Number(result.range[1])) {
            actorData.system.stats.presence.basic_bonus = parseInt(result.text, 10);
          }

          if (actorData.system.stats.quickness.temp >= Number(result.range[0]) && actorData.system.stats.quickness.basic_bonus <= Number(result.range[1])) {
            actorData.system.stats.quickness.basic_bonus = parseInt(result.text, 10);
          }

          if (actorData.system.stats.strength.temp >= Number(result.range[0]) && actorData.system.stats.strength.basic_bonus <= Number(result.range[1])) {
            actorData.system.stats.strength.basic_bonus = parseInt(result.text, 10);
          }
        }
      }
    }
  }

  // Tally each stat bonus and populate the total field.
  calculateStatBonuses(actorData) {
    const systemData = actorData.system;

    actorData.system.stats.agility.stat_bonus = Number(systemData.stats.agility.racial_bonus)
                                              + Number(systemData.stats.agility.special_bonus)
                                              + Number(systemData.stats.agility.basic_bonus);

    actorData.system.stats.constitution.stat_bonus = Number(systemData.stats.constitution.racial_bonus)
                                                   + Number(systemData.stats.constitution.special_bonus)
                                                   + Number(systemData.stats.constitution.basic_bonus);

    actorData.system.stats.memory.stat_bonus = Number(systemData.stats.memory.racial_bonus)
                                             + Number(systemData.stats.memory.special_bonus)
                                             + Number(systemData.stats.memory.basic_bonus);

    actorData.system.stats.reasoning.stat_bonus = Number(systemData.stats.reasoning.racial_bonus)
                                                + Number(systemData.stats.reasoning.special_bonus)
                                                + Number(systemData.stats.reasoning.basic_bonus);


    actorData.system.stats.self_discipline.stat_bonus = Number(systemData.stats.self_discipline.racial_bonus)
                                                      + Number(systemData.stats.self_discipline.special_bonus)
                                                      + Number(systemData.stats.self_discipline.basic_bonus);

    actorData.system.stats.empathy.stat_bonus = Number(systemData.stats.empathy.racial_bonus)
                                              + Number(systemData.stats.empathy.special_bonus)
                                              + Number(systemData.stats.empathy.basic_bonus);

    actorData.system.stats.intuition.stat_bonus = Number(systemData.stats.intuition.racial_bonus)
                                                + Number(systemData.stats.intuition.special_bonus)
                                                + Number(systemData.stats.intuition.basic_bonus);

    actorData.system.stats.presence.stat_bonus = Number(systemData.stats.presence.racial_bonus)
                                               + Number(systemData.stats.presence.special_bonus)
                                               + Number(systemData.stats.presence.basic_bonus);

    actorData.system.stats.quickness.stat_bonus = Number(systemData.stats.quickness.racial_bonus)
                                                + Number(systemData.stats.quickness.special_bonus)
                                                + Number(systemData.stats.quickness.basic_bonus);

    actorData.system.stats.strength.stat_bonus = Number(systemData.stats.strength.racial_bonus)
                                               + Number(systemData.stats.strength.special_bonus)
                                               + Number(systemData.stats.strength.basic_bonus);
  }

  // Calculate each Resistance Roll with the formula on the character sheet.
  calculateResistanceRolls(actorData) {
    const systemData = actorData.system;

    actorData.system.resistance_rolls.essence.value = Number(systemData.stats.empathy.stat_bonus * 3);

    actorData.system.resistance_rolls.channeling.value = Number(systemData.stats.intuition.stat_bonus * 3);

    actorData.system.resistance_rolls.mentalism.value = Number(systemData.stats.presence.stat_bonus * 3);

    actorData.system.resistance_rolls.fear.value = Number(systemData.stats.self_discipline.stat_bonus * 3);

    actorData.system.resistance_rolls.poison_disease.value = Number(systemData.stats.constitution.stat_bonus * 3);

    actorData.system.resistance_rolls.chann_ess.value = Number(systemData.stats.intuition.stat_bonus)
                                                      + Number(systemData.stats.empathy.stat_bonus);

    actorData.system.resistance_rolls.chann_ment.value = Number(systemData.stats.intuition.stat_bonus)
                                                       + Number(systemData.stats.presence.stat_bonus);

    actorData.system.resistance_rolls.ess_ment.value = Number(systemData.stats.empathy.stat_bonus)
                                                     + Number(systemData.stats.presence.stat_bonus);

    actorData.system.resistance_rolls.arcane.value = Number(systemData.stats.empathy.stat_bonus)
                                                   + Number(systemData.stats.intuition.stat_bonus)
                                                   + Number(systemData.stats.presence.stat_bonus);

    actorData.system.resistance_rolls.essence.total = actorData.system.resistance_rolls.essence.value
                                                    + actorData.system.resistance_rolls.essence.race_mod;

    actorData.system.resistance_rolls.channeling.total = actorData.system.resistance_rolls.channeling.value
                                                       + actorData.system.resistance_rolls.channeling.race_mod;

    actorData.system.resistance_rolls.mentalism.total = actorData.system.resistance_rolls.mentalism.value
                                                      + actorData.system.resistance_rolls.mentalism.race_mod;

    actorData.system.resistance_rolls.fear.total = actorData.system.resistance_rolls.fear.value
                                                 + actorData.system.resistance_rolls.fear.race_mod;

    actorData.system.resistance_rolls.poison_disease.total = actorData.system.resistance_rolls.poison_disease.value
                                                           + actorData.system.resistance_rolls.poison_disease.race_mod;

    actorData.system.resistance_rolls.chann_ess.total = actorData.system.resistance_rolls.chann_ess.value
                                                      + actorData.system.resistance_rolls.chann_ess.race_mod;

    actorData.system.resistance_rolls.chann_ment.total = actorData.system.resistance_rolls.chann_ment.value
                                                       + actorData.system.resistance_rolls.chann_ment.race_mod;

    actorData.system.resistance_rolls.ess_ment.total = actorData.system.resistance_rolls.ess_ment.value
                                                     + actorData.system.resistance_rolls.ess_ment.race_mod;

    actorData.system.resistance_rolls.arcane.total = actorData.system.resistance_rolls.arcane.value
                                                   + actorData.system.resistance_rolls.arcane.race_mod;
  }

  calculateSkillBonuses() {
    for (const item of this.items) {
      if (item.type === "skill") {
        console.log(`rmss | actor.js | Calculating skill bonus for Skill: ${item.name}`);
        item.calculateSelectedSkillCategoryBonus(item);
        item.calculateSkillTotalBonus(item);
      }
    }
  }

  // Tallys the bonus for each Stat that is applicable to the Skill Category and then updates the total
  calculateSkillCategoryStatBonuses() {
    for (const item of this.items) {
      if (item.type === "skill_category") {

        console.log(`rmss | actor.js | Calculating Skill Category Stat Bonuses for: ${item.name}`);
        // Get all the applicable stats for this skill category
        let app_stat_1 = item.system.app_stat_1;
        let app_stat_2 = item.system.app_stat_2;
        let app_stat_3 = item.system.app_stat_3;

        // If the first one is None we don't need to do anything further
        if (app_stat_1 === "None") {
          continue;
        }
        else
        {
          let applicable_stat_bonuses = [];

          // Iterate through the applicable stats and find their full names
          for (const stat in CONFIG.rmss.stats) {
            // If the configured App Stat matches the one of the stats in config
            if (app_stat_1 === CONFIG.rmss.stats[stat].shortname) {
              // Add the Stat Bonus to the array
              applicable_stat_bonuses.push(this.system.stats[stat].stat_bonus);
            }
            if (app_stat_2 === CONFIG.rmss.stats[stat].shortname) {
              // Add the Stat Bonus to the array
              applicable_stat_bonuses.push(this.system.stats[stat].stat_bonus);
            }
            if (app_stat_3 === CONFIG.rmss.stats[stat].shortname) {
              // Add the Stat Bonus to the array
              applicable_stat_bonuses.push(this.system.stats[stat].stat_bonus);
            }
          }
          // Compute the total bonus for the applicable stats
          let applicable_stat_bonus = 0;
          for (const bonus of applicable_stat_bonuses) {
            applicable_stat_bonus += bonus;
          }
          // Apply the update if we found stat bonuses for every applicable stat
          if ( item.system.stat_bonus != applicable_stat_bonus ) {
            item.system.stat_bonus = applicable_stat_bonus;
          }
          // Update the total in the Item
          item.calculateSkillCategoryTotalBonus(item);
        }
      }
    }
  }

  // For each skill category return an object in this format.
  // {{ _id: "skill category name"}}
  // This is the format that the select helper on the skill sheet needs

  getOwnedItemsByType(item_type) {
    let ownedItems = {None: "None"};
    console.log(`rmss | actor.js | Getting owned ${item_type} for: ${this.name}`);
    for (const item of this.items) {
      if (item.type === item_type) {
        ownedItems[item._id] = item.name;
      }
    }
    return (ownedItems);
  }
}
