import React from 'react';
import TalentStatisticBox from 'interface/others/TalentStatisticBox';
import Analyzer from 'parser/core/Analyzer';
import Events from 'parser/core/Events';
import { SELECTED_PLAYER } from 'parser/core/EventFilter';
import SPELLS from 'common/SPELLS';

const BUFFER_MS = 50;

class MeatCleaver extends Analyzer {
  whirlwindEvents = [];
  lastWhirlwindCast = 0;

  constructor(...args) {
    super(...args);
    this.active = this.selectedCombatant.hasTalent(SPELLS.MEAT_CLEAVER_TALENT.id);
    if (!this.active) {
      return;
    }

    this.addEventListener(Events.energize.to(SELECTED_PLAYER).spell(SPELLS.WHIRLWIND_FURY_ENERGIZE), this.onWhirlwindEnergize);
    this.addEventListener(Events.damage.by(SELECTED_PLAYER).spell([SPELLS.WHIRLWIND_FURY_DAMAGE_MH, SPELLS.WHIRLWIND_FURY_DAMAGE_OH]), this.onWhirlwindDamage);
    this.addEventListener(Events.applybuff.to(SELECTED_PLAYER).spell(SPELLS.ENRAGE), this.onEnrage);
  }

  // The Energize event ligns up with the cast, so using it for both the rage gain, and timings of the cast.
  onWhirlwindEnergize(event) {
    this.lastWhirlwindCast = event.timestamp;
    this.whirlwindEvents[this.lastWhirlwindCast] = {
      resourceChange: event.resourceChange,
      triggeredEnrage: false,
      targetsHit: 0,
      isFirstRoundOfDamage: true,
      hasRecklessness: this.selectedCombatant.hasBuff(SPELLS.RECKLESSNESS.id),
    };
  }

  onEnrage(event) {
    if (event.timestamp - this.lastWhirlwindCast <= BUFFER_MS) {
      this.whirlwindEvents[this.lastWhirlwindCast].triggeredEnrage = true;
    }
  }

  onWhirlwindDamage(event) {
    // Whirlwind triggers damage 3 times. We only need to count the number of targets hit on the first set of MH damage
    if (this.whirlwindEvents[this.lastWhirlwindCast].isFirstRoundOfDamage) {
      if (event.ability.guid === SPELLS.WHIRLWIND_FURY_DAMAGE_MH.id) {
        this.whirlwindEvents[this.lastWhirlwindCast].targetsHit++;
      } else {
        this.whirlwindEvents[this.lastWhirlwindCast].isFirstRoundOfDamage = false;
      }
    }
  }

  get numberOfEnrageTriggers() {
    return this.whirlwindEvents.filter(e => e.triggeredEnrage).length;
  }

  get rageGainedByMeatCleaver() {
    return this.whirlwindEvents.reduce((total, event) => {
      const rageGained = event.resourceChange;
      const rageFromHit = rageGained - (event.hasRecklessness ? 6 : 3);
      const rageFromMeatCleaver = rageFromHit - (event.targetsHit > 5 ? 5 : event.targetsHit) * (event.hasRecklessness ? 2 : 1);
      return total + rageFromMeatCleaver;
    }, 0);
  }

  statistic() {
    return (
      <TalentStatisticBox
        talent={SPELLS.MEAT_CLEAVER_TALENT.id}
        value={`${this.rageGainedByMeatCleaver} rage gained`}
        label="Meat Cleaver"
        tooltip={`Enrage was triggered <b>${this.numberOfEnrageTriggers}</b> times by Meat Cleaver.`}
        />
    );
  }
}

export default MeatCleaver;
@@ -295,16 +295,109 @@
  = 50;%0A%0A
+const RAGE_GAIN_WW_ON_USE = 3;%0Aconst RAGE_GAIN_WW_ON_HIT = 1;%0Aconst WW_ON_HIT_RAGE_CAP = 5;%0A%0A
 class Me
@@ -2412,73 +2412,358 @@
     
-const rageFromHit = rageGained - (event.hasRecklessness ? 6 : 3);
+// WW generates 3 rage on cast (6 during recklessness). Subtract this to get rage gained from hitting targets%0A      const rageFromHit = rageGained - (event.hasRecklessness ? RAGE_GAIN_WW_ON_USE * 2 : RAGE_GAIN_WW_ON_USE);%0A      // WW generates 1 rage per target hit (2 during recklessness) up to 5 targets. Subtract this to get rage gained from trait
 %0A   
@@ -2831,13 +2831,47 @@
 t %3E 
-5 ? 5
+WW_ON_HIT_RAGE_CAP ? WW_ON_HIT_RAGE_CAP
  : e
@@ -2918,28 +2918,240 @@
 s ? 
-2 : 1);%0A      return
+RAGE_GAIN_WW_ON_HIT * 2 : RAGE_GAIN_WW_ON_HIT);%0A      // Due to calculating this backwards, if WW was cast near to full rage, rageFromMeatCleaver could be negative but should just be 0.%0A      return rageFromMeatCleaver %3C 0 ? total :
  tot

Update for Meat Cleaver