local E, L, V, P, G = unpack(ElvUI);
local MER = E:GetModule('MerathilisUI');
local LSM = LibStub('LibSharedMedia-3.0');

-- Cache global variables
-- Lua functions
local next, pairs, table = next, pairs, table

-- WoW API / Variables
local GameTooltip = GameTooltip
local GetNumGroupMembers = GetNumGroupMembers
local UnitClass = UnitClass
local UnitExists = UnitExists
local UnitGroupRolesAssigned = UnitGroupRolesAssigned
local UnitName = UnitName
local UnitInRaid = UnitInRaid
local UnitIsDeadOrGhost = UnitIsDeadOrGhost

-- Global variables that we don't cache, list them here for the mikk's Find Globals script
-- GLOBALS: RAID_CLASS_COLORS

local watches = {}
local frame = CreateFrame('Frame', "MUIGroupInfo", UIParent)

local header = frame:CreateFontString(nil, 'ARTWORK', 'GameFontHighlight')
header:FontTemplate()
header:SetTextColor(1, 1, 1)
header:SetPoint('TOPLEFT', frame, -3, 0)

local t = frame:CreateFontString('MuiRaidStats_Alive', 'ARTWORK', 'GameFontHighlight')
t:SetPoint('TOPLEFT', header, 'BOTTOMLEFT', 3, -6)

local t2 = frame:CreateFontString('MuiRaidStats_Roles', 'ARTWORK', 'GameFontHighlight')
t2:SetPoint('TOPLEFT', t, 'BOTTOMLEFT', 0, -3)

local name = frame:CreateFontString('MuiRaidStats_GRIDName', 'ARTWORK', 'GameFontHighlight')
name:FontTemplate()
name:SetTextColor(1, 1, 1)
name:SetPoint('TOPLEFT', t2, 'BOTTOMLEFT', 20, -8)

local function sort(a, b)
	return ((a.color.r + a.color.g + a.color.b)..a.name) < ((b.color.r + b.color.g + b.color.b)..b.name)
end

local result = nil
local last, alive, c_alive, max = 0, 0, 0, 0
function Update(self, elapsed)
	if E.db.mui.unitframes.groupinfo then
		last = last + elapsed
		if last > 1 then
			last = 0
			result = nil
			alive, max = 0, 0
			local num = GetNumGroupMembers()
			if num > 0 then
				-- total raid
				for i = 1, num do
					local unit = UnitInRaid('player') and ('raid'..i) or ('party'..i)
					if UnitExists(unit) then
						max = max + 1
						if not UnitIsDeadOrGhost(unit) then alive = alive + 1 end
					end
				end
				-- role callback handler
				for name, callback in pairs(watches) do
					local count = 0
					c_alive = 0
					for i = 1, num do
						local unit = UnitInRaid('player') and ('raid'..i) or ('party'..i)
						if UnitExists(unit) and callback(unit) then
							count = count + 1
							if not UnitIsDeadOrGhost(unit) then
								c_alive = c_alive + 1
							end
						end
					end
					if count > 0 then
						result = (result and result..'   ' or '')..name ..': '..count..'/'..c_alive
					end
				end
			end
			if max > 0 then
				header:Show()
				header:SetText(UnitInRaid('player') and ('RAID') or ('PARTY'))
				t:SetFormattedText(alive..'/'..max..L[' alive'])
				t:Show()
				frame:SetWidth(t:GetWidth())
				E:CreateMover(frame, frame:GetName()..'Mover', L["MUIGroupInfo"], nil, nil, nil, 'ALL,PARTY,RAID')
			else
				header:Hide()
				t:Hide()
			end
			if result then
				t2:SetText(result)
				t2:Show()
				frame:SetWidth(t:GetWidth())
			else
				t2:Hide()
			end
		end
	end
end

function OnEnter()
	GameTooltip:SetOwner(frame, 'ANCHOR_BOTTOMRIGHT', 50, -15)
	for name, callback in pairs(watches) do
		local matches = {}
		for i = 1, GetNumGroupMembers() do
			local unit = UnitInRaid('player') and ('raid'..i) or ('party'..i)
			if UnitExists(unit) and callback(unit) then
				local _, id = UnitClass(unit)
				table.insert(matches, {name = UnitName(unit), color = RAID_CLASS_COLORS[id], alive = UnitIsDeadOrGhost(unit) and '(Dead)' or ''})
			end
		end

		if next(matches) then
			if GameTooltip:NumLines() > 0 then GameTooltip:AddLine(' ') end
			GameTooltip:AddLine(name..':', 1, 1, 1)
			table.sort(matches, sort)
			for _, v in pairs(matches) do
				GameTooltip:AddDoubleLine(v.name, v.alive, v.color.r, v.color.g, v.color.b, v.color.r, v.color.g, v.color.b)
			end
		end
	end
	GameTooltip:Show()
end

function MER:AddWatch(name, callback)
	watches[name] = callback
end

-- Tank
MER:AddWatch('|TInterface\\AddOns\\ElvUI_MerathilisUI\\media\\textures\\Tank.tga:14:14|t', function(unit)
	if UnitGroupRolesAssigned(unit) == 'TANK' then
		return (not UnitIsDeadOrGhost(unit))
	end
end)

-- Healer
MER:AddWatch('|TInterface\\AddOns\\ElvUI_MerathilisUI\\media\\textures\\Healer.tga:14:14|t', function(unit)
	if UnitGroupRolesAssigned(unit) == 'HEALER' then
		return (not UnitIsDeadOrGhost(unit))
	end
end)

frame:SetPoint("CENTER", LeftChatPanel, "LEFT", 40, 0)
frame:SetHeight(16)
frame:SetClampedToScreen(true)
frame:SetScript('OnUpdate', Update)
frame:SetScript('OnEnter', OnEnter)
frame:SetScript('OnLeave', function() GameTooltip:Hide() end)
frame:RegisterEvent('GROUP_ROSTER_UPDATE')