import computeStat from '/imports/api/creature/computation/computeStat.js';
import applyToggles from '/imports/api/creature/computation/applyToggles.js';

export default function combineStat(stat, aggregator, memo){
  if (stat.type === 'attribute'){
    combineAttribute(stat, aggregator);
  } else if (stat.type === 'skill'){
    combineSkill(stat, aggregator, memo);
  } else if (stat.type === 'damageMultiplier'){
    combineDamageMultiplier(stat, memo);
  }
}

function getAggregatorResult(stat, aggregator){
  let result = (aggregator.base + aggregator.add) * aggregator.mul;
  if (result < aggregator.min) {
    result = aggregator.min;
  }
  if (result > aggregator.max) {
    result = aggregator.max;
  }
  if (aggregator.set !== undefined) {
    result = aggregator.set;
  }
  if (!stat.decimal && Number.isFinite(result)){
    result = Math.floor(result);
  }
  return result;
}

function combineAttribute(stat, aggregator){
  stat.value = getAggregatorResult(stat, aggregator);
  stat.baseValue = aggregator.statBaseValue;
  stat.baseValueErrors = aggregator.baseValueErrors;
  if (stat.attributeType === 'ability') {
    stat.modifier = Math.floor((stat.value - 10) / 2);
  }
  stat.currentValue = stat.value - (stat.damage || 0);
  stat.hide = aggregator.hasNoEffects &&
    stat.baseValue === undefined ||
    undefined
}

function combineSkill(stat, aggregator, memo){
  // Skills are based on some ability Modifier
  let ability = memo.statsByVariableName[stat.ability]
  if (stat.ability && ability){
    if (!ability.computationDetails.computed){
      computeStat(ability, memo);
    }
    stat.abilityMod = ability.modifier;
  }
  // Combine all the child proficiencies
  stat.proficiency = stat.baseProficiency || 0;
  for (let i in stat.computationDetails.proficiencies){
    let prof = stat.computationDetails.proficiencies[i];
    applyToggles(prof, memo);
    if (
      !prof.computationDetails.disabledByToggle &&
      prof.value > stat.proficiency
    ){
      stat.proficiency = prof.value;
    }
  }
  // Get the character's proficiency bonus to apply
  let profBonusStat = memo.statsByVariableName['proficiencyBonus'];
  let profBonus = profBonusStat && profBonusStat.value;

  if (typeof profBonus !== 'number' && memo.statsByVariableName['level']){
    let level = memo.statsByVariableName['level'].value;
    profBonus = Math.ceil(level / 4) + 1;
  }
  // Multiply the proficiency bonus by the actual proficiency
  profBonus *= stat.proficiency;
  // Base value
  stat.baseValue = aggregator.statBaseValue;
  stat.baseValueErrors = aggregator.baseValueErrors;
  // Combine everything to get the final result
  let result = (aggregator.base + stat.abilityMod + profBonus + aggregator.add) * aggregator.mul;
  if (result < aggregator.min) result = aggregator.min;
  if (result > aggregator.max) result = aggregator.max;
  if (aggregator.set !== undefined) {
    result = aggregator.set;
  }
  if (Number.isFinite(result)){
    result = Math.floor(result);
  }
  stat.value = result;
  // Advantage/disadvantage
  if (aggregator.advantage && !aggregator.disadvantage){
    stat.advantage = 1;
  } else if (aggregator.disadvantage && !aggregator.advantage){
    stat.advantage = -1;
  } else {
    stat.advantage = 0;
  }
  // Passive bonus
  stat.passiveBonus = aggregator.passiveAdd;
  // conditional benefits
  stat.conditionalBenefits = aggregator.conditional;
  // Roll bonuses
  stat.rollBonus = aggregator.rollBonus;
  // Forced to fail
  stat.fail = aggregator.fail;
  // Rollbonus
  stat.rollBonuses = aggregator.rollBonus;
  // Hide
  stat.hide = aggregator.hasNoEffects &&
    stat.baseValue === undefined &&
    stat.proficiency == 0 ||
    undefined;
}

function combineDamageMultiplier(stat){
  if (stat.immunityCount) return 0;
  let result;
  if (stat.ressistanceCount && !stat.vulnerabilityCount){
    result = 0.5;
  }  else if (!stat.ressistanceCount && stat.vulnerabilityCount){
    result = 2;
  } else {
    result = 1;
  }
  stat.value = result;
}
