local addonName, addon = ...

_G[addonName] = addon

--[[-----------------------------------------------------------------------------
Event handling - Use one frame to process multiple individual OnEvent needs
-------------------------------------------------------------------------------]]
do
	local frame, select, next, events = CreateFrame('Frame'), select, pairs({ })
	--local frame, select, next, events = CreateFrame('Frame'), select, next, {} -- maybe a fix? but no...
	local register, unregister = frame.RegisterEvent, frame.UnregisterEvent
	frame:Hide()

	frame:SetScript('OnEvent', function(self, event, ...)
		for reference, func in next, events[event], nil do
			func(reference, event, ...)
		end
	end)

	function addon.RegisterEvent(reference, event, func)
		if not events[event] then
			events[event] = { }
			register(frame, event)
		end
		events[event][reference] = func
	end

	function addon.RegisterEvents(reference, func, ...)
		local event
		for index = 1, select('#', ...) do
			event = select(index, ...)
			if not events[event] then
				events[event] = { }
				register(frame, event)
			end
			events[event][reference] = func
		end
	end

	function addon.UnregisterEvent(reference, event)
		if events[event] then
			events[event][reference] = nil
			if not next(events[event]) then
				events[event] = nil
				unregister(frame, event)
			end
		end
	end

	function addon.UnregisterAllEvents(reference)
		for event, registry in next, events, nil do
			registry[reference] = nil
			if not next(registry) then
				events[event] = nil
				unregister(frame, event)
			end
		end
	end
end

--[[-----------------------------------------------------------------------------
SafeCall - Queue a method of addon to run once combat ends if needed
-------------------------------------------------------------------------------]]
do
	local combatLockdown, queue = InCombatLockdown(), { }

	addon.RegisterEvent("Core-SafeCall-EnterCombat", 'PLAYER_REGEN_DISABLED', function(self)
		combatLockdown = true
	end)

	addon.RegisterEvent("Core-SafeCall-LeaveCombat", 'PLAYER_REGEN_ENABLED', function(self)
		combatLockdown = nil
		for method, arg in pairs(queue) do
			addon[method](addon, arg)
			queue[method] = nil
		end
	end)

	function addon:SafeCall(method, arg)
		if combatLockdown then
			queue[method] = arg or false
		else
			addon[method](addon, arg)
		end
	end
end

--[[-----------------------------------------------------------------------------
Localized class name to file class name look up table
-------------------------------------------------------------------------------]]
local CLASS = { }
for fileName, localName in pairs(LOCALIZED_CLASS_NAMES_MALE) do
	CLASS[localName] = fileName
end
for fileName, localName in pairs(LOCALIZED_CLASS_NAMES_FEMALE) do
	CLASS[localName] = fileName
end
addon.CLASS = CLASS

--[[-----------------------------------------------------------------------------
MoneyToString - Get formatted text from an ammount of copper
-------------------------------------------------------------------------------]]
function addon:MoneyToString(ammount, forceIcons)
	local cu = ammount % 100
	ammount = floor(ammount / 100)
	local ag, au = ammount % 100, floor(ammount / 100)
	local cuInd, agInd, auInd
	if GetCVarBool('showChatIcons') or forceIcons then
		cuInd = [[|TInterface\MoneyFrame\UI-CopperIcon:0|t]]
		agInd = [[|TInterface\MoneyFrame\UI-SilverIcon:0|t ]]
		auInd = [[|TInterface\MoneyFrame\UI-GoldIcon:0|t ]]
	else
		cuInd = "|cffeda55fc|r"
		agInd = "|cffc7c7cfs|r "
		auInd = "|cffffd700g|r "
	end
	local string = ""
	if au > 0 then
		string = au .. auInd .. ag .. agInd
	elseif ag > 0 then
		string = ag .. agInd
	end
	return string .. cu .. cuInd
end

--[[-----------------------------------------------------------------------------
DoNothing - A simple dummie/do nothing function
-------------------------------------------------------------------------------]]
local function DoNothing()
end
addon.DoNothing = DoNothing

--[[-----------------------------------------------------------------------------
HideTooltip - Hide GameTooltip (several frames use this)
-------------------------------------------------------------------------------]]
function addon:HideTooltip()
	GameTooltip:Hide()
	self.tooltip = nil
end

--[[-----------------------------------------------------------------------------
HideFrame - Hide a frame, prevents it from being reshown
-------------------------------------------------------------------------------]]
function addon:HideFrame(reference)
	local frame = type(reference) == 'string' and _G[reference] or reference
	if type(frame) ~= 'table' then return end
	frame.Show = DoNothing
	frame:Hide()
end

--[[-----------------------------------------------------------------------------
ShowFrame - Show a frame, undoing :HideFrame behavior
-------------------------------------------------------------------------------]]
function addon:ShowFrame(reference)
	local frame = type(reference) == 'string' and _G[reference] or reference
	if type(frame) ~= 'table' then return end
	frame.Show = nil
	frame:Show()
end

--[[-----------------------------------------------------------------------------
LockFrame - Lock a frame, prevents SetPoint and ClearAllPoints from working
-------------------------------------------------------------------------------]]
function addon:LockFrame(reference)
	local frame = type(reference) == 'string' and _G[reference] or reference
	if type(frame) ~= 'table' then return end
	frame.SetPoint = DoNothing
	frame.ClearAllPoints = DoNothing
end

--[[-----------------------------------------------------------------------------
UnlockFrame - Undo :LockFrame
-------------------------------------------------------------------------------]]
function addon:UnlockFrame(reference)
	local frame = type(reference) == 'string' and _G[reference] or reference
	if type(frame) ~= 'table' then return end
	frame.SetPoint = nil
	frame.ClearAllPoints = nil
end

--[[-----------------------------------------------------------------------------
RunSlashCmd
-------------------------------------------------------------------------------]]
function addon:RunSlashCmd(cmd)
	local slash, rest = cmd:match("^(%S+)%s*(.-)$")
	for name, func in pairs(SlashCmdList) do
		local i, slashCmd = 1
		repeat
			slashCmd = _G['SLASH_' .. name .. i]
			if slashCmd == slash then
				func(rest)
				return true
			end
			i = i + 1
		until not slashCmd
	end
end

--[[-----------------------------------------------------------------------------
Class/Reaction type Coloring
-------------------------------------------------------------------------------]]
do 
    local format = string.format
    GCHex = function(color)
        return format('|cff%02x%02x%02x', color.r * 255, color.g * 255, color.b * 255)
    end
end

function addon:unitColor(unit)
    local color = { r=1, g=1, b=1 }
    if UnitIsPlayer(unit) then
        local _, class = UnitClass(unit)
        color = RAID_CLASS_COLORS[class]
        return color
    else
        local reaction = UnitReaction(unit, "player")
        if reaction then
            color = FACTION_BAR_COLORS[reaction]
            return color
        end
    end
    return color
end

--[[-----------------------------------------------------------------------------
Delay a function
-------------------------------------------------------------------------------]]
local waitTable = {};
local waitFrame = nil;
function addon:FuncDelay(delay, func, ...)
  if(type(delay)~="number" or type(func)~="function") then
    return false;
  end
  if(waitFrame == nil) then
    waitFrame = CreateFrame("Frame","WaitFrame", UIParent);
    waitFrame:SetScript("onUpdate",function (self,elapse)
      local count = #waitTable;
      local i = 1;
      while(i<=count) do
        local waitRecord = tremove(waitTable,i);
        local d = tremove(waitRecord,1);
        local f = tremove(waitRecord,1);
        local p = tremove(waitRecord,1);
        if(d>elapse) then
          tinsert(waitTable,i,{d-elapse,f,p});
          i = i + 1;
        else
          count = count - 1;
          f(unpack(p));
        end
      end
    end);
  end
  tinsert(waitTable,{delay,func,{...}});
  return true;
end

--[[-----------------------------------------------------------------------------
Blizzard Build comparisonn for ptr/beta/live compatible versions
-------------------------------------------------------------------------------]]
function addon:CompareBuild(comver, combuild, comref, lowcomref, highcomref)
	local version, build, bdate, toc = GetBuildInfo()
	if version > comver and build > combuild then
		addon[highcomref]()
	elseif version < comver and build < combuild then
		addon[lowcomref]()
	elseif version == comver and build == combuild then
		addon[comref]()
	end
end

--[[-----------------------------------------------------------------------------
Reload Frame
-------------------------------------------------------------------------------]]
function addon:OpenReloadFrame(myfunc)
	local reloadFrame
	if(reloadFrame) then
		return reloadFrame:Show()
	end

	reloadFrame = CreateFrame("Frame", nil, UIParent)
	reloadFrame:SetHeight(160)
	reloadFrame:SetWidth(350)
	reloadFrame:SetPoint("CENTER", UIParent, "CENTER", 0, 200)
	reloadFrame:SetBackdrop{
		bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
		tile = true,
		tileSize = 32,
		edgeSize = 32,
		insets = {
			left = 11,
			right = 12,
			top = 12,
			bottom = 11
		}
	}

	local text = reloadFrame:CreateFontString(nil, "ARTWORK", "GameFontNormalHuge")
	text:SetText("GrimUI: Reload")
	text:SetPoint("TOP", 0, -20)

	local text2 = reloadFrame:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
	text2:SetText("GrimUI requires a relog or reload\n to finish its configuration.")
	text2:SetPoint("TOP", 0, -60)

	local button1 = CreateFrame("Button", "okay", reloadFrame, "UIPanelButtonTemplate")
	button1:SetHeight(45)
	button1:SetWidth(125)
	button1:SetPoint("BOTTOMLEFT", 15, 15)
	button1:SetText("Reload")
	button1:RegisterForClicks("AnyUp")
	button1:SetScript("OnClick", myfunc)

	local button2 = CreateFrame("Button", "cancel", reloadFrame, "UIPanelButtonTemplate")
	button2:SetHeight(45)
	button2:SetWidth(125)
	button2:SetPoint("BOTTOMRIGHT", -15, 15)
	button2:SetText("Cancel")
	button2:RegisterForClicks("AnyUp")
	button2:SetScript("OnClick", function() reloadFrame:Hide() end)
end

--[[-----------------------------------------------------------------------------
LibSharedMedia support
-------------------------------------------------------------------------------]]
local LSM = LibStub('LibSharedMedia-3.0')

LSM:Register('background', addonName, [[Interface\Addons\]] .. addonName .. [[\Media\MainBG]])

LSM:Register('font', "Franklin Gothing Medium", [[Interface\Addons\]] .. addonName .. [[\Media\Font1.ttf]])
LSM:Register('font', "Comic Sans MS", [[Interface\Addons\]] .. addonName .. [[\Media\Font3.ttf]])

--[[-----------------------------------------------------------------------------
Extra Key Binding Data
-------------------------------------------------------------------------------]]
BINDING_HEADER_GRIMUI = "----- GrimUI -----"
BINDING_HEADER_RAID_MOUSEOVER = "Raid Targeting (Mouseover)"
BINDING_HEADER_WORLD_TARGET = "World Target / Flares"

_G["BINDING_NAME_CLICK EWM_BlueFlare:LeftButton"] = "Blue Flare"
_G["BINDING_NAME_CLICK EWM_GreenFlare:LeftButton"] = "Green Flare"
_G["BINDING_NAME_CLICK EWM_PurpleFlare:LeftButton"] = "Purple Flare"
_G["BINDING_NAME_CLICK EWM_RedFlare:LeftButton"] = "Red Flare"
_G["BINDING_NAME_CLICK EWM_YellowFlare:LeftButton"] = "Yellow Flare"

local function CreateEasyMarkerButton(btnName, point, relativeTo, pointRel)
	local frame = CreateFrame("Button", btnName, UIParent, "SecureActionButtonTemplate");
	frame:SetPoint(point, relativeTo, pointRel, 0, -3);
	frame:SetAttribute("type", "macro");
end

CreateEasyMarkerButton("EWM_BlueFlare", "TOPLEFT", UIParent, "TOPLEFT");
EWM_BlueFlare:SetAttribute("macrotext", [[
/click CompactRaidFrameManagerDisplayFrameLeaderOptionsRaidWorldMarkerButton
/click DropDownList1Button1
]]);

CreateEasyMarkerButton("EWM_GreenFlare", "TOPLEFT", UIParent, "BOTTOMLEFT");
EWM_GreenFlare:SetAttribute("macrotext", [[
/click CompactRaidFrameManagerDisplayFrameLeaderOptionsRaidWorldMarkerButton
/click DropDownList1Button2
]]);

CreateEasyMarkerButton("EWM_PurpleFlare", "TOPLEFT", UIParent, "BOTTOMLEFT");
EWM_PurpleFlare:SetAttribute("macrotext", [[
/click CompactRaidFrameManagerDisplayFrameLeaderOptionsRaidWorldMarkerButton
/click DropDownList1Button3
]]);

CreateEasyMarkerButton("EWM_RedFlare", "TOPLEFT", UIParent, "BOTTOMLEFT");
EWM_RedFlare:SetAttribute("macrotext", [[
/click CompactRaidFrameManagerDisplayFrameLeaderOptionsRaidWorldMarkerButton
/click DropDownList1Button4
]]);

CreateEasyMarkerButton("EWM_YellowFlare", "TOPLEFT", UIParent, "BOTTOMLEFT");
EWM_YellowFlare:SetAttribute("macrotext", [[
/click CompactRaidFrameManagerDisplayFrameLeaderOptionsRaidWorldMarkerButton
/click DropDownList1Button5
]]);

--[[-----------------------------------------------------------------------------
Localization support. AceLocale
-------------------------------------------------------------------------------]]
local AceLocale = LibStub("AceLocale-3.0")
local L = AceLocale:GetLocale( "GrimUI", true )
