local XPerl_Target_Events = {}

----------------------
-- Loading Function --
----------------------

function XPerl_Target_OnLoad(self)
	CombatFeedback_Initialize(getglobal(self:GetName().."_CastClickOverlayHitIndicator"), 30)

	local events = {"UNIT_COMBAT", "PLAYER_FLAGS_CHANGED",
		"PARTY_MEMBER_DISABLE", "PARTY_MEMBER_ENABLE", "RAID_TARGET_UPDATE", "PARTY_MEMBERS_CHANGED",
		"PARTY_LEADER_CHANGED", "PARTY_LOOT_METHOD_CHANGED"}
	for i,event in pairs(events) do
		self:RegisterEvent(event)
	end

	local partyid = self:GetAttribute("unit")

	if (partyid == "target") then
		self.optPrefix = "Target"
		self:RegisterEvent("PLAYER_TARGET_CHANGED")
		self:RegisterEvent("PLAYER_COMBO_POINTS")

		XPerl_SecureUnitButton_OnLoad(getglobal(self:GetName().."_CastClickOverlay"), "target",
        		function(self)
                		HideDropDownMenu(1)
                		ToggleDropDownMenu(1, nil, TargetFrameDropDown, "XPerl_Target_StatsFrame", 0, 0)
        		end
		)

		XPerl_Target_CPMeter:SetMinMaxValues(0, 5)

	else
		self.optPrefix = "Focus"
		self:RegisterEvent("PLAYER_FOCUS_CHANGED")

		XPerl_SecureUnitButton_OnLoad(getglobal(self:GetName().."_CastClickOverlay"), "focus",
        		function(self)
                		HideDropDownMenu(1)
                		ToggleDropDownMenu(1, nil, TargetFrameDropDown, "XPerl_Focus_StatsFrame", 0, 0)
        		end
		)

		getglobal(self:GetName().."_CastClickOverlayHitIndicator"):SetPoint("CENTER", XPerl_Focus_PortraitFrame, "CENTER", 0, 0)
	end

	XPerl_RegisterClickCastFrame(getglobal(self:GetName().."_CastClickOverlay"))

	XPerl_UnitEvents(self, XPerl_Target_Events, {"UNIT_SPELLMISS", "UNIT_FACTION", "UNIT_DYNAMIC_FLAGS", "UNIT_FLAGS",
				"UNIT_CLASSIFICATION_CHANGED", "UNIT_MODEL_CHANGED", "UNIT_AURA"})
	XPerl_RegisterBasics(self, XPerl_Target_Events)

	--self.PlayerFlash = 0
	self.perlBuffs = 0
	self.perlDebuffs = 0
	self.RangeUpdate = 1

	--XPerl_InitFadeFrame(self)

	if (partyid == "target" and XPerl_Target_AssistFrame) then
		-- Since target module is loaded after raid helper, we have to attach this manually
		-- because the target frame did not exist when this frame was created
		XPerl_Target_AssistFrame:SetParent(XPerl_Target_CastClickOverlay)
		XPerl_Target_AssistFrame:ClearAllPoints()
		XPerl_Target_AssistFrame:SetPoint("TOPLEFT", XPerl_Target_PortraitFrame, "TOPRIGHT", -2, -20)
	end

	-- Set here to reduce amount of function calls made
	self:SetScript("OnEvent", XPerl_Target_OnEvent)
	self:SetScript("OnUpdate", XPerl_Target_OnUpdate)
	self:SetScript("OnShow", XPerl_Target_UpdatePortrait)

	XPerl_RegisterHighlight(getglobal(self:GetName().."_CastClickOverlay"), 3)
	XPerl_RegisterPerlFrames(self, {"NameFrame", "StatsFrame", "LevelFrame", "PortraitFrame", "TypeFramePlayer", "CreatureType", "BossFrame", "CPFrame"})

	self.FlashFrames = {getglobal(self:GetName().."_PortraitFrame"), getglobal(self:GetName().."_NameFrame"),
				getglobal(self:GetName().."_LevelFrame"), getglobal(self:GetName().."_StatsFrame"),
				getglobal(self:GetName().."_BossFrame"), getglobal(self:GetName().."_TypeFramePlayer"),
				getglobal(self:GetName().."_CreatureType")}

	XPerl_ArcaneBar_RegisterFrame(getglobal(self:GetName().."_NameFrame"), partyid, "ArcaneBar"..self.optPrefix)
end

--------------------
-- Buff Functions --
--------------------
local function GetBuffButton(self, buffnum, debuff, createIfAbsent)

	local buffType
	if (debuff == 1) then
		buffType = "DeBuff"
	else
		buffType = "Buff"
	end
	local name = self:GetName().."_BuffFrame_"..buffType..buffnum
	local button = getglobal(name)

	if (not button and createIfAbsent) then
		local parent
		if (self == XPerl_Target) then
			parent = XPerl_Target_BuffFrame
		else
			parent = getglobal(self:GetName().."_BuffFrame")
		end

		button = CreateFrame("Button", name, parent, "XPerl_"..buffType.."Template")
		button:SetID(buffnum)

		local size = XPerlConfig[self.optPrefix.."BuffSize"] * (1 + (0.2 * debuff))
		button:SetHeight(size)
		button:SetWidth(size)

		if (debuff == 1) then
			button:SetScript("OnEnter", XPerl_Target_SetDeBuffTooltip)
		else
			button:SetScript("OnEnter", XPerl_Target_SetBuffTooltip)
		end
		button:SetScript("OnLeave", XPerl_PlayerTipHide)

		button:ClearAllPoints()
		if (buffnum == 1) then
			button:SetPoint("TOPLEFT", 0, 0)
		else
			local prevButton = getglobal(self:GetName().."_BuffFrame_"..buffType..(buffnum - 1))
			button:SetPoint("TOPLEFT", prevButton, "TOPRIGHT", 1 + debuff, 0)
		end
	end

	return button
end

-- This gets complicated. When we're the target frame, we have to wrap to next line of buffs if there's no mana on the target, or if the mob type frame is shown
-- And if the mob type frame is shown, AND there's no mana, then we may have to use small width on 2 rows, depending on buff size.
-- displayWidth is our current row max
-- displayWidthExtra is the max size after any short rows
-- displayWidthStart remembers the short row size for 2nd pass
function XPerl_Targets_BuffPositions(self)
	local unitTarget = self:GetAttribute("unit")
	local argFramePrefix = self:GetName().."_"
	local above = 0
	if (self == XPerl_Target or self == XPerl_Focus) then
		above = XPerlConfig[self.optPrefix.."BuffsAbove"] == 1
	else
		above = XPerlConfig.TargetTargetBuffsAbove == 1
	end

	local buffFrame = getglobal(argFramePrefix.."BuffFrame")
	local nameFrame = getglobal(argFramePrefix.."NameFrame")
	local statsFrame = getglobal(argFramePrefix.."StatsFrame")
	local creatureTypeFrame = getglobal(self:GetName().."_CreatureType")
	if (above) then
		buffFrame:ClearAllPoints()
		buffFrame:SetPoint("BOTTOMLEFT", nameFrame, "TOPLEFT", 2, 0)
	else
		buffFrame:ClearAllPoints()
		buffFrame:SetPoint("TOPLEFT", statsFrame, "BOTTOMLEFT", 2, 0)
	end

	local nameBuff, rankBuff, unitBuff = XPerl_UnitBuff(unitTarget, 1, XPerlConfig[self.optPrefix.."CastableBuffs"])
	local buff1 = GetBuffButton(self, 1, 0, true)
	nameBuff, rankBuff, unitBuff = XPerl_UnitDebuff(unitTarget, 1, XPerlConfig[self.optPrefix.."CastableBuffs"])
	local debuff1 = GetBuffButton(self, 1, 1, true)

	local buffHeight, debuffHeight
	if (buff1) then
		buffHeight = math.floor(buff1:GetHeight() + 1.5)
	else
		buffHeight = 21
	end
	if (debuff1) then
		debuffHeight = math.floor(debuff1:GetHeight() + 2.5)
	else
		debuffHeight = 23
	end
	local displayWidth = math.floor(getglobal(argFramePrefix.."StatsFrame"):GetWidth() - 3.5)
	local displayWidthStart = displayWidth
	local displayWidthExtra = displayWidth
	local mana = UnitManaMax(unitTarget)
	local buffRows = 1
	local debuffRows = 1

	local pframe = getglobal(argFramePrefix.."PortraitFrame")
	if (pframe) then
		displayWidthExtra = displayWidthExtra + math.floor(pframe:GetWidth() - 3.5)
	end

	if (unitTarget == "target" or unitTarget == "focus") then
		if (XPerlConfig["Show"..self.optPrefix.."Level"] == 1 or XPerlConfig["Show"..self.optPrefix.."ClassIcon"] == 1) then
			pframe = getglobal(argFramePrefix.."LevelFrame")
			if (pframe) then
				displayWidthExtra = displayWidthExtra + math.floor(pframe:GetWidth() - 3.5)
			end
		end

		if (above or (creatureTypeFrame and not creatureTypeFrame:IsShown()) or UnitFactionGroup("player") ~= UnitFactionGroup(unitTarget)) then
			displayWidth = displayWidthExtra
		end
	else
		displayWidthExtra = displayWidth
		displayWidthStart = displayWidth
	end

	local unitBuffName, unitBuffRank, unitBuff = XPerl_UnitBuff(unitTarget, 1, XPerlConfig[self.optPrefix.."CastableBuffs"])
	local buffPrev = buff1
	local buffRowStart = buffPrev
	local buffsWidth = buffHeight
	self.buffData = {{row = 1, buff = buffRowStart}}
	for i = 2,20 do
		unitBuffName, unitBuffRank, unitBuff = XPerl_UnitBuff(unitTarget, i, XPerlConfig[self.optPrefix.."CastableBuffs"])
		local buff = GetBuffButton(self, i, 0, unitBuff and (buffRows <= XPerlConfig[self.optPrefix.."BuffRows"]))

		if (buff) then
			buff:ClearAllPoints()
			if (buffsWidth + buffHeight > displayWidth) then
				if (above) then
					buff:SetPoint("BOTTOMLEFT", buffRowStart, "TOPLEFT", 0, -1)
				else
					buff:SetPoint("TOPLEFT", buffRowStart, "BOTTOMLEFT", 0, -1)
				end
				buffRowStart = buff

				if (buffRows > 1 or mana > 0 or buffHeight > 26 or (creatureTypeFrame and not creatureTypeFrame:IsShown())) then
					displayWidth = displayWidthExtra
				end

				buffsWidth = 0
				buffRows = buffRows + 1
			else
				buff:SetPoint("TOPLEFT", buffPrev, "TOPRIGHT", 1, 0)
			end

			buffsWidth = buffsWidth + buffHeight
			buffPrev = buff
		end
		tinsert(self.buffData, {row = buffRows, buff = buffRowStart})
	end

	if (not above) then
		if ((UnitFactionGroup("player") == UnitFactionGroup(unitTarget))) then
			if (mana == 0) then
				if (buffRows > 1 or buffHeight > 25) then
					displayWidth = displayWidthExtra
				else
					displayWidth = displayWidthStart
				end
			else
				displayWidth = displayWidthExtra
			end
		else
			if ((unitTarget == "target" or unitTarget == "focus") and (mana == 0 or (creatureTypeFrame and creatureTypeFrame:IsShown()))) then
				displayWidth = displayWidthStart
			else
				displayWidth = displayWidthExtra
			end
		end
	end

	local unitDebuffName, unitDebuffRank, unitDebuff = XPerl_UnitDebuff(unitTarget, 1, XPerlConfig[self.optPrefix.."CastableBuffs"])
	buffPrev = debuff1
	buffRowStart = buffPrev
	buffsWidth = debuffHeight
	self.debuffData = {{row = 1, buff = buffRowStart}}
	for i = 2,40 do
		unitDebuffName, unitDebuffRank, unitDebuff = XPerl_UnitDebuff(unitTarget, i, XPerlConfig[self.optPrefix.."CastableBuffs"])
		local buff = GetBuffButton(self, i, 1, unitDebuff and (debuffRows <= XPerlConfig[self.optPrefix.."BuffRows"]))

		if (buff) then
			buff:ClearAllPoints()
			if (buffsWidth + debuffHeight > displayWidth) then
				if (above) then
					buff:SetPoint("BOTTOMLEFT", buffRowStart, "TOPLEFT", 0, 2)
				else
					buff:SetPoint("TOPLEFT", buffRowStart, "BOTTOMLEFT", 0, -2)
				end
				buffRowStart = buff

				if (debuffRows > 1 or mana > 0 or debuffHeight > 26 or (not creatureTypeFrame or not creatureTypeFrame:IsShown())) then
					displayWidth = displayWidthExtra
				end

				buffsWidth = 0
				debuffRows = debuffRows + 1
			else
				buff:SetPoint("TOPLEFT", buffPrev, "TOPRIGHT", 2, 0)
			end

			buffsWidth = buffsWidth + debuffHeight
			buffPrev = buff
		end
		tinsert(self.debuffData, {row = debuffRows, buff = buffRowStart})
	end
end

-- XPerl_Targets_BuffUpdate
function XPerl_Targets_BuffUpdate(self, argFramePrefix)
	if (self == XPerl_Target) then
		above = XPerlConfig[self.optPrefix.."BuffsAbove"] == 1
	else
		above = XPerlConfig.TargetTargetBuffsAbove == 1
	end

	local partyid = self:GetAttribute("unit")
	if (UnitExists(partyid)) then
		self.perlBuffs = 0
		self.perlDebuffs = 0

		for buffnum=1,20 do
			local hide = false
			if (self.buffData and self.buffData[buffnum] and self.buffData[buffnum].row > XPerlConfig[self.optPrefix.."BuffRows"]) then
				hide = true
			else
				local name, rank, buff, count = XPerl_UnitBuff(partyid, buffnum, XPerlConfig[self.optPrefix.."CastableBuffs"])

				if (buff) then
					local button = GetBuffButton(self, buffnum, 0, true)
					local icon = getglobal(button:GetName().."Icon")

					self.perlBuffs = self.perlBuffs + 1
					local buffCount = getglobal(button:GetName().."Count")

					icon:SetTexture(buff)
					if (count > 1) then
						buffCount:SetText(count)
						buffCount:Show()
					else
						buffCount:Hide()
					end
					button:Show()
				else
					hide = true
				end
			end

			if (hide) then
				local button = getglobal(argFramePrefix.."BuffFrame_Buff"..buffnum)
				if (button) then
					button:Hide()
				end
			end
		end

		for buffnum=1,40 do
			local hide = false
			if (self.debuffData and self.debuffData[buffnum] and self.debuffData[buffnum].row > XPerlConfig[self.optPrefix.."BuffRows"]) then
				hide = true
			else
				local name, rank, debuff, debuffApplications, debuffType = XPerl_UnitDebuff(partyid, buffnum, XPerlConfig[self.optPrefix.."CurableDebuffs"])

				if (debuff) then
					local button = GetBuffButton(self, buffnum, 1, true)
					local icon = getglobal(button:GetName().."Icon")

					self.perlDebuffs = self.perlDebuffs + 1
					local debuffCount = getglobal(button:GetName().."Count")

					icon:SetTexture(debuff)
					if ( debuffApplications > 1 ) then
						debuffCount:SetText(debuffApplications)
						debuffCount:Show()
					else
						debuffCount:Hide()
					end

					local borderColor = DebuffTypeColor[(debuffType or "none")]
					local buffBorder = getglobal(button:GetName().."Border")
					buffBorder:SetVertexColor(borderColor.r, borderColor.g, borderColor.b)

					button:Show()
				else
					hide = true
				end
			end

			if (hide) then
				local button = getglobal(argFramePrefix.."BuffFrame_DeBuff"..buffnum)
				if (button) then
					button:Hide()
				end
			end
		end

		local buff1 = getglobal(argFramePrefix.."BuffFrame_Buff1")
		local debuff1 = getglobal(argFramePrefix.."BuffFrame_DeBuff1")
		if (buff1 or debuff1) then
			if (buff1) then buff1:ClearAllPoints() end
			if (debuff1) then debuff1:ClearAllPoints() end

			if ((UnitFactionGroup("player") == UnitFactionGroup(partyid))) then
				if (buff1) then
					if (above) then
						buff1:SetPoint("BOTTOMLEFT", 0, 0)
					else
						buff1:SetPoint("TOPLEFT", 0, 0)
					end
				end
				if (debuff1) then
					local mark = self.perlBuffs
					if (mark < 1) then
						mark = 1
					end
					if (above) then
						debuff1:SetPoint("BOTTOMLEFT", self.buffData[mark].buff, "TOPLEFT", 0, 2)
					else
						debuff1:SetPoint("TOPLEFT", self.buffData[mark].buff, "BOTTOMLEFT", 0, -2)
					end
				end
			else
				if (debuff1) then
					if (above) then
						debuff1:SetPoint("BOTTOMLEFT", 0, 0)
					else
						debuff1:SetPoint("TOPLEFT", 0, 0)
					end
				end
				if (buff1) then
					local mark = self.perlDebuffs
					if (mark < 1) then
						mark = 1
					end
					if (self.perlDebuffs > 0) then
						if (above) then
							buff1:SetPoint("BOTTOMLEFT", self.debuffData[mark].buff, "TOPLEFT", 0, 2)
						else
							buff1:SetPoint("TOPLEFT", self.debuffData[mark].buff, "BOTTOMLEFT", 0, -2)
						end
					end
				end
			end
		end
	end
end

-- XPerl_Target_SetBuffTooltip
function XPerl_Target_SetBuffTooltip (self)
	local frame = self:GetParent():GetParent()

	GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")

	local partyid = frame:GetAttribute("unit")
	XPerl_TooltipSetUnitBuff(GameTooltip, partyid, self:GetID(), XPerlConfig[frame.optPrefix.."CastableBuffs"])
	XPerl_ToolTip_AddBuffDuration(partyid)
end

-- XPerl_Target_SetDeBuffTooltip
function XPerl_Target_SetDeBuffTooltip (self)
	local frame = self:GetParent():GetParent()

	GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")

	local partyid = frame:GetAttribute("unit")
	XPerl_TooltipSetUnitDebuff(GameTooltip, partyid, self:GetID(), XPerlConfig[frame.optPrefix.."CurableDebuffs"])
	XPerl_ToolTip_AddDebuffDuration(partyid, nil, self:GetID(), XPerlConfig[frame.optPrefix.."CurableDebuffs"])
end

-- GetComboColour
local function GetComboColour(num)
	if (num == 5) then		return 1,   0, 0
	elseif (num == 4) then		return 1, 0.5, 0
	elseif (num == 3) then		return 1,   1, 0
	elseif (num == 2) then		return 0.5, 1, 0
	elseif (num == 1) then		return 0,   1, 0
	end
end

---------------
-- Combo Points
---------------
local function XPerl_Target_UpdateCombo(self)
	if (self == XPerl_Target) then
		local combopoints = GetComboPoints()
		local r, g, b = GetComboColour(combopoints)
		if (XPerlConfig.UseCPMeter == 1) then
			XPerl_Target_CPFrame:Hide()
			XPerl_Target_CPMeter:SetValue(combopoints)
			XPerl_Target_CPMeter:Show()
			if (r) then
				XPerl_Target_CPMeter:SetStatusBarColor(r, g, b, 0.7)
			else
				XPerl_Target_CPMeter:Hide()
			end
		elseif (XPerlConfig.BlizzardCPMeter == 0) then
			XPerl_Target_CPMeter:Hide()
			XPerl_Target_CPFrame:Show()
			XPerl_Target_CPFrameText:SetText(combopoints)
			if (r) then
				XPerl_Target_CPFrameText:SetTextColor(r, g, b)
			else
				XPerl_Target_CPFrame:Hide()
			end
		end
	end
end

-- XPerl_UnitDebuffInformation
local function XPerl_UnitDebuffInformation(self, debuff)
	local i = 1
	local partyid = self:GetAttribute("unit")

	while UnitDebuff(partyid, i) do
		XPerlBuffStatusTooltip:SetUnitDebuff(partyid, i )
		if (XPerlBuffStatusTooltipTextLeft1:GetText() == debuff) then
			_, _, _, debuffApplications = UnitDebuff(partyid, i)
			return debuffApplications
		end

		i = i + 1
	end

	return 0
end

---------------------
--Debuffs          --
---------------------
local function XPerl_Target_DebuffUpdate(self)
	local partyid = self:GetAttribute("unit")
	if (self == XPerl_Target) then
		if (GetComboPoints() == 0) then
			local numDebuffs = 0
			local _, class = UnitClass("player")

			if (class == "WARRIOR") then
				numDebuffs = XPerl_UnitDebuffInformation(self, XPERL_SPELL_SUNDER)
			elseif (class == "PRIEST") then
				numDebuffs = XPerl_UnitDebuffInformation(self, XPERL_SPELL_SHADOWV)
			elseif (class == "MAGE") then
				numDebuffs = XPerl_UnitDebuffInformation(self, XPERL_SPELL_FIREV)

				if (numDebuffs == 0) then
					numDebuffs = XPerl_UnitDebuffInformation(self, XPERL_SPELL_WINTERCH)
				end
			end

			local r, g, b = GetComboColour(numDebuffs)
			if (XPerlConfig.UseCPMeter == 1) then
				XPerl_Target_CPFrame:Hide()
				XPerl_Target_CPMeter:SetValue(numDebuffs)
				XPerl_Target_CPMeter:Show()
				if (r) then
					XPerl_Target_CPMeter:SetStatusBarColor(r, g, b, 0.4)
				else
					XPerl_Target_CPMeter:Hide()
				end
			else
				XPerl_Target_CPMeter:Hide()
				XPerl_Target_CPFrame:Show()
				XPerl_Target_CPFrameText:SetText(numDebuffs)
				if (r) then
					XPerl_Target_CPFrameText:SetTextColor(r, g, b)
				else
					XPerl_Target_CPFrame:Hide()
				end
			end
		else
			XPerl_Target_UpdateCombo(self)
		end
	end
end

-------------------------
-- The Update Functions--
-------------------------
local function XPerl_Target_UpdatePVP(self)
	local partyid = self:GetAttribute("unit")
	local targetrankname, targetrank=GetPVPRankInfo(UnitPVPRank(partyid), partyid)
	local pvpRankIcon = getglobal(self:GetName().."_NameFrame_PVPRankIcon")
	local pvpStatusIcon = getglobal(self:GetName().."_NameFrame_PVPStatus")

	if (targetrank and XPerlConfig["Show"..self.optPrefix.."PVPRank"] == 1 and UnitIsPlayer(partyid)) then
		pvpRankIcon:Show()
		if (targetrank==0) then
			pvpRankIcon:Hide()
		else
			pvpRankIcon:SetTexture(string.format("Interface\\PVPRankBadges\\PVPRank%02d", targetrank))
		end
	else
		pvpRankIcon:Hide()
	end
	if (XPerlConfig["Show"..self.optPrefix.."PVP"] == 1 and UnitIsPVP(partyid)) then
		pvpStatusIcon:SetTexture("Interface\\TargetingFrame\\UI-PVP-"..(UnitFactionGroup(partyid) or "FFA"))
		pvpStatusIcon:Show()
	else
		pvpStatusIcon:Hide()
	end
	XPerl_SetUnitNameColor(partyid, getglobal(self:GetName().."_NameFrame_NameBarText"))

	if (XPerlConfig[self.optPrefix.."ReactionHighlight"] == 1) then
		local c = XPerl_ReactionColour(partyid)
		getglobal(self:GetName().."_NameFrame"):SetBackdropColor(c.r, c.g, c.b)
	end

        if (UnitIsVisible(partyid) and UnitIsCharmed(partyid)) then
		getglobal(self:GetName().."_NameFrame_Warning"):Show()
	else
		getglobal(self:GetName().."_NameFrame_Warning"):Hide()
	end
end

-- XPerl_Target_UpdateName
local function XPerl_Target_UpdateName(self)
	local partyid = self:GetAttribute("unit")
	local targetname = UnitName(partyid)
	getglobal(self:GetName().."_NameFrame_NameBarText"):SetText(targetname)
	XPerl_Target_UpdatePVP(self)
end

-- XPerl_Target_UpdatePortrait
function XPerl_Target_UpdatePortrait(self)
	if (XPerlConfig["Show"..self.optPrefix.."Portrait"] == 1) then
		local partyid = self:GetAttribute("unit")
		if (UnitExists(partyid)) then
			if (UnitIsVisible(partyid) and XPerlConfig["Show"..self.optPrefix.."Portrait3D"] == 1) then
				getglobal(self:GetName().."_PortraitFrame_Portrait"):Hide()
				getglobal(self:GetName().."_PortraitFrame_Portrait3D"):Show()
				XPerlSetPortrait3D(getglobal(self:GetName().."_PortraitFrame_Portrait3D"), partyid)
			else
				getglobal(self:GetName().."_PortraitFrame_Portrait"):Show()
				getglobal(self:GetName().."_PortraitFrame_Portrait3D"):Hide()
				SetPortraitTexture(getglobal(self:GetName().."_PortraitFrame_Portrait"), partyid)
			end
		end
	end
end

-- XPerl_Target_UpdateLevel
local function XPerl_Target_UpdateLevel(self)
	local partyid = self:GetAttribute("unit")
	local targetlevel = UnitLevel(partyid)
	getglobal(self:GetName().."_LevelFrameText"):SetText(targetlevel)
	-- Set Level
	if (XPerlConfig["Show"..self.optPrefix.."Level"] == 1) then
		getglobal(self:GetName().."_LevelFrame"):Show()
		getglobal(self:GetName().."_LevelFrame"):SetWidth(27)
		if (targetlevel < 0) then
			getglobal(self:GetName().."_LevelFrameText"):SetTextColor(1, 0, 0)
			getglobal(self:GetName().."_LevelFrame"):Hide()
		else
			local color = GetDifficultyColor(targetlevel)
			getglobal(self:GetName().."_LevelFrameText"):SetTextColor(color.r, color.g, color.b)
		end
                if (XPerlConfig["Show"..self.optPrefix.."Elite"] == 0 and (UnitClassification(partyid) == "elite" or UnitClassification(partyid) == "worldboss")) then --(UnitIsPlusMob(partyid))) then
			getglobal(self:GetName().."_LevelFrameText"):SetText(targetlevel.."+")
			getglobal(self:GetName().."_LevelFrame"):SetWidth(33)
		end
	end
end

-- XPerl_Target_UpdateClassification
local function XPerl_Target_UpdateClassification(self)
	local partyid = self:GetAttribute("unit")
	local targetclassification = UnitClassification(partyid)

	local bossFrame = getglobal(self:GetName().."_BossFrame")
	local bossFrameText = getglobal(self:GetName().."_BossFrameText")

	if (UnitIsCivilian(partyid)) then
		bossFrameText:SetText(XPERL_TYPE_CIVILIAN)
                bossFrameText:SetTextColor(1, 0, 0)
	        bossFrame:Show()

	elseif (targetclassification == "normal" and UnitPlayerControlled(partyid)) then
		if (not UnitIsPlayer(partyid)) then
			bossFrameText:SetText(XPERL_TYPE_PET)
	                bossFrameText:SetTextColor(1, 1, 1)
		        bossFrame:Show()
		else
	        	bossFrame:Hide()
		end

	elseif ((XPerlConfig["Show"..self.optPrefix.."Level"] == 1 and XPerlConfig["Show"..self.optPrefix.."Elite"] ==1) or targetclassification=="Rare+" or targetclassification=="Rare") then
		bossFrame:Show()
		if (targetclassification == "worldboss") then
			bossFrameText:SetText(XPERL_TYPE_BOSS)
	                bossFrameText:SetTextColor(1, 0.5, 0.5)

		elseif (targetclassification == "rareelite") then
			bossFrameText:SetText(XPERL_TYPE_RAREPLUS)
	                bossFrameText:SetTextColor(0.8, 0.8, 0.8)

		elseif (targetclassification == "elite") then
			bossFrameText:SetText(XPERL_TYPE_ELITE)
	                bossFrameText:SetTextColor(1, 1, 0.5)

		elseif (targetclassification == "rare") then
			bossFrameText:SetText(XPERL_TYPE_RARE)
	                bossFrameText:SetTextColor(0.8, 0.8, 0.8)

		else
			bossFrame:Hide()
		end
        else
                bossFrame:Hide()
	end

	bossFrame:SetWidth(bossFrameText:GetStringWidth() + 10)
end

-- XPerl_Target_UpdateType
local function XPerl_Target_UpdateType(self)
	local partyid = self:GetAttribute("unit")
	local targettype = UnitCreatureType(partyid)

	local creatureTypeFrame = getglobal(self:GetName().."_CreatureType")
	local creatureTypeText = getglobal(self:GetName().."_CreatureTypeText")

	if (targettype == XPERL_TYPE_NOT_SPECIFIED) then
		targettype = nil
	end

	if (XPerlConfig["Show"..self.optPrefix.."MobType"] == 1) then
		creatureTypeFrame:Show()
	else
		creatureTypeFrame:Hide()
	end

	getglobal(self:GetName().."_TypeFramePlayer"):Hide()
	creatureTypeText:SetText(targettype)

	if (UnitIsPlayer(partyid)) then
		local _, PlayerClass = UnitClass(partyid)
		if (XPerlConfig["Show"..self.optPrefix.."ClassIcon"] ==1) then
			local r, l, t, b = XPerl_ClassPos(PlayerClass)
			getglobal(self:GetName().."_TypeFramePlayer_ClassTexture"):SetTexCoord(r, l, t, b)
			getglobal(self:GetName().."_TypeFramePlayer"):Show()
		end
		creatureTypeFrame:Hide()
	else
		if (targettype and targettype ~= "") then
			creatureTypeText:SetTextColor(1, 1, 1)
			creatureTypeFrame:SetWidth(getglobal(self:GetName().."_CreatureTypeText"):GetStringWidth() + 10)
		else
			creatureTypeFrame:Hide()
		end
	end

	-- If it's too long, we anchor it to left side of portrait instead of right, to avoid it overlapping some buffs
	creatureTypeFrame:ClearAllPoints()
	if (creatureTypeFrame:GetWidth() > getglobal(self:GetName().."_PortraitFrame"):GetWidth()) then
		creatureTypeFrame:SetPoint("TOPLEFT", getglobal(self:GetName().."_PortraitFrame"), "BOTTOMLEFT", 0, 2)
	else
		creatureTypeFrame:SetPoint("TOPRIGHT", getglobal(self:GetName().."_PortraitFrame"), "BOTTOMRIGHT", 0, 2)
	end
end

-- XPerl_Target_UpdateManaType
local function XPerl_Target_UpdateManaType(self)
	XPerl_Target_SetManaType(self)
end

-- XPerl_Target_SetManaType
function XPerl_Target_SetManaType(self)
	local partyid = self:GetAttribute("unit")
	local frameManaBar = getglobal(self:GetName().."_StatsFrame_ManaBar")
	local frameManaBarText = getglobal(self:GetName().."_StatsFrame_ManaBarText")
	local frameStatsFrame = getglobal(self:GetName().."_StatsFrame")

	local targetmanamax = UnitManaMax(partyid)

	if ((targetmanamax == 0) or ((partyid == "target" or partyid == "focus") and XPerlConfig["Show"..self.optPrefix.."Mana"] ==0) or (strmatch(partyid, "targettarget") and XPerlConfig.ShowTargetTargetMana == 0)) then
		if (frameManaBar:IsShown()) then
			frameManaBar:Hide()

			if (self == XPerl_Target or self == XPerl_Focus) then
				frameStatsFrame:SetHeight(28 + (XPerlConfig.FatHealthBars * 2))
				XPerl_StatsFrameSetup(self)
			end
		end
		return
	end

	XPerl_SetManaBarType(partyid, frameManaBar)

	local targetmana = UnitMana(partyid)

	if (not frameManaBar:IsShown()) then
		frameManaBarText:Show()
		frameManaBar:Show()
		if (self == XPerl_Target or self == XPerl_Focus) then
			frameStatsFrame:SetHeight(40)
			XPerl_StatsFrameSetup(self)
		end
	end
end

-- XPerl_Target_UpdateMana
local function XPerl_Target_UpdateMana(self)
	XPerl_Target_SetMana(self)
end

-- XPerl_Target_SetMana
function XPerl_Target_SetMana(self)
	local partyid = self:GetAttribute("unit")
	local frameManabar = getglobal(self:GetName().."_StatsFrame_ManaBar")
	local frameHealthBarPercent = getglobal(self:GetName().."_StatsFrame_HealthBarPercent")
	local frameManaBarPercent = getglobal(self:GetName().."_StatsFrame_ManaBarPercent")
	local frameManaBarText = getglobal(self:GetName().."_StatsFrame_ManaBarText")

	local targetmana = UnitMana(partyid)
	local targetmanamax = UnitManaMax(partyid)
	if (frameHealthBarPercent:IsVisible()) then
		frameManaBarPercent:Show()
	end

	if (targetmanamax == 1 and targetmana > targetmanamax) then
		targetmanamax = targetmana
	end

	frameManabar:SetMinMaxValues(0, targetmanamax)
	frameManabar:SetValue(targetmana)

	frameManaBarPercent:SetText(string.format("%d",(100*(targetmana / targetmanamax))+0.5).."%")
	frameManaBarText:SetText(targetmana.."/"..targetmanamax)
end

-- XPerl_Target_UpdateHealth
local function XPerl_Target_UpdateHealth(self)
	XPerl_Target_SetHealth(self, XPerlConfig["Show"..self.optPrefix.."Percent"])

	if (XPerlConfig["Show"..self.optPrefix.."Values"] == 1) then
		getglobal(self:GetName().."_StatsFrame_HealthBarText"):Show()
		getglobal(self:GetName().."_StatsFrame_ManaBarText"):Show()
	else
		getglobal(self:GetName().."_StatsFrame_HealthBarText"):Hide()
		getglobal(self:GetName().."_StatsFrame_ManaBarText"):Hide()
	end

	local partyid = self:GetAttribute("unit")
	if (not UnitIsConnected(partyid)) then
		getglobal(self:GetName().."_StatsFrame_HealthBarText"):SetText(XPERL_LOC_OFFLINE)
		self:SetAlpha(XPerlConfig.Transparency / 2)
	else
		self:SetAlpha(XPerlConfig.Transparency)
	end
end

-- XPerl_Target_SetHealth
function XPerl_Target_SetHealth(self, bPercent)
	local partyid = self:GetAttribute("unit")
	local selfid = self:GetName().."_StatsFrame_"
	local frameHealthBar = getglobal(selfid.."HealthBar")
	local frameHealthBarPercent = getglobal(selfid.."HealthBarPercent")
	local frameHealthBarText = getglobal(selfid.."HealthBarText")
	local frameManaBarPercent = getglobal(selfid.."ManaBarPercent")

	local targethealth, targethealthmax = UnitHealth(partyid), UnitHealthMax(partyid)
	if (targethealth > targethealthmax) then
--ChatFrame1:AddMessage("NOTE: 1.12.1 glitch still exists")
		-- New glitch with 1.12.1
		if (UnitIsDeadOrGhost(partyid)) then
			targethealth = 0
		else
			targethealth = targethealthmax
		end
	end

	if (self.feigning) then
		-- For coloured consistancy with other frames
		targethealth = 0
		targethealthmax = 1
	end

	local healthPct = targethealth / targethealthmax

	frameHealthBar:SetMinMaxValues(0, targethealthmax)
	if (XPerlConfig.InverseBars == 1) then
		frameHealthBar:SetValue(targethealthmax - targethealth)
	else
		frameHealthBar:SetValue(targethealth)
	end

	XPerl_SetSmoothBarColor(frameHealthBar, healthPct)
	if (targethealthmax == 100) then
		frameHealthBarPercent:SetText(targethealth.."%")
	else
		frameHealthBarPercent:SetText(string.format("%d",(100*healthPct)+0.5).."%")
	end
	if (targethealthmax ~= 100) then
		if (XPerlConfig["HealerMode"..self.optPrefix] == 1) then
			if (XPerlConfig["HealerMode"..self.optPrefix.."Type"] == 1) then
				frameHealthBarText:SetText(string.format("%d/%d", targethealth - targethealthmax, targethealthmax))
			else
				frameHealthBarText:SetText(targethealth - targethealthmax)
			end
		else
			frameHealthBarText:SetText(targethealth.."/"..targethealthmax)
		end
	else
		-- Hide MobInfo-2 frame
		if MobHealthFrame then
			MobHealthFrame:Hide()
		end

		local current, max
		if (MobHealth3) then
			local found
			current, max, found = MobHealth3:GetUnitHealth(partyid, targethealth, targethealthmax, UnitName(partyid), UnitLevel(partyid))

			if (not found) then
				current = nil
			end

		elseif (MobHealthDB) then
			local index
			if UnitIsPlayer(partyid) then
				index = UnitName(partyid)
			else
				index = UnitName(partyid)..":"..UnitLevel(partyid)
			end

			local table = MobHealthDB
			if (not (table and table[index])) then
				table = MobHealthPlayerDB
			end
			if (table and table[index]) then
				if ( type(table[index]) ~= "string" ) then
					frameHealthBarText:SetText(targethealth.."%")
				end
				local pts, pct = strmatch(table[index], "^(%d+)/(%d+)$")

				if ( pts and pct ) then
					pts = pts + 0
					pct = pct + 0
					if( pct ~= 0 ) then
						pointsPerPct = pts / pct
					else
						pointsPerPct = 0
					end
				end
				local currentPct = UnitHealth(partyid)
				if ( pointsPerPct > 0 ) then
					current = (currentPct * pointsPerPct) + 0.5
					max = (100 * pointsPerPct) + 0.5
				end
			end
		end

		if (current) then
			if (XPerlConfig["HealerMode"..self.optPrefix] == 1) then
				if (XPerlConfig["HealerMode"..self.optPrefix.."Type"] == 1) then
					if (max > 100000) then
						frameHealthBarText:SetText(string.format("%d%s/%d%s", (current - max) / XPERL_LOC_LARGENUMDIV, XPERL_LOC_LARGENUMTAG, max / XPERL_LOC_LARGENUMDIV, XPERL_LOC_LARGENUMTAG))
					else
						frameHealthBarText:SetText(string.format("%d/%d", current - max, max))
					end
				else
					if (max > 100000) then
						frameHealthBarText:SetText(string.format("%d%s", (current - max) / XPERL_LOC_LARGENUMDIV, XPERL_LOC_LARGENUMTAG))
					else
						frameHealthBarText:SetText(string.format("%d", current - max))
					end
				end
			else
				if (max > 100000) then
					frameHealthBarText:SetText(string.format("%.1f%s/%.1f%s", current / XPERL_LOC_LARGENUMDIV, XPERL_LOC_LARGENUMTAG, max / XPERL_LOC_LARGENUMDIV, XPERL_LOC_LARGENUMTAG))
				else
					frameHealthBarText:SetText(string.format("%d/%d", current, max))
				end
			end
		else
			frameHealthBarText:SetText(targethealth.."%")
		end
	end

	if (bPercent == 1) then
		if (UnitIsGhost(partyid)) then
			frameManaBarPercent:Hide()
			frameHealthBarPercent:SetText(XPERL_LOC_GHOST)
		elseif (self.feigning or UnitIsDead(partyid)) then
			frameManaBarPercent:Hide()
			frameHealthBarPercent:SetText(XPERL_LOC_DEAD)
			if (self.feigning or XPerl_IsFeignDeath(partyid)) then
				frameHealthBarText:SetText(XPERL_LOC_FEIGNDEATH)
			end

		elseif (UnitExists(partyid) and not UnitIsConnected(partyid)) then
			frameManaBarPercent:Hide()
			frameHealthBarPercent:SetText(XPERL_LOC_OFFLINE)
		end
	else
		if (UnitIsGhost(partyid)) then
			frameHealthBarText:SetText(XPERL_LOC_GHOST)
		elseif (self.feigning or UnitIsDead(partyid)) then
			if (self.feigning or XPerl_IsFeignDeath(partyid)) then
				frameHealthBarText:SetText(XPERL_LOC_FEIGNDEATH)
			else
				frameHealthBarText:SetText(XPERL_LOC_DEAD)
			end
		elseif (UnitExists(partyid) and not UnitIsConnected(partyid)) then
			frameHealthBarText:SetText(XPERL_LOC_OFFLINE)
		end
	end
end

-- XPerl_Target_Update_Combat
function XPerl_Target_Update_Combat(self)
	local act = getglobal(self:GetName().."_NameFrame_ActivityStatus")
	local partyid = self:GetAttribute("unit")
        if (UnitAffectingCombat(partyid)) then
                act:Show()
        else
                act:Hide()
        end
end

-- XPerl_Target_CombatFlash
local function XPerl_Target_CombatFlash(self, elapsed, argNew, argGreen)
	if (XPerl_CombatFlashSet (elapsed, self, argNew, argGreen)) then
		XPerl_CombatFlashSetFrames(self)
	end
end

-- XPerl_Target_Udpate_Range
function XPerl_Target_Udpate_Range(self)
	local rangeIcon = getglobal(self:GetName().."_NameFrame_RangeStatus")
	local partyid = self:GetAttribute("unit")
	if (XPerlConfig.Show30YardSymbol == 0 or CheckInteractDistance(partyid, 4) or not UnitIsConnected(partyid)) then
		rangeIcon:Hide()
	else
		rangeIcon:Show()
		rangeIcon:SetAlpha(1)
	end
end

-- XPerl_Target_UpdateLeader
local function XPerl_Target_UpdateLeader(self)
	local leader
	local partyid = self:GetAttribute("unit")
	if (UnitIsUnit(partyid, "player")) then
		leader = IsPartyLeader()

	elseif (UnitInRaid(partyid)) then
		local find = UnitName(partyid)
		for i = 1,GetNumRaidMembers() do
			local name, rank = GetRaidRosterInfo(i)
			if (name == find) then
				leader = (rank == 2)
				break
			end
		end

	elseif (UnitInParty(partyid)) then
		local index = GetPartyLeaderIndex()
		if (index > 0) then
			leader = UnitIsUnit(partyid, "party"..index)
		end
	end

	if (leader) then
		getglobal(self:GetName().."_NameFrame_LeaderIcon"):Show()
	else
		getglobal(self:GetName().."_NameFrame_LeaderIcon"):Hide()
	end

	-- We can't determine who is master looter in raid if not in current party... :(
	local ml
	local method, index = GetLootMethod()

	if (method == "master" and index) then
		if (index == 0 and UnitIsUnit("player", partyid)) then
			ml = true
		elseif (index >= 1 and index <= 4) then
			ml = UnitIsUnit(partyid, "party"..index)
		end
	end

	if (ml) then
		getglobal(self:GetName().."_NameFrame_MasterIcon"):Show()
	else
		getglobal(self:GetName().."_NameFrame_MasterIcon"):Hide()
	end
end

-- RaidTargetUpdate
local function RaidTargetUpdate(self)
	local partyid = self:GetAttribute("unit")
	XPerl_Update_RaidIcon(partyid, getglobal(self:GetName().."_NameFrame_RaidIcon"))

	local raidIcon = getglobal(self:GetName().."_NameFrame_RaidIcon")

	raidIcon:ClearAllPoints()
	if (XPerlConfig.AlternateRaidIcon == 1) then
		raidIcon:SetHeight(16)
		raidIcon:SetWidth(16)
		raidIcon:SetPoint("CENTER", getglobal(self:GetName().."_NameFrame"), "TOPRIGHT", -5, -4)
	else
		raidIcon:SetHeight(32)
		raidIcon:SetWidth(32)
		raidIcon:SetPoint("CENTER", getglobal(self:GetName().."_NameFrame"), "CENTER", 0, 0)
	end
end


-- XPerl_Target_UpdateDisplay
function XPerl_Target_UpdateDisplay(self)
	local partyid = self:GetAttribute("unit")
	if (UnitExists(partyid)) then
		XPerl_NoFadeBars(true)

		XPerl_Target_UpdateName(self)
		XPerl_Target_UpdateLevel(self)
		XPerl_Target_UpdateClassification(self)
		XPerl_Target_UpdateType(self)
		XPerl_Target_UpdatePVP(self)
		XPerl_Target_UpdateManaType(self)
		XPerl_Target_UpdateMana(self)
		XPerl_Target_UpdateHealth(self)

		XPerl_Target_UpdateLeader(self)
                XPerl_Target_Update_Combat(self)
		XPerl_Target_UpdateCombo(self)
		XPerl_Target_UpdatePortrait(self)
		RaidTargetUpdate(self)

		XPerl_NoFadeBars()

		-- Some optimizing here to limit the amount of work done on a target change
		local buffOptionString = tostring(XPerl_Target_StatsFrame_ManaBar:IsVisible() or 0)..tostring(XPerl_Target_BossFrame:IsVisible() or 0)..tostring(XPerl_Target_CreatureType:IsVisible() or 0)
		if (XPerl_Target.buffOptionString ~= buffOptionString) then
			XPerl_Target.buffOptionString = buffOptionString
			-- Work out where all our buffs can fit, we only do this for a fresh target
			XPerl_Targets_BuffPositions(self)
		end

		XPerl_Targets_BuffUpdate(self, self:GetName().."_")

		XPerl_Target_DebuffUpdate(self)

		if (not UnitIsConnected(partyid)) then
			self:SetAlpha(XPerlConfig.Transparency / 2)
		else
			self:SetAlpha(XPerlConfig.Transparency)
		end
	end
end

-- XPerl_Target_OnUpdate
function XPerl_Target_OnUpdate(self)
	CombatFeedback_OnUpdate(arg1)

	self.RangeUpdate = self.RangeUpdate - arg1
	if (self.RangeUpdate <= 0) then
		self.RangeUpdate = 0.5
		XPerl_Target_Udpate_Range(self)
	end
	if (self.PlayerFlash) then
		XPerl_Target_CombatFlash(self, arg1, false)
	end
end

-------------------
-- Event Handler --
-------------------
function XPerl_Target_OnEvent(self, event)
	local func = XPerl_Target_Events[event]
	if (func) then
		func(self)
	else
XPerl_ShowMessage("EXTRA EVENT")
	end
end

-- UNIT_COMBAT
function XPerl_Target_Events:UNIT_COMBAT()
	local partyid = self:GetAttribute("unit")
	if (arg1 == partyid) then
		XPerl_Target_Update_Combat(self)

		if (XPerlConfig.CombatHitIndicator == 1 and XPerlConfig["Show"..self.optPrefix.."Portrait"] == 1) then
			CombatFeedback_OnCombatEvent(arg2, arg3, arg4, arg5)
		end

		if (arg2 == "HEAL") then
			XPerl_Target_CombatFlash(self, 0, true, true)
		elseif (arg4 and arg4 > 0) then
			XPerl_Target_CombatFlash(self, 0, true)
		end
	end
end

-- UNIT_SPELLMISS
function XPerl_Target_Events:UNIT_SPELLMISS()
	if (XPerlConfig.CombatHitIndicator == 1 and XPerlConfig["Show"..self.optPrefix.."Portrait"] == 1) then
		CombatFeedback_OnSpellMissEvent(arg2)
	end
end

-- PLAYER_TARGET_CHANGED
function XPerl_Target_Events:PLAYER_TARGET_CHANGED()
	self.feigning = nil
	self.PlayerFlash = 0
	XPerl_CombatFlashSetFrames(self)
	XPerl_Target_UpdateDisplay(self)
	return
end

XPerl_Target_Events.PLAYER_FOCUS_CHANGED = XPerl_Target_Events.PLAYER_TARGET_CHANGED

-- UNIT_HEALTH, UNIT_MAXHEALTH
function XPerl_Target_Events:UNIT_HEALTH()
	XPerl_Target_UpdateHealth(self)
end
XPerl_Target_Events.UNIT_MAXHEALTH = XPerl_Target_Events.UNIT_HEALTH

-- UNIT_DYNAMIC_FLAGS
function XPerl_Target_Events:UNIT_DYNAMIC_FLAGS()
	XPerl_Target_UpdateName(self)
	XPerl_Target_UpdatePVP(self)
	XPerl_Target_Update_Combat(self)
end

XPerl_Target_Events.UNIT_FLAGS = XPerl_Target_Events.UNIT_DYNAMIC_FLAGS

-- RAID_TARGET_UPDATE
function XPerl_Target_Events:RAID_TARGET_UPDATE()
	RaidTargetUpdate(XPerl_Target)
	RaidTargetUpdate(XPerl_Focus)
end

-- UNIT_MANA, UNIT_MAXMANA, UNIT_RAGE, UNIT_MAXRAGE, UNIT_ENERGY
-- UNIT_MAXENERGY, UNIT_FOCUS, UNIT_MAXFOCUS
function XPerl_Target_Events:UNIT_MANA()
	XPerl_Target_UpdateMana(self)
end
XPerl_Target_Events.UNIT_MAXMANA	= XPerl_Target_Events.UNIT_MANA
XPerl_Target_Events.UNIT_RAGE		= XPerl_Target_Events.UNIT_MANA
XPerl_Target_Events.UNIT_MAXRAGE	= XPerl_Target_Events.UNIT_MANA
XPerl_Target_Events.UNIT_ENERGY		= XPerl_Target_Events.UNIT_MANA
XPerl_Target_Events.UNIT_MAXENERGY	= XPerl_Target_Events.UNIT_MANA
XPerl_Target_Events.UNIT_FOCUS		= XPerl_Target_Events.UNIT_MANA
XPerl_Target_Events.UNIT_MAXFOCUS	= XPerl_Target_Events.UNIT_MANA

-- UNIT_DISPLAYPOWER
function XPerl_Target_Events:UNIT_DISPLAYPOWER()
	XPerl_Target_UpdateManaType(self)
	XPerl_Target_UpdateMana(self)
end

-- UNIT_MODEL_CHANGED
function XPerl_Target_Events:UNIT_MODEL_CHANGED()
	XPerl_Target_UpdatePortrait(self)
end
--XPerl_Target_Events.UNIT_PORTRAIT_UPDATE = XPerl_Target_Events.UNIT_MODEL_CHANGED

-- UNIT_NAME_UPDATE
function XPerl_Target_Events:UNIT_NAME_UPDATE()
	XPerl_Target_UpdateName(self)
end

-- UNIT_LEVEL
function XPerl_Target_Events:UNIT_LEVEL()
	XPerl_Target_UpdateLevel(self)
end

-- UNIT_CLASSIFICATION_CHANGED
function XPerl_Target_Events:UNIT_CLASSIFICATION_CHANGED()
	XPerl_Target_UpdateClassification(self)
end

-- PLAYER_COMBO_POINTS
function XPerl_Target_Events:PLAYER_COMBO_POINTS()
	XPerl_Target_UpdateCombo(self)
end

-- UNIT_AURA
function XPerl_Target_Events:UNIT_AURA()
	local partyid = self:GetAttribute("unit")
	if (not self.perlBuffs or XPerl_UnitBuff(partyid, self.perlBuffs + 1, XPerlConfig[self.optPrefix.."CastableBuffs"])) then
		XPerl_Targets_BuffPositions(self)
	elseif (XPerl_UnitDebuff(partyid, self.perlDebuffs + 1, XPerlConfig[self.optPrefix.."CastableBuffs"])) then
		XPerl_Targets_BuffPositions(self)
	end

	XPerl_Targets_BuffUpdate(self, self:GetName().."_")
	XPerl_Target_DebuffUpdate(self)

	local _, class = UnitClass(partyid)
	if (class == "HUNTER") then
		local f = XPerl_IsFeignDeath(partyid)
		if (f ~= self.feigning) then
			self.feigning = f
			XPerl_Target_UpdateHealth(self)
		end
	end
end

-- UNIT_FACTION
function XPerl_Target_Events:UNIT_FACTION()
	XPerl_Target_UpdatePVP(self)
	XPerl_Targets_BuffPositions(self)
end

-- PLAYER_FLAGS_CHANGED
function XPerl_Target_Events:PLAYER_FLAGS_CHANGED()
	XPerl_Target_Update_Combat(self)
	XPerl_Target_UpdatePVP(self)
	XPerl_Target_UpdateHealth(self)

end

-- PARTY_MEMBER_ENABLE
function XPerl_Target_Events:PARTY_MEMBER_ENABLE()
	local partyid = self:GetAttribute("unit")
	if (UnitInParty(partyid) or UnitInRaid(partyid)) then
		XPerl_Target_Update_Combat(self)
		XPerl_Target_UpdatePVP(self)
		XPerl_Target_UpdateHealth(self)
	end
end

XPerl_Target_Events.PARTY_MEMBER_DISABLE = XPerl_Target_Events.PARTY_MEMBER_ENABLE

-- PARTY_LOOT_METHOD_CHANGED
function XPerl_Target_Events:PARTY_LOOT_METHOD_CHANGED()
	XPerl_Target_UpdateLeader(self)
end
XPerl_Target_Events.PARTY_MEMBERS_CHANGED = XPerl_Target_Events.PARTY_LOOT_METHOD_CHANGED
XPerl_Target_Events.PARTY_LEADER_CHANGED  = XPerl_Target_Events.PARTY_LOOT_METHOD_CHANGED

-- XPerl_Target_Set_Bits
function XPerl_Target_Set_Bits(self)

	self.buffOptionString = nil

	local portraitFrame = getglobal(self:GetName().."_PortraitFrame")
	local nameFrame = getglobal(self:GetName().."_NameFrame")
	local statsFrame = getglobal(self:GetName().."_StatsFrame")
	local statsFrameHPPerc = getglobal(self:GetName().."_StatsFrame_HealthBarPercent")
	local statsFrameMPPerc = getglobal(self:GetName().."_StatsFrame_ManaBarPercent")
	local levelFrame = getglobal(self:GetName().."_LevelFrame")
	local classTexFrame = getglobal(self:GetName().."_TypeFramePlayer_ClassTexture")
	local pvpRankIconFrame = getglobal(self:GetName().."_NameFrame_PVPRankIcon")

	if (XPerlConfig["Show"..self.optPrefix.."Portrait"] ==0) then
		portraitFrame:Hide()
		portraitFrame:SetWidth(2)
		self:SetWidth(160)
	else
		portraitFrame:Show()
		portraitFrame:SetWidth(60)
		self:SetWidth(220)

		XPerl_Target_UpdatePortrait(self)
	end

	if (XPerlConfig["Show"..self.optPrefix.."Percent"] ==0) then
		nameFrame:SetWidth(128)
		statsFrame:SetWidth(128)
		statsFrameHPPerc:Hide()
		statsFrameMPPerc:Hide()
	else
		nameFrame:SetWidth(160)
		statsFrame:SetWidth(160)
		statsFrameHPPerc:Show()
		statsFrameMPPerc:Show()
	end

	if (XPerlConfig["Show"..self.optPrefix.."Level"] ==0) then
		levelFrame:Hide()
	else
		levelFrame:Show()
	end

	if (XPerlConfig["Show"..self.optPrefix.."ClassIcon"] ==0) then
		classTexFrame:Hide()
	else
		classTexFrame:Show()
	end

	if (XPerlConfig["Show"..self.optPrefix.."PVPRank"] == 0) then
		pvpRankIconFrame:Hide()
	else
		pvpRankIconFrame:Show()
	end

	local cco = getglobal(self:GetName().."_CastClickOverlay")
	if (XPerlConfig["Show"..self.optPrefix.."Portrait"] == 1) then
		cco:SetPoint("BOTTOMRIGHT", portraitFrame, "BOTTOMRIGHT", 26, -1)
	else
		cco:SetPoint("BOTTOMRIGHT", statsFrame, "BOTTOMRIGHT", 26, -1)
	end

	XPerlConfig[self.optPrefix.."BuffSize"] = tonumber(XPerlConfig[self.optPrefix.."BuffSize"]) or 20
	XPerl_SetBuffSize(self:GetName().."_", XPerlConfig[self.optPrefix.."BuffSize"], XPerlConfig[self.optPrefix.."BuffSize"] * 1.2)
end

-- Using the Blizzard Combo Point frame, but we move the buttons around a little
function XPerl_Target_Set_BlizzCPFrame(self)
	ComboFrame:ClearAllPoints()
	ComboPoint1:ClearAllPoints()
	ComboPoint2:ClearAllPoints()
	ComboPoint3:ClearAllPoints()
	ComboPoint4:ClearAllPoints()
	ComboPoint5:ClearAllPoints()

	if (XPerlConfig.BlizzardCPMeter == 1) then
		-- This setup will put the buttons along the top of the portrait frame

		ComboFrame:SetScale(XPerlConfig["Scale_"..self.optPrefix.."Frame"])

		if (XPerlConfig.BlizzardCPPosition == "top") then
			ComboFrame:SetPoint("TOPLEFT", XPerl_Target_PortraitFrame, "TOPLEFT", -1, 4)
			ComboPoint1:SetPoint("TOPLEFT", 0, 0)
			ComboPoint2:SetPoint("LEFT", ComboPoint1, "RIGHT", 0, 1)
			ComboPoint3:SetPoint("LEFT", ComboPoint2, "RIGHT", 0, 1)
			ComboPoint4:SetPoint("LEFT", ComboPoint3, "RIGHT", 0, -1)
			ComboPoint5:SetPoint("LEFT", ComboPoint4, "RIGHT", 0, -4)

		elseif (XPerlConfig.BlizzardCPPosition == "bottom") then
			ComboFrame:SetPoint("BOTTOMLEFT", XPerl_Target_PortraitFrame, "BOTTOMLEFT", -1, -4)
			ComboPoint1:SetPoint("BOTTOMLEFT", 0, 0)
			ComboPoint2:SetPoint("LEFT", ComboPoint1, "RIGHT", 0, -1)
			ComboPoint3:SetPoint("LEFT", ComboPoint2, "RIGHT", 0, -1)
			ComboPoint4:SetPoint("LEFT", ComboPoint3, "RIGHT", 0, 1)
			ComboPoint5:SetPoint("LEFT", ComboPoint4, "RIGHT", 0, -1)

		elseif (XPerlConfig.BlizzardCPPosition == "left") then
			ComboFrame:SetPoint("BOTTOMLEFT", XPerl_Target_PortraitFrame, "BOTTOMLEFT", -1, 0)
			ComboPoint1:SetPoint("BOTTOMLEFT", 0, 0)
			ComboPoint2:SetPoint("BOTTOM", ComboPoint1, "TOP", -1, 0)
			ComboPoint3:SetPoint("BOTTOM", ComboPoint2, "TOP", -1, 0)
			ComboPoint4:SetPoint("BOTTOM", ComboPoint3, "TOP", 1, 0)
			ComboPoint5:SetPoint("BOTTOM", ComboPoint4, "TOP", 3, -5)

		elseif (XPerlConfig.BlizzardCPPosition == "right") then
			ComboFrame:SetPoint("BOTTOMRIGHT", XPerl_Target_PortraitFrame, "BOTTOMRIGHT", 2, 0)
			ComboPoint1:SetPoint("BOTTOMRIGHT", 0, 0)
			ComboPoint2:SetPoint("BOTTOM", ComboPoint1, "TOP", 1, 0)
			ComboPoint3:SetPoint("BOTTOM", ComboPoint2, "TOP", 1, 0)
			ComboPoint4:SetPoint("BOTTOM", ComboPoint3, "TOP", -1, 0)
			ComboPoint5:SetPoint("BOTTOM", ComboPoint4, "TOP", 0, -5)

		end

		ComboFrame:RegisterEvent("PLAYER_TARGET_CHANGED")
		ComboFrame:RegisterEvent("PLAYER_COMBO_POINTS")
	else
		ComboFrame:Hide()
		ComboFrame:UnregisterEvent("PLAYER_TARGET_CHANGED")
		ComboFrame:UnregisterEvent("PLAYER_COMBO_POINTS")
	end
end
