'use strict';

let Options = {
  Language: 'en',
};

let gPullCounter;

class PullCounter {
  constructor(element) {
    this.element = element;
    this.zone = null;
    this.bossStarted = false;
    this.party = [];
    this.bosses = [];

    this.resetRegex = Regexes.echo({ line: '.*pullcounter reset.*?' });
    this.countdownEngageRegex = LocaleRegex.countdownEngage[Options.ParserLanguage] ||
      LocaleRegex.countdownEngage['en'];

    callOverlayHandler({
      call: 'cactbotLoadData',
      overlay: 'pullcounter',
    }).then((data) => gPullCounter.SetSaveData(data));

    this.ReloadTriggers();
  }

  OnFightStart(boss) {
    this.pullCounts[boss.id] = (this.pullCounts[boss.id] || 0) + 1;
    this.bossStarted = true;

    this.ShowElementFor(boss.id);
    this.SaveData();
  }

  ShowElementFor(id) {
    this.element.innerText = this.pullCounts[id];
    this.element.classList.remove('wipe');
  }

  SaveData() {
    callOverlayHandler({
      call: 'cactbotSaveData',
      overlay: 'pullcounter',
      data: JSON.stringify(this.pullCounts),
    });
  }

  OnLogEvent(e) {
    if (this.bossStarted)
      return;
    for (let i = 0; i < e.detail.logs.length; ++i) {
      let log = e.detail.logs[i];
      if (log.match(this.resetRegex))
        this.ResetPullCounter();
      if (log.match(this.countdownEngageRegex)) {
        if (this.countdownBoss)
          this.OnFightStart(this.countdownBoss);
        else
          this.AutoStartBossIfNeeded();
        return;
      }
      for (let b = 0; b < this.bosses.length; ++b) {
        let boss = this.bosses[b];
        if (log.match(boss.startRegex)) {
          this.OnFightStart(boss);
          return;
        }
      }
    }
  }

  OnChangeZone(e) {
    this.element.innerText = '';
    this.zone = e.zoneName;
    this.ReloadTriggers();
  }

  ResetPullCounter() {
    if (this.bosses.length > 0) {
      for (let i = 0; i < this.bosses.length; ++i) {
        let id = this.bosses[i].id;
        this.pullCounts[id] = 0;
        console.log('resetting pull count of: ' + id);
        this.ShowElementFor(id);
      }
    } else {
      let id = this.zone;
      console.log('resetting pull count of: ' + id);
      this.ShowElementFor(id);
    }

    this.SaveData();
  }

  ReloadTriggers() {
    this.bosses = [];
    this.countdownBoss = null;
    if (!this.zone || !this.pullCounts)
      return;

    for (let i = 0; i < gBossFightTriggers.length; ++i) {
      let boss = gBossFightTriggers[i];
      if (!this.zone.match(Regexes.parse(boss.zoneRegex)))
        continue;
      this.bosses.push(boss);
      if (boss.countdownStarts) {
        // Only one boss can be started with countdown in a zone.
        if (this.countdownBoss)
          console.error('Countdown boss conflict: ' + boss.id + ', ' + this.countdownBoss.id);
        this.countdownBoss = boss;
      }
    }
  }

  OnInCombatChange(e) {
    if (!e.detail.inGameCombat) {
      this.bossStarted = false;
      return;
    }
    this.AutoStartBossIfNeeded();
  }

  AutoStartBossIfNeeded() {
    // Start an implicit boss fight for this zone in parties of 8 people
    // where no other bosses have been specified.
    if (this.bosses.length > 0)
      return;
    if (this.bossStarted)
      return;
    if (this.party.length != 8)
      return;
    this.OnFightStart({
      id: this.zone,
      countdownStarts: true,
    });
  }

  OnPartyWipe() {
    this.element.classList.add('wipe');
  }

  OnPartyChange(e) {
    this.party = e.party;
  }

  SetSaveData(e) {
    try {
      if (e != null && e.data)
        this.pullCounts = JSON.parse(e.data);
      else
        this.pullCounts = {};
    } catch (err) {
      console.error('onSendSaveData parse error: ' + err.message);
    }
    this.ReloadTriggers();
  }
}

UserConfig.getUserConfigLocation('pullcounter', function() {
  gPullCounter = new PullCounter(document.getElementById('pullcounttext'));

  addOverlayListener('onLogEvent', (e) => gPullCounter.OnLogEvent(e));
  addOverlayListener('ChangeZone', (e) => gPullCounter.OnChangeZone(e));
  addOverlayListener('onInCombatChangedEvent', (e) => gPullCounter.OnInCombatChange(e));
  addOverlayListener('onPartyWipe', () => gPullCounter.OnPartyWipe());
  addOverlayListener('PartyChanged', (e) => gPullCounter.OnPartyChange(e));
});

@@ -1787,16 +1787,494 @@
 neName;%0A
+%0A    // Network log zone names that start with %22the%22 are lowercase.%0A    // Adjust this here to match saved pull counts for zones which%0A    // do not have this property and originally used zone names%0A    // coming from the ffxiv parser plugin.%0A%0A    // TODO: add some backwards compatible way to turn zone names into%0A    // zone ids when we load that zone and a pull count exists?%0A    if (this.zone.length %3E 0)%0A      this.zone = this.zone%5B0%5D.toUpperCase() + this.zone.substr(1);%0A%0A
     this

fix incorrect pull counts after c4b13ad