Quantcast
local addonName, addonTable = ...
local addon = addonTable[1];
local pmc = addon.parseModulesCore;

local mod = pmc:NewModule("Recount", "AceHook-3.0", "AceEvent-3.0");
if not mod then return end;

-- Global functions
local wipe = wipe;
local tinsert = tinsert;

function mod:IsActivatable()
	return IsAddOnLoaded("Recount");
end

function mod:GetPlayersFromLastFight()
	local players = {};
	-- Pets are not included in player's damage, so keep track
	-- and manually merge them afterwards
	local pets = {};

	local fightData;
	for name, combatant in pairs(Recount.db2.combatants) do
		fightData = combatant.Fights.LastFightData;
		local damage = (fightData and fightData.Damage) or 0;
		local healing = (fightData and fightData.Healing) or 0;

		-- Since Recount groups by combatant instead of fights
		-- we have to verify that the combatant was part of the fight.
		if fightData and (damage > 0 or healing > 0) then
			if combatant.type == "Pet" then
				pets[name] = {damage = damage, healing = healing};
			elseif combatant.type == "Grouped" or combatant.type == "Self" then
				if self:ShouldIncludePlayer(combatant.GUID, combatant.Name) then
					local playerData = {
						id = combatant.GUID,
						name = combatant.Name,
						damage = damage,
						healing = healing,
						pets = combatant.Pet
					};
					tinsert(players, playerData);
				end
			end
		end
	end

	-- Merge pets and players
	for _, playerData in ipairs(players) do
		if playerData.pets then
			for _, petName in ipairs(playerData.pets) do
				if pets[petName] then
					playerData.damage = playerData.damage + pets[petName].damage;
					playerData.healing = playerData.healing + pets[petName].healing;
				end
			end
			playerData.pets = nil;
		end
	end

	return players;
end

function mod:ProcessParseRequest(encounter, callback)
	-- Look at the most recent one, as previous ones might
	-- be wipes at the same boss
	if self.recountFightEncounterId ~= encounter.id then
		self:Debug("No Recount fight found for boss");
		return callback(false);
	end

	-- CombatTimes is an object {startTime, endTime, formatStart, formatEnd, name}
	-- where the times are from GetTime() and not time(). Because of that
	-- we have to calculate our own unix timestamp for startTime.
	local combatInfo = Recount.db2.CombatTimes[#Recount.db2.CombatTimes];
	local duration = combatInfo[2] - combatInfo[1];
	local startTime = floor(time() - duration);

	local playerParses = self:GetPlayersFromLastFight();

	return callback(true, startTime, duration, playerParses);
end

function mod:GetParsesForEncounter(encounter, callback)
	-- If recount hasn't finished the fight, wait for it
	if Recount.InCombat then
		tinsert(self.pendingParseRequests, {encounter = encounter, callback = callback});
	else
		self:ProcessParseRequest(encounter, callback);
	end
end

function mod:LeaveCombat()
	self:Debug("Recount: LeaveCombat")

	-- If we have requests waiting for LeaveCombat, process them now.
	if #self.pendingParseRequests then
		for _, pendingRequest in ipairs(self.pendingParseRequests) do
			local encounter = pendingRequest.encounter;
			local callback = pendingRequest.callback;
			self:ProcessParseRequest(encounter, callback);
		end
		wipe(self.pendingParseRequests);
	end
end

function mod:PutInCombat()
	self:Debug("Recount: PutInCombat");

	self.recountFightEncounterId = self.currentEncounterId;
end

function mod:ENCOUNTER_START(event, encounterID, encounterName, difficultyID, raidSize)
	-- Since recount doesn't track the encounter itself, we have to do it.
	-- We do this by setting the currentEncounterId whenever an encounter
	-- starts. If recount is currently in combat, or if recount starts
	-- combat between ENCOUNTER_START and END, then we track that fight as
	-- the fight against the encounter id.

	self.currentEncounterId = encounterID;

	if Recount.InCombat then
		-- If recount currently is in a fight then track
		-- the current encounter id as the encounter being fighted.
		self.recountFightEncounterId = encounterID;
	end
end

function mod:ENCOUNTER_END(event, encounterId, encounterName, difficultyId, raidSize, endStatus)
	self.currentEncounterId = nil;
end

function mod:OnEnable()
	self.pendingParseRequests = {};
	self.currentEncounterId = nil;
	self.recountFightEncounterId = nil;

	self:RegisterEvent("ENCOUNTER_START");
	self:RegisterEvent("ENCOUNTER_END");

	self:SecureHook(Recount, "LeaveCombat");
	self:SecureHook(Recount, "PutInCombat");
end

function mod:OnDisable()
	wipe(self.pendingParseRequests);
	self.currentEncounterId = nil;
	self.recountFightEncounterId = nil;

	self:UnregisterEvent("ENCOUNTER_START");
	self:UnregisterEvent("ENCOUNTER_END");

	self:UnHook(Recount, "LeaveCombat");
	self:UnHook(Recount, "PutInCombat");
end