local init_done

-- SetTex
local highlightPositions = {{0, 0.25, 0, 0.5}, {0.25, 0.75, 0, 0.5}, {0, 1, 0.5, 1}, {0.75, 1, 0, 0.5}}
local function SetTex(self, num)
	if (XPerlConfig.HighlightSelection == 1) then
		if (self:GetFrameType() == "Button") then
			self:SetHighlightTexture("Interface\\Addons\\XPerl\\images\\XPerl_Highlight", "ADD")
			local p = highlightPositions[num]
			local tex = self:GetHighlightTexture()
			tex:SetTexCoord(p[1], p[2], p[3], p[4])
			tex:SetVertexColor(0.86, 0.82, 0.41)
		end
	else
		if (self:GetFrameType() == "Button") then
			self:SetHighlightTexture("")
		end
	end
end

-- RegisterHighlight
local HighlightFrames = {}
function XPerl_RegisterHighlight(frame, ratio)
	HighlightFrames[frame] = ratio
	if (init_done) then
		SetTex(frame, ratio)
	end
end

-- XPerl_SetHighlights
function XPerl_SetHighlights()
	for k,v in pairs(HighlightFrames) do
		SetTex(k, v)
	end
end

-- SetupUnitFrame
local function SetupUnitFrame(argFrame)
	argFrame:SetBackdropBorderColor(XPerlConfig.BorderColour.r, XPerlConfig.BorderColour.g, XPerlConfig.BorderColour.b, XPerlConfig.BorderColour.a);	--, XPerlConfig.Transparency)
	argFrame:SetBackdropColor(XPerlConfig.BackColour.r, XPerlConfig.BackColour.g, XPerlConfig.BackColour.b, XPerlConfig.BackColour.a);			--XPerlConfig.Transparency)
end

-- SetupUnitFrameList
local function SetupUnitFrameList(frame, subList)
	if (type(subList) == "table") then
		frame:SetAlpha(XPerlConfig.Transparency)

		for k,v in pairs(subList) do
			local f = getglobal(frame:GetName().."_"..v)
			if (f) then
				SetupUnitFrame(f)
			end
		end
	else
		SetupUnitFrame(frame)
	end
end

-- XPerl_RegisterUnitFrame(frame)
local UnitFrames = {}
function XPerl_RegisterPerlFrames(frame, subList)
	if (not subList) then
		subList = true
	end
	UnitFrames[frame] = subList

	if (init_done) then
		SetupUnitFrameList(frame, subList)
	end
end

-- XPerl_SetupAllPerlFrames
function XPerl_SetupAllPerlFrames(frame)
	for k,v in pairs(UnitFrames) do
		SetupUnitFrameList(k, v)
	end
end

-- XPerl_SetAllFrames
function XPerl_SetAllFrames()
	XPerl_SetupAllPerlFrames()
	XPerl_SetHighlights()

	for k,v in pairs({"Player", "Target", "Focus", "TargetTarget", "TargetTargetTarget"}) do
		local f = getglobal("XPerl_"..v.."_NameFrame_PVPRankIcon")
		if (f) then f:SetAlpha(0.3) end
	end
end

-- Buff Tooltip Hook
local function XPerl_GameTooltipSetPlayerBuff(self, id)
	if (this.buffFilter == "HELPFUL") then
		XPerl_ToolTip_AddBuffDuration("player", self)
	end
end

-- XPerl_Init()
function XPerl_Init()
	init_done = true
	hooksecurefunc(GameTooltip, "SetPlayerBuff", XPerl_GameTooltipSetPlayerBuff)

	-- Check for eCastbar and disable old frame if used.
	if (eCastingBar_Saved and eCastingBar_Player and eCastingBar_Saved[eCastingBar_Player].Enabled == 1) then
		XPerlConfig.OldCastBar = 0
	elseif (BCastBar and BCastingBar and BCastBarDragButton) then
		XPerlConfig.OldCastBar = 0
	end

	if (XPerl_Player) then
		XPerl_Player:Show()
	end

	XPerl_OptionActions()
	XPerl_SlashOnLoad()

	local name, title, notes, enabled = GetAddOnInfo("PerlButton")
	if (name and enabled) then
		DisableAddOn("PerlButton")
		XPerl_Notice("Disabled 'PerlButton' addon. It is not compatible or needed with X-Perl")
		-- PerlButton was made for Nymbia's Perl UnitFrames. We have our own minimap button
	end

	name, title, notes, enabled = GetAddOnInfo("WT_ZoningTimeFix")
	if (name and enabled) then
		DisableAddOn("WT_ZoningTimeFix")
		XPerl_Notice("Disabled 'WT_ZoningTimeFix' addon. It is not compatible with X-Perl, and creates display issues.")
	end

	name, title, notes, enabled = GetAddOnInfo("CT_PartyBuffs")
	if (name and enabled) then
		DisableAddOn("CT_PartyBuffs")
		XPerl_Notice("Disabled 'CT_PartyBuffs' addon. It is not compatible with X-Perl, and creates display issues.")
	end
	if (CT_PartyBuffFrame1) then
		CT_PartyBuffFrame1:Hide()
		CT_PartyBuffFrame2:Hide()
		CT_PartyBuffFrame3:Hide()
		CT_PartyBuffFrame4:Hide()
		CT_PetBuffFrame:Hide()
	end

	if (EarthFeature_AddButton) then
		EarthFeature_AddButton ({name = XPerl_ProductName,
					icon = XPerl_ModMenuIcon,
					subtext = "by "..XPerl_Author,
					tooltip = XPerl_LongDescription,
					callback = XPerl_Toggle})
	end

	if(CT_RegisterMod) then
		CT_RegisterMod(XPerl_ProductName.." "..XPerl_VersionNumber, "By "..XPerl_Author, 4, XPerl_ModMenuIcon, XPerl_LongDescription, "switch", "", XPerl_Toggle)
	end

	if (myAddOnsFrame) then
                myAddOnsList.XPerl_Description = {
                        name			= XPerl_Description,
                        description		= XPerl_LongDescription,
                        version			= XPerl_VersionNumber,
                        category		= MYADDONS_CATEGORY_OTHERS,
                        frame			= "XPerl_Globals",
                        optionsframe		= "XPerl_Options"
                        }
	end

	if (GroupHeal and GroupHeal.HealButtons) then
		-- Fix button placement on party frames for GroupHeal addon (worked for Nybmia,
		-- but we have our party targets in that old position
		for k, v in pairs(GroupHeal.HealButtons[1]) do
			v:ClearAllPoints()
			v:SetPoint("TOPLEFT", getglobal(v:GetParent():GetName().."_StatsFrame"), "BOTTOMRIGHT", 0, 2)
		end
	end

	--if (not strfind("Zek Hek Zeks Zekked Zekstuff Pooksie Wazek", UnitName("player")) or GetRealmName() ~= "Bloodhoof") then
	--	XPerl_ShowMessage = function() end
	--end

	XPerl_Init = nil
end

-- XPerl_StatsFrame_Setup
function XPerl_StatsFrameSetup(self, others, offset)
	if (not self) then
		return
	end
	local StatsFrame = getglobal(self:GetName().."_StatsFrame")
	if (not StatsFrame) then
		return
	end

        local healthBar = getglobal(StatsFrame:GetName().."_HealthBar")
        local healthBarText = getglobal(StatsFrame:GetName().."_HealthBarText")
        local healthBarPercent = getglobal(StatsFrame:GetName().."_HealthBarPercent")
        local manaBar = getglobal(StatsFrame:GetName().."_ManaBar")
        local manaBarPercent = getglobal(StatsFrame:GetName().."_ManaBarPercent")
	local otherBars = {}
	local secondaryBarsShown = 0
	local showPercent = 0
	if (healthBarPercent:IsShown() or manaBarPercent:IsShown()) then
		showPercent = 1
	end
        local percentSize = showPercent * 35;   -- 0 means 0, 1 means 32 offset (+3 for spacing after text), which is our size difference

	offset = (offset or 0)

	if (manaBar:IsShown()) then
		secondaryBarsShown = secondaryBarsShown + 1
	end

	local needTicker = 0
	if (XPerlConfig.EnergyTicker == 1 and StatsFrame == XPerl_Player_StatsFrame and UnitPowerType("player") == 3) then
		needTicker = 1
	end

	if (others) then
		for i,other in pairs(others) do
			local bar = getglobal(StatsFrame:GetName().."_"..other)
			if (bar) then
				tinsert(otherBars, bar)

				if (bar:IsShown()) then
					secondaryBarsShown = secondaryBarsShown + 1
				end
			else
				if (not bar) then XPerl_Notice("No frame found called '"..StatsFrame:GetName().."_"..other.."'"); end
			end
		end
	end

	if (XPerlConfig.FatHealthBars == 1) then
		if (StatsFrame == XPerl_Player_Pet_StatsFrame) then
			healthBarText:SetFontObject(GameFontNormalSmall)
		else
			healthBarText:SetFontObject(GameFontNormal)
		end

        	healthBar:ClearAllPoints()
        	healthBar:SetPoint("TOPLEFT", 5, -5)
        	healthBar:SetPoint("BOTTOMRIGHT", -(5 + percentSize), 5 + needTicker + (secondaryBarsShown * 10))

        	manaBar:ClearAllPoints()
        	manaBar:SetPoint("BOTTOMLEFT", 5, -5 + needTicker + (secondaryBarsShown * 10))
        	manaBar:SetPoint("TOPRIGHT", healthBar, "BOTTOMRIGHT", 0, 0)

		local lastBar = manaBar
		local tickerSpace = needTicker * 2
		for i,bar in pairs(otherBars) do
			if (bar:IsShown()) then
        	        	bar:ClearAllPoints()

        	        	bar:SetPoint("TOPLEFT", lastBar, "BOTTOMLEFT", 0, -tickerSpace)
        	        	bar:SetPoint("BOTTOMRIGHT", lastBar, "BOTTOMRIGHT", 0, -10 - tickerSpace)

				lastBar = bar
				tickerSpace = 0
			end
        	end
	else
		healthBarText:SetFontObject(GameFontNormalSmall)

        	healthBar:ClearAllPoints()
        	healthBar:SetPoint("TOPLEFT", 8, -9 + offset)
        	healthBar:SetPoint("BOTTOMRIGHT", StatsFrame, "TOPRIGHT", -(8 + percentSize), -19 + offset)

        	manaBar:ClearAllPoints()
        	manaBar:SetPoint("TOPLEFT", healthBar, "BOTTOMLEFT", 0, -2)
        	manaBar:SetPoint("BOTTOMRIGHT", healthBar, "BOTTOMRIGHT", 0, -12)

		local lastBar = manaBar
		for i,bar in pairs(otherBars) do
			if (bar:IsShown()) then
        	        	bar:ClearAllPoints()

        	        	bar:SetPoint("TOPLEFT", lastBar, "BOTTOMLEFT", 0, -2)
        	        	bar:SetPoint("BOTTOMRIGHT", lastBar, "BOTTOMRIGHT", 0, -12)

				lastBar = bar
			end
        	end
	end
end

-- XPerl_Setup_StatsFrames
function XPerl_Setup_StatsFrames()

	XPerl_StatsFrameSetup(XPerl_Player, {"DruidBar", "XPBar"})
	XPerl_StatsFrameSetup(XPerl_Player_Pet, {"XPBar"}, 2)

	XPerl_StatsFrameSetup(XPerl_Target)
	XPerl_StatsFrameSetup(XPerl_Focus)
	XPerl_StatsFrameSetup(XPerl_TargetTarget)
	XPerl_StatsFrameSetup(XPerl_TargetTargetTarget)

	for i = 1,4 do
		XPerl_StatsFrameSetup(getglobal("XPerl_party"..i))
		XPerl_StatsFrameSetup(getglobal("XPerl_partypet"..i), nil, 2)
	end
end

-- XPerl_SetTransparency
local function XPerl_SetTransparency(num)
	local function Alpha(unit)
		if (UnitIsConnected(unit)) then
			return num
		else
			return num / 2
		end
	end

	local function SetAlpha(f, a)
		if (f) then
			f:SetAlpha(a)
		end
	end

	SetAlpha(XPerl_Player, num)
	SetAlpha(XPerl_Target, Alpha("target"))
	SetAlpha(XPerl_Focus, Alpha("focus"))
	SetAlpha(XPerl_TargetTarget, num)
	SetAlpha(XPerl_TargetTargetTarget, num)
	SetAlpha(XPerl_party1, Alpha("party1"))
	SetAlpha(XPerl_party2, Alpha("party2"))
	SetAlpha(XPerl_party3, Alpha("party3"))
	SetAlpha(XPerl_party4, Alpha("party4"))
	SetAlpha(XPerl_partypet1, Alpha("party1"))
	SetAlpha(XPerl_partypet2, Alpha("party2"))
	SetAlpha(XPerl_partypet3, Alpha("party3"))
	SetAlpha(XPerl_partypet4, Alpha("party4"))
	SetAlpha(XPerl_Player_Pet, num)
	SetAlpha(XPerl_PlayerArcaneBar, num/2)
	SetAlpha(XPerl_TargetArcaneBar, num/2)
	SetAlpha(XPerl_FocusArcaneBar, num/2)
	SetAlpha(XPerl_Party1ArcaneBar, num/2)
	SetAlpha(XPerl_Party2ArcaneBar, num/2)
	SetAlpha(XPerl_Party3ArcaneBar, num/2)
	SetAlpha(XPerl_Party4ArcaneBar, num/2)
end

-- XPerl_SetTextTransparencyFrame
function XPerl_SetTextTransparencyFrame(self)
	local subFrames = {"HealthBarText", "HealthBarPercent", "ManaBarText", "ManaBarPercent"}

	for k,v in pairs(subFrames) do
		local f = getglobal(self:GetName().."_StatsFrame_"..v)
		if (f) then
			f:SetTextColor(1,1,1,XPerlConfig.TextTransparency)
		end
	end
end

-- XPerl_SetTextTransparency
local function XPerl_SetTextTransparency(num)

	local statFrames = {XPerl_Player, XPerl_Player_Pet, XPerl_Target, XPerl_Focus, XPerl_TargetTarget, XPerl_TargetTargetTarget,
				XPerl_party1, XPerl_party2, XPerl_party3, XPerl_party4,
				XPerl_partypet1, XPerl_partypet2, XPerl_partypet3, XPerl_partypet4}

	for k,v in pairs(statFrames) do
		XPerl_SetTextTransparencyFrame(v)
	end

	if (XPerl_Player) then
		XPerl_Player_StatsFrame_DruidBarText:SetTextColor(1,1,1,XPerlConfig.TextTransparency)
		XPerl_Player_StatsFrame_DruidBarPercent:SetTextColor(1,1,1,XPerlConfig.TextTransparency)
		XPerl_Player_StatsFrame_XPBarText:SetTextColor(1,1,1,XPerlConfig.TextTransparency)
		XPerl_Player_StatsFrame_XPBarPercent:SetTextColor(1,1,1,XPerlConfig.TextTransparency)
	end
end

-- XPerl_GetBarTexture
function XPerl_GetBarTexture()
	if (XPerlConfig.BarTextures == 0) then
		return "Interface\\TargetingFrame\\UI-StatusBar"
	elseif (XPerlConfig.BarTextures == 1) then
		return "Interface\\AddOns\\XPerl\\Images\\XPerl_StatusBar"
	else
		return "Interface\\AddOns\\XPerl\\Images\\XPerl_StatusBar"..XPerlConfig.BarTextures
	end
end

-- Set1Bar
local function Set1Bar(bar, tex)
	local f = getglobal(bar:GetName().."Tex")
	if (f) then
		f:SetTexture(tex)
	end
	f = getglobal(bar:GetName().."BG")
	if (f) then
		if (XPerlConfig.BackgroundTextures == 1) then
			f:SetTexture(tex)
		else
			f:SetTexture("Interface\\TargetingFrame\\UI-StatusBar")
		end
	end
end

-- XPerl_RegisterBar
local XPerlBars = {}
function XPerl_RegisterBar(bar)
	tinsert(XPerlBars, bar)
	if (init_done) then
		local tex = XPerl_GetBarTexture()
		Set1Bar(bar, tex)
	end
end

-- XPerl_SetBarTextures
function XPerl_SetBarTextures()
	local tex = XPerl_GetBarTexture()
	for k,v in pairs(XPerlBars) do
		Set1Bar(v, tex)
	end

	if (XPerl_Player) then
		XPerl_Player_StatsFrame_DruidBar:SetStatusBarColor(XPerlConfig.ColourMana.r, XPerlConfig.ColourMana.g, XPerlConfig.ColourMana.b)
		XPerl_Player_StatsFrame_DruidBarBG:SetVertexColor(XPerlConfig.ColourMana.r, XPerlConfig.ColourMana.g, XPerlConfig.ColourMana.b, 0.25)
	end
end

-- XPerl_OptionActions()
function XPerl_OptionActions()

	if (InCombatLockdown()) then
		XPerl_OutOfCombatOptionSet = true
		return
	end

	local function ValidAlpha(alpha)
		alpha = tonumber(alpha)
		if (alpha < 0 or alpha > 1) then
			alpha = 1
		end
		return alpha
	end

	local function ValidScale(scale)
		scale = tonumber(scale)
		if (scale < 0.5) then
			scale = 0.5
		elseif (scale > XPerlConfig.MaximumScale) then
			scale = XPerlConfig.MaximumScale
		end
		return scale
	end

	if (XPerl_Player) then
		XPerl_Player_Set_Bits()
	end
	if (XPerl_Player_Pet) then
		XPerl_Player_Pet_Set_Bits()
	end
	if (XPerl_Target) then
		XPerl_Target_Set_Bits(XPerl_Target)
		XPerl_Target_Set_BlizzCPFrame(XPerl_Target)
	end
	if (XPerl_Focus) then
		XPerl_Target_Set_Bits(XPerl_Focus)
	end
	if (XPerl_TargetTarget) then
		XPerl_TargetTarget_Set_Bits()
	end
	if (XPerl_party1) then
		XPerl_Party_Set_Bits()
	end
	if (XPerl_partypet1) then
		XPerl_Party_Pet_Set_Name()
	end

	XPerlConfig.Transparency = ValidAlpha(XPerlConfig.Transparency)

	XPerlConfig.TextTransparency = ValidAlpha(XPerlConfig.TextTransparency)
	XPerl_SetTextTransparency(XPerlConfig.TextTransparency)

	XPerlConfig.Scale_PlayerFrame = ValidScale(XPerlConfig.Scale_PlayerFrame)
	if (XPerl_Player) then
		XPerl_Player:SetScale(XPerlConfig.Scale_PlayerFrame)
	end

	XPerlConfig.Scale_PetFrame = ValidScale(XPerlConfig.Scale_PetFrame)
	if (XPerl_Player_Pet) then
		XPerl_Player_Pet:SetScale(XPerlConfig.Scale_PetFrame)
	end

	XPerlConfig.Scale_PartyFrame = ValidScale(XPerlConfig.Scale_PartyFrame)
	if (XPerl_ScaleParty) then
		XPerl_ScaleParty(XPerlConfig.Scale_PartyFrame)
	end

	XPerlConfig.Scale_PartyPets = ValidScale(XPerlConfig.Scale_PartyPets)
	if (XPerl_ScalePartyPets) then
		XPerl_ScalePartyPets(XPerlConfig.Scale_PartyPets)
	end

	XPerlConfig.Scale_TargetFrame = ValidScale(XPerlConfig.Scale_TargetFrame)
	if (XPerl_Target) then
		XPerl_Target:SetScale(XPerlConfig.Scale_TargetFrame)
	end
	XPerlConfig.Scale_FocusFrame = ValidScale(XPerlConfig.Scale_FocusFrame)
	if (XPerl_Focus) then
		XPerl_Focus:SetScale(XPerlConfig.Scale_FocusFrame)
	end
	XPerlConfig.Scale_TargetTargetFrame = ValidScale(XPerlConfig.Scale_TargetTargetFrame)
	if (XPerl_ScaleTargetTarget) then
		XPerl_ScaleTargetTarget(XPerlConfig.Scale_TargetTargetFrame)
	end

	XPerlConfig.Scale_Raid = ValidScale(XPerlConfig.Scale_Raid)
	if (XPerl_ScaleRaid) then
		XPerl_ScaleRaid(XPerlConfig.Scale_Raid)
	end

	if (XPerl_ArcaneBar_Set) then
		XPerl_ArcaneBar_Set()
	end

	XPerl_SetBarTextures()
	XPerl_Setup_StatsFrames()

	XPerl_SetAllFrames()
	XPerl_SetTransparency(XPerlConfig.Transparency)

	if (XPerl_Player) then				XPerl_Player_UpdateDisplay(XPerl_Player)		end
	if (XPerl_Player_Pet_UpdateDisplay) then	XPerl_Player_Pet_UpdateDisplay (XPerl_Player_Pet)	end
	if (XPerl_Target) then				XPerl_Target_UpdateDisplay(XPerl_Target)		end
	if (XPerl_Focus) then				XPerl_Target_UpdateDisplay(XPerl_Focus)			end
	if (XPerl_TargetTarget) then
		XPerl_TargetTarget_UpdateDisplay(XPerl_TargetTarget)
		if (XPerl_TargetTargetTarget) then
			XPerl_TargetTarget_UpdateDisplay(XPerl_TargetTargetTarget)
		end
	end

	if (XPerl_party1) then				XPerl_Party_UpdateDisplayAll()		end
	if (XPerl_partypet1) then			XPerl_Party_Pet_UpdateDisplayAll()	end

	if (XPerl_Raid_OptionActions) then
		XPerl_Raid_OptionActions()
	end
end
