local name, ns = ...
local Addon = _G[name]

local group_members = {}
local offline_times = {}
local afk_times = {}
local dnd = {}
local dead_times = {}

Addon.cache = {
	offline_times = offline_times,
	afk_times = afk_times,
	dnd = dnd,
	dead_times = dead_times,
}
Addon.group = group_members

local tmp = {}
local player_guid = UnitGUID("player")
local function updateparty(event)
	local prefix, min, max = "raid", 1, GetNumGroupMembers()
	if max == 0 then
		prefix, min, max = "party", 0, GetNumPartyMembers()
	end
	if max == 0 then
		-- not in a raid or a party
		wipe(group_members)
		group_members["player"] = player_guid
		return
	end

	wipe(group_members)
	for i = min, max do
		local unit
		if i == 0 then
			unit = 'player'
		else
			unit = prefix .. i
		end
		local guid = UnitGUID(unit)
		group_members[unit] = guid

		if guid then
			tmp[guid] = true
		end
	end

	-- Cleanup any timers that reference people no longer in the party
	for guid in pairs(offline_times) do
		if not tmp[guid] then
			offline_times[guid] = nil
		end
	end
	for guid in pairs(dead_times) do
		if not tmp[guid] then
			dead_times[guid] = nil
		end
	end
	for guid in pairs(afk_times) do
		if not tmp[guid] then
			afk_times[guid] = nil
		end
	end
	wipe(tmp)
end

local function update_timers()
	for unit, guid in pairs(group_members) do
		if not UnitIsConnected(unit) then
			if not offline_times[guid] then
				offline_times[guid] = GetTime()
			end
			afk_times[guid] = nil
			if dnd[guid] then
				dnd[guid] = nil
			end
		else
			offline_times[guid] = nil
			if UnitIsAFK(unit) then
				if not afk_times[guid] then
					afk_times[guid] = GetTime()
				end
			else
				afk_times[guid] = nil
				local dnd_change = false
				if UnitIsDND(unit) then
					if not dnd[guid] then
						dnd[guid] = true
					end
				else
					if dnd[guid] then
						dnd[guid] = nil
					end
				end
			end
		end
		if UnitIsDeadOrGhost(unit) then
			if not dead_times[guid] then
				dead_times[guid] = GetTime()
			end
		else
			dead_times[guid] = nil
		end
	end
end

function Addon:InitUnitWatcher()
	updateparty()
	self:RegisterEvent("PLAYER_FLAGS_CHANGED", update_timers)
	self:RegisterEvent("PARTY_MEMBERS_CHANGED", updateparty)
	self:RegisterEvent("PLAYER_ENTERING_WORLD", updateparty)
	self:ScheduleRepeatingTimer(update_timers, 1)
end