local XPerl_Target_Events = {}
local conf
XPerl_RequestConfig(function(new) conf = new end)

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

function XPerl_Target_OnLoad(self, partyid)
	XPerl_SetChildMembers(self)

	CombatFeedback_Initialize(self.hitIndicator.text, 30)
	self.hitIndicator.text:SetPoint("CENTER", self.portraitFrame, "CENTER", 0, 0)

	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

	self.partyid = partyid
	if (partyid == "target") then
		XPerl_Highlight:Register(XPerl_Target_HighlightCallback)

		XPerl_BlizzFrameDisable(TargetFrame)
		XPerl_BlizzFrameDisable(TargetofTargetFrame)

		self.optPrefix = "Target"
		self:RegisterEvent("PLAYER_TARGET_CHANGED")
		self:RegisterEvent("PLAYER_COMBO_POINTS")
	else
		self.optPrefix = "Focus"
		self:RegisterEvent("PLAYER_FOCUS_CHANGED")
	end

	self.nameFrame.cpMeter:SetMinMaxValues(0, 5)

	self.buffSetup = {
		debuffOnEnter = XPerl_Target_SetDeBuffTooltip,
		buffOnEnter = XPerl_Target_SetBuffTooltip,
		buffOnLeave = XPerl_PlayerTipHide,
		buffSizeOpt = self.optPrefix.."BuffSize",
		debuffSizeMod = 0.2,
		debuffAnchor1 = function(self, b) b:SetPoint("TOPLEFT", 0, 0) end,
	}
	self.buffSetup.buffAnchor1 = self.buffSetup.debuffAnchor1

	XPerl_SecureUnitButton_OnLoad(self.nameFrame, partyid, XPerl_ShowGenericMenu)
	XPerl_SecureUnitButton_OnLoad(self, partyid, XPerl_ShowGenericMenu)

	RegisterUnitWatch(self)

	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(self)
		XPerl_Target_AssistFrame:ClearAllPoints()
		XPerl_Target_AssistFrame:SetPoint("TOPLEFT", self.portraitFrame, "TOPRIGHT", -2, -20)
		XPerl_Target_AssistFrame:Raise()
	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(self.highlight, 3)
	XPerl_RegisterPerlFrames(self, {self.nameFrame, self.statsFrame, self.levelFrame, self.portraitFrame, self.typeFramePlayer, self.creatureTypeFrame, self.bossFrame, self.cpFrame})

	self.FlashFrames = {self.portraitFrame, self.nameFrame, self.levelFrame, self.statsFrame, self.bossFrame,
				self.typeFramePlayer, self.typeFrame}

	if (XPerl_ArcaneBar_RegisterFrame) then
		XPerl_ArcaneBar_RegisterFrame(self.nameFrame, partyid, "ArcaneBar"..self.optPrefix)
	end

	XPerl_RegisterOptionChanger(XPerl_Target_Set_Bits, self)
end

-- XPerl_Raid_HighlightCallback(updateName)
function XPerl_Target_HighlightCallback(updateName)
	if (XPerl_Target:IsShown() and UnitName("target") == updateName and UnitIsFriend("player", "target")) then
		XPerl_Highlight:SetHighlight(XPerl_Target, updateName)
	end
	if (XPerl_Focus:IsShown() and UnitName("focus") == updateName and UnitIsFriend("player", "focus")) then
		XPerl_Highlight:SetHighlight(XPerl_Focus, updateName)
	end
end

--------------------
-- Buff Functions --
--------------------

-- 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 = conf[self.optPrefix.."BuffsAbove"] == 1
	else
		above = conf.TargetTargetBuffsAbove == 1
	end

	local creatureTypeFrame = self.creatureTypeFrame
	if (above) then
		self.buffFrame:ClearAllPoints()
		self.buffFrame:SetPoint("BOTTOMLEFT", self.nameFrame, "TOPLEFT", 2, 0)
	else
		self.buffFrame:ClearAllPoints()
		self.buffFrame:SetPoint("TOPLEFT", self.statsFrame, "BOTTOMLEFT", 2, 0)
	end

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

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

	if (self.portraitFrame) then
		displayWidthExtra = displayWidthExtra + floor(self.portraitFrame:GetWidth() - 3.5)
	end

	if (unitTarget == "target" or unitTarget == "focus") then
		if (conf["Show"..self.optPrefix.."Level"] == 1 or conf["Show"..self.optPrefix.."ClassIcon"] == 1) then
			if (self.levelFrame) then
				displayWidthExtra = displayWidthExtra + floor(self.levelFrame: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, conf[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, conf[self.optPrefix.."CastableBuffs"])
		local buff = XPerl_GetBuffButton(self, i, 0, unitBuff and (buffRows <= conf[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, conf[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, conf[self.optPrefix.."CastableBuffs"])
		local buff = XPerl_GetBuffButton(self, i, 1, unitDebuff and (debuffRows <= conf[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)
	if (self == XPerl_Target or self == XPerl_Focus) then
		above = conf[self.optPrefix.."BuffsAbove"] == 1
	else
		above = conf.TargetTargetBuffsAbove == 1
	end

	local partyid = self.partyid
	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 > conf[self.optPrefix.."BuffRows"]) then
				hide = true
			else
				local name, rank, buff, count = XPerl_UnitBuff(partyid, buffnum, conf[self.optPrefix.."CastableBuffs"])

				if (buff) then
					local button = XPerl_GetBuffButton(self, buffnum, 0, true)

					self.perlBuffs = self.perlBuffs + 1

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

			if (hide) then
				local button = self.buffFrame.buff and self.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 > conf[self.optPrefix.."BuffRows"]) then
				hide = true
			else
				local name, rank, debuff, debuffApplications, debuffType = XPerl_UnitDebuff(partyid, buffnum, conf[self.optPrefix.."CurableDebuffs"])

				if (debuff) then
					local button = XPerl_GetBuffButton(self, buffnum, 1, true)

					self.perlDebuffs = self.perlDebuffs + 1

					button.icon:SetTexture(debuff)
					if ((debuffApplications or 0) > 1) then
						button.count:SetText(debuffApplications)
						button.count:Show()
					else
						button.count:Hide()
					end

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

					button:Show()
				else
					hide = true
				end
			end

			if (hide) then
				local button = self.buffFrame.debuff and self.buffFrame.debuff[buffnum]
				if (button) then
					button:Hide()
				end
			end
		end

		local buff1 = self.buffFrame.buff and self.buffFrame.buff[1]
		local debuff1 = self.buffFrame.debuff and self.buffFrame.debuff[1]
		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")

	XPerl_TooltipSetUnitBuff(GameTooltip, frame.partyid, self:GetID(), conf[frame.optPrefix.."CastableBuffs"])
	XPerl_ToolTip_AddBuffDuration(frame.partyid)
end

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

	GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")

	XPerl_TooltipSetUnitDebuff(GameTooltip, frame.partyid, self:GetID(), conf[frame.optPrefix.."CurableDebuffs"])
	XPerl_ToolTip_AddDebuffDuration(frame.partyid, nil, self:GetID(), conf[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 (conf.UseCPMeter == 1) then
			self.cpFrame:Hide()
			self.nameFrame.cpMeter:SetValue(combopoints)
			self.nameFrame.cpMeter:Show()
			if (r) then
				self.nameFrame.cpMeter:SetStatusBarColor(r, g, b, 0.7)
			else
				self.nameFrame.cpMeter:Hide()
			end
		elseif (conf.BlizzardCPMeter == 0) then
			self.nameFrame.cpMeter:Hide()
			self.cpFrame:Show()
			self.cpFrame.text:SetText(combopoints)
			if (r) then
				self.cpFrame.text:SetTextColor(r, g, b)
			else
				self.cpFrame:Hide()
			end
		end
	end
end

-- XPerl_UnitDebuffInformation
local function XPerl_UnitDebuffInformation(self, debuff)
	local i = 1
	local partyid = self.partyid
	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.partyid
	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 (conf.UseCPMeter == 1) then
				self.cpFrame:Hide()
				self.nameFrame.cpMeter:SetValue(numDebuffs)
				self.nameFrame.cpMeter:Show()
				if (r) then
					self.nameFrame.cpMeter:SetStatusBarColor(r, g, b, 0.4)
				else
					self.nameFrame.cpMeter:Hide()
				end
			else
				self.nameFrame.cpMeter:Hide()
				self.cpFrame:Show()
				self.cpFrame.text:SetText(numDebuffs)
				if (r) then
					self.cpFrame.text:SetTextColor(r, g, b)
				else
					self.cpFrame:Hide()
				end
			end
		else
			XPerl_Target_UpdateCombo(self)
		end
	end
end

-------------------------
-- The Update Functions--
-------------------------
local function XPerl_Target_UpdatePVP(self)
	local partyid = self.partyid
	local targetrankname, targetrank=GetPVPRankInfo(UnitPVPRank(partyid), partyid)

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

	if (conf[self.optPrefix.."ReactionHighlight"] == 1) then
		local c = XPerl_ReactionColour(partyid)
		self.nameFrame:SetBackdropColor(c.r, c.g, c.b)

		if (conf.ClassColouredNames == 1 and UnitPlayerControlled(partyid)) then
			XPerl_SetUnitNameColor(partyid, self.nameFrame.text)
		else
			self.nameFrame.text:SetTextColor(1, 1, 1, conf.TextTransparency)
		end
	else
		XPerl_SetUnitNameColor(partyid, self.nameFrame.text)
	end

        if (UnitIsVisible(partyid) and UnitIsCharmed(partyid)) then
		self.nameFrame.warningIcon:Show()
	else
		self.nameFrame.warningIcon:Hide()
	end
end

-- XPerl_Target_UpdateName
local function XPerl_Target_UpdateName(self)
	local targetname = UnitName(self.partyid)
	self.nameFrame.text:SetText(targetname)
	XPerl_Target_UpdatePVP(self)
end

-- XPerl_Target_UpdatePortrait
function XPerl_Target_UpdatePortrait(self)
	if (conf["Show"..self.optPrefix.."Portrait"] == 1) then
		if (UnitExists(self.partyid)) then
			if (UnitIsVisible(self.partyid) and conf["Show"..self.optPrefix.."Portrait3D"] == 1) then
				self.portraitFrame.portrait:Hide()
				self.portraitFrame.portrait3D:Show()
				XPerlSetPortrait3D(self.portraitFrame.portrait3D, self.partyid)
			else
				self.portraitFrame.portrait:Show()
				self.portraitFrame.portrait3D:Hide()
				SetPortraitTexture(self.portraitFrame.portrait, self.partyid)
			end
		end
	end
end

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

-- XPerl_Target_UpdateClassification
local function XPerl_Target_UpdateClassification(self)
	local partyid = self.partyid
	local targetclassification = UnitClassification(partyid)
	local bossType, eliteGfx

	if (UnitIsCivilian(partyid)) then
		bossType = XPERL_TYPE_CIVILIAN
                self.bossFrame.text:SetTextColor(1, 0, 0)

	elseif (targetclassification == "normal" and UnitPlayerControlled(partyid)) then
		if (not UnitIsPlayer(partyid)) then
			bossType = XPERL_TYPE_PET
	                self.bossFrame.text:SetTextColor(1, 1, 1)
		end

	elseif ((conf["Show"..self.optPrefix.."Level"] == 1 and conf["Show"..self.optPrefix.."Elite"] > 0) or targetclassification=="Rare+" or targetclassification=="Rare") then
		if (conf["Show"..self.optPrefix.."Elite"] == 1) then
			if (targetclassification == "worldboss") then
				bossType = XPERL_TYPE_BOSS
	        	        self.bossFrame.text:SetTextColor(1, 0.5, 0.5)

			elseif (targetclassification == "rareelite") then
				bossType = XPERL_TYPE_RAREPLUS
	        	        self.bossFrame.text:SetTextColor(0.8, 0.8, 0.8)

			elseif (targetclassification == "elite") then
				bossType = XPERL_TYPE_ELITE
	        	        self.bossFrame.text:SetTextColor(1, 1, 0.5)

			elseif (targetclassification == "rare") then
				bossType = XPERL_TYPE_RARE
	        	        self.bossFrame.text:SetTextColor(0.8, 0.8, 0.8)
			end
		else
			eliteGfx = true
			if (targetclassification == "worldboss" or targetclassification == "elite") then
				self.eliteFrame.tex:SetVertexColor(1, 1, 0, 1)

			elseif (targetclassification == "rareelite") then
				self.eliteFrame.tex:SetVertexColor(1, 1, 0.5, 1)

			elseif (targetclassification == "rare") then
				self.eliteFrame.tex:SetVertexColor(1, 1, 1, 1)
			else
				eliteGfx = nil
			end
		end
	end

	if (bossType) then
		self.bossFrame:Show()
		self.bossFrame.text:SetText(bossType)
		self.bossFrame:SetWidth(self.bossFrame.text:GetStringWidth() + 10)
	else
		self.bossFrame:Hide()
	end

	if (eliteGfx) then
		self.eliteFrame:Show()
	else
		self.eliteFrame:Hide()
	end
end

-- XPerl_Target_UpdateType
local function XPerl_Target_UpdateType(self)
	local partyid = self.partyid
	local targettype = UnitCreatureType(partyid)

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

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

	self.typeFramePlayer:Hide()
	self.creatureTypeFrame.text:SetText(targettype)

	if (UnitIsPlayer(partyid)) then
		local LocalClass, PlayerClass = UnitClass(partyid)
		if (conf["Show"..self.optPrefix.."ClassIcon"] ==1) then
			if (conf["Show"..self.optPrefix.."ClassText"] ==1) then
				self.bossFrame.text:SetText(LocalClass)
				self.bossFrame.text:SetTextColor(1, 1, 1)
				self.bossFrame:Show()
				self.bossFrame:SetWidth(self.bossFrame.text:GetStringWidth() + 10)
			else
				local r, l, t, b = XPerl_ClassPos(PlayerClass)
				self.typeFramePlayer.classTexture:SetTexCoord(r, l, t, b)
				self.typeFramePlayer:Show()
			end
		end
		self.creatureTypeFrame:Hide()
	else
		if (targettype and targettype ~= "") then
			self.creatureTypeFrame.text:SetTextColor(1, 1, 1)
			self.creatureTypeFrame:SetWidth(self.creatureTypeFrame.text:GetStringWidth() + 10)
		else
			self.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
	self.creatureTypeFrame:ClearAllPoints()
	if (self.creatureTypeFrame:GetWidth() > self.portraitFrame:GetWidth()) then
		self.creatureTypeFrame:SetPoint("TOPLEFT", self.portraitFrame, "BOTTOMLEFT", 0, 2)
	else
		self.creatureTypeFrame:SetPoint("TOPRIGHT", self.portraitFrame, "BOTTOMRIGHT", 0, 2)
	end
end

-- XPerl_Target_SetManaType
function XPerl_Target_SetManaType(self)
	local partyid = self.partyid
	local targetmanamax = UnitManaMax(partyid)

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

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

	XPerl_SetManaBarType(self)

	local targetmana = UnitMana(partyid)

	if (not self.statsFrame.manaBar:IsShown()) then
		self.statsFrame.manaBar.text:Show()
		self.statsFrame.manaBar:Show()
		if (self == XPerl_Target or self == XPerl_Focus) then
			self.statsFrame: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 targetmana = UnitMana(self.partyid)
	local targetmanamax = UnitManaMax(self.partyid)
	if (self.statsFrame.healthBar.percent:IsVisible()) then
		self.statsFrame.manaBar.percent:Show()
	end

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

	self.statsFrame.manaBar:SetMinMaxValues(0, targetmanamax)
	self.statsFrame.manaBar:SetValue(targetmana)

	self.statsFrame.manaBar.percent:SetText(format("%d",(100*(targetmana / targetmanamax))+0.5).."%")
	self.statsFrame.manaBar.text:SetText(targetmana.."/"..targetmanamax)
end

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

	if (conf["Show"..self.optPrefix.."Values"] == 1) then
		self.statsFrame.healthBar.text:Show()
		self.statsFrame.manaBar.text:Show()
	else
		self.statsFrame.healthBar.text:Hide()
		self.statsFrame.manaBar.text:Hide()
	end

	if (not UnitIsConnected(self.partyid)) then
		self.statsFrame.healthBar.text:SetText(XPERL_LOC_OFFLINE)
	end
end

-- XPerl_Target_SetHealth
function XPerl_Target_SetHealth(self, bPercent)
	local partyid = self.partyid

	local targethealth, targethealthmax = UnitHealth(partyid), UnitHealthMax(partyid)
	if (targethealth > targethealthmax) then
		-- 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

	self.statsFrame.healthBar:SetMinMaxValues(0, targethealthmax)
	if (conf.InverseBars == 1) then
		self.statsFrame.healthBar:SetValue(targethealthmax - targethealth)
	else
		self.statsFrame.healthBar:SetValue(targethealth)
	end

	if (targethealthmax == 100) then
		self.statsFrame.healthBar.percent:SetText(targethealth.."%")
	else
		self.statsFrame.healthBar.percent:SetText(format("%d",(100*healthPct)+0.5).."%")
	end
	if (targethealthmax ~= 100) then
		if (conf["HealerMode"..self.optPrefix] == 1) then
			if (conf["HealerMode"..self.optPrefix.."Type"] == 1 and UnitIsFriend(partyid, "player")) then
				self.statsFrame.healthBar.text:SetText(format("%d/%d", targethealth - targethealthmax, targethealthmax))
			else
				self.statsFrame.healthBar.text:SetText(targethealth - targethealthmax)
			end
		else
			self.statsFrame.healthBar.text: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
					self.statsFrame.healthBar.text: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 (conf["HealerMode"..self.optPrefix] == 1 and UnitIsFriend(partyid, "player")) then
				if (conf["HealerMode"..self.optPrefix.."Type"] == 1) then
					if (max > 100000) then
						self.statsFrame.healthBar.text:SetText(format("%d%s/%d%s", (current - max) / XPERL_LOC_LARGENUMDIV, XPERL_LOC_LARGENUMTAG, max / XPERL_LOC_LARGENUMDIV, XPERL_LOC_LARGENUMTAG))
					else
						self.statsFrame.healthBar.text:SetText(format("%d/%d", current - max, max))
					end
				else
					if (max > 100000) then
						self.statsFrame.healthBar.text:SetText(format("%d%s", (current - max) / XPERL_LOC_LARGENUMDIV, XPERL_LOC_LARGENUMTAG))
					else
						self.statsFrame.healthBar.text:SetText(format("%d", current - max))
					end
				end
			else
				if (max > 100000) then
					self.statsFrame.healthBar.text:SetText(format("%.1f%s/%.1f%s", current / XPERL_LOC_LARGENUMDIV, XPERL_LOC_LARGENUMTAG, max / XPERL_LOC_LARGENUMDIV, XPERL_LOC_LARGENUMTAG))
				else
					self.statsFrame.healthBar.text:SetText(format("%d/%d", current, max))
				end
			end
		else
			self.statsFrame.healthBar.text:SetText(targethealth.."%")
		end
	end

	local color
	if (bPercent == 1) then
		if (UnitIsGhost(partyid)) then
			self.statsFrame.manaBar.percent:Hide()
			self.statsFrame.healthBar.percent:SetText(XPERL_LOC_GHOST)

		elseif (self.feigning or UnitIsDead(partyid)) then
			self.statsFrame.manaBar.percent:Hide()
			self.statsFrame.healthBar.percent:SetText(XPERL_LOC_DEAD)
			if (self.feigning or XPerl_IsFeignDeath(partyid)) then
				self.statsFrame.healthBar.text:SetText(XPERL_LOC_FEIGNDEATH)
			end

		elseif (UnitExists(partyid) and not UnitIsConnected(partyid)) then
			self.statsFrame.manaBar.percent:Hide()
			self.statsFrame.healthBar.percent:SetText(XPERL_LOC_OFFLINE)

		elseif (UnitIsAFK(partyid) and (self == XPerl_Target or self == XPerl_Focus)) then
			self.statsFrame.healthBar.percent:SetText(CHAT_MSG_AFK)

		else
			color = true
		end
	else
		if (UnitIsGhost(partyid)) then
			self.statsFrame.healthBar.text:SetText(XPERL_LOC_GHOST)

		elseif (self.feigning or UnitIsDead(partyid)) then
			if (self.feigning or XPerl_IsFeignDeath(partyid)) then
				self.statsFrame.healthBar.text:SetText(XPERL_LOC_FEIGNDEATH)
			else
				self.statsFrame.healthBar.text:SetText(XPERL_LOC_DEAD)
			end

		elseif (UnitExists(partyid) and not UnitIsConnected(partyid)) then
			self.statsFrame.healthBar.text:SetText(XPERL_LOC_OFFLINE)

		elseif (UnitIsAFK(partyid)) then	-- and (self == XPerl_Target or self == XPerl_Focus)) then
			self.statsFrame.healthBar.text:SetText(CHAT_MSG_AFK)

		else
			color = true
		end
	end

	if (color) then
		XPerl_SetSmoothBarColor(self.statsFrame.healthBar, healthPct)

		if (self.statsFrame.greyMana) then
			self.statsFrame.greyMana = nil
			XPerl_Target_SetManaType(self)
		end
	else
		self.statsFrame:SetGrey()
	end
end

-- XPerl_Target_Update_Combat
function XPerl_Target_Update_Combat(self)
        if (UnitAffectingCombat(self.partyid)) then
                self.nameFrame.combatIcon:Show()
        else
                self.nameFrame.combatIcon: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_Update_Range
function XPerl_Target_Update_Range(self)
	if (conf.Show30YardSymbol == 0 or CheckInteractDistance(self.partyid, 4) or not UnitIsConnected(self.partyid)) then
		self.nameFrame.rangeIcon:Hide()
	else
		self.nameFrame.rangeIcon:Show()
		self.nameFrame.rangeIcon:SetAlpha(1)
	end
end

-- XPerl_Target_UpdateLeader
local function XPerl_Target_UpdateLeader(self)
	local leader
	local partyid = self.partyid
	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
		self.nameFrame.leaderIcon:Show()
	else
		self.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
		self.nameFrame.masterIcon:Show()
	else
		self.nameFrame.masterIcon:Hide()
	end
end

-- RaidTargetUpdate
local function RaidTargetUpdate(self)
	local raidIcon = self.nameFrame.raidIcon

	XPerl_Update_RaidIcon(raidIcon, self.partyid)

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


-- XPerl_Target_UpdateDisplay
function XPerl_Target_UpdateDisplay(self)
	if (UnitExists(self.partyid)) then
		XPerl_NoFadeBars(true)

		XPerl_Target_UpdateName(self)
		XPerl_Target_UpdateLevel(self)
		XPerl_Target_UpdateClassification(self)
		XPerl_Target_UpdateType(self)
		XPerl_Target_SetManaType(self)
		XPerl_Target_UpdateMana(self)
		XPerl_Target_UpdateHealth(self)

		if (conf.TargetChangeDefer == 1) then
			self.nameFrame.combatIcon:Hide()
			self.portraitFrame.portrait:Hide()
			self.portraitFrame.portrait3D:Hide()
			self.nameFrame.leaderIcon:Hide()
			self.nameFrame.masterIcon:Hide()
			self.cpFrame:Hide()
			self.nameFrame.cpMeter:Hide()
			self.nameFrame.raidIcon:Hide()
			self.deferring = true
			self.RangeUpdate = 0.5
		else
			XPerl_Target_UpdateLeader(self)
                	XPerl_Target_Update_Combat(self)
			XPerl_Target_UpdateCombo(self)
			XPerl_Target_UpdatePortrait(self)
			RaidTargetUpdate(self)
		end

		XPerl_Highlight:SetHighlight(self, UnitName(self.partyid))
		XPerl_UpdateSpellRange(self, self.partyid)

		XPerl_NoFadeBars()

		-- Some optimizing here to limit the amount of work done on a target change
		local buffOptionString = tostring(self.statsFrame.manaBar:IsVisible() or 0)..tostring(self.bossFrame:IsVisible() or 0)..tostring(self.creatureTypeFrame: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)
		XPerl_Target_DebuffUpdate(self)

		if (conf.TargetDebuffHighlight == 1) then
			if (XPerlConfig.TargetDebuffHighlightWho == 1 or
				(XPerlConfig.TargetDebuffHighlightWho == 2 and UnitIsFriend(self.partyid, "player")) or
				(XPerlConfig.TargetDebuffHighlightWho == 3 and UnitIsEnemy(self.partyid, "player"))) then

				XPerl_CheckDebuffs(self, self.partyid)
			end
		end

		XPerl_Target_UpdatePVP(self)

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

-- XPerl_Target_OnUpdate
function XPerl_Target_OnUpdate(self, elapsed)
	CombatFeedback_OnUpdate(elapsed)

	self.RangeUpdate = self.RangeUpdate - elapsed
	if (self.RangeUpdate <= 0) then
		self.RangeUpdate = 0.2
		XPerl_Target_Update_Range(self)
		XPerl_UpdateSpellRange(self)

		if (self.deferring) then
			self.deferring = nil
			XPerl_Target_UpdateLeader(self)
                	XPerl_Target_Update_Combat(self)
			XPerl_Target_UpdateCombo(self)
			XPerl_Target_UpdatePortrait(self)
			RaidTargetUpdate(self)
		end
	end
	if (self.PlayerFlash) then
		XPerl_Target_CombatFlash(self, elapsed, 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()
	if (arg1 == self.partyid) then
		XPerl_Target_Update_Combat(self)

		if (conf[self.optPrefix.."CombatHitIndicator"] == 1 and conf["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 (conf[self.optPrefix.."CombatHitIndicator"] == 1 and conf["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_SetManaType(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()
	if (conf.TargetDebuffHighlight == 1) then
		XPerl_CheckDebuffs(self, self.partyid)
		if (conf[self.optPrefix.."ReactionHighlight"] == 1) then
			XPerl_Target_UpdatePVP(self)
		end
	end

	if (not self.perlBuffs or XPerl_UnitBuff(self.partyid, self.perlBuffs + 1, conf[self.optPrefix.."CastableBuffs"])) then
		XPerl_Targets_BuffPositions(self)
	elseif (XPerl_UnitDebuff(self.partyid, self.perlDebuffs + 1, conf[self.optPrefix.."CastableBuffs"])) then
		XPerl_Targets_BuffPositions(self)
	end

	XPerl_Targets_BuffUpdate(self)
	XPerl_Target_DebuffUpdate(self)

	local _, class = UnitClass(self.partyid)
	if (class == "HUNTER") then
		local f = XPerl_IsFeignDeath(self.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()
	if (UnitInParty(self.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

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

		XPerl_Target_UpdatePortrait(self)
	end

	if (conf["Show"..self.optPrefix.."Percent"] ==0) then
		self.nameFrame:SetWidth(128)
		self.statsFrame:SetWidth(128)
		self.statsFrame.healthBar.percent:Hide()
		self.statsFrame.manaBar.percent:Hide()
	else
		self.nameFrame:SetWidth(160)
		self.statsFrame:SetWidth(160)
		self.statsFrame.healthBar.percent:Show()
		self.statsFrame.manaBar.percent:Show()
	end

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

	if (conf["Show"..self.optPrefix.."ClassIcon"] ==0) then
		self.typeFramePlayer.classTexture:Hide()
	else
		self.typeFramePlayer.classTexture:Show()
	end

	if (conf["Show"..self.optPrefix.."PVPRank"] == 0) then
		self.nameFrame.pvpRankIcon:Hide()
	else
		self.nameFrame.pvpRankIcon:Show()
	end

	if (conf["Show"..self.optPrefix.."Portrait"] == 1) then
		self.highlight:SetPoint("BOTTOMRIGHT", self.portraitFrame, "BOTTOMRIGHT", 26, -1)
	else
		self.highlight:SetPoint("BOTTOMRIGHT", self.statsFrame, "BOTTOMRIGHT", 26, -1)
	end

	conf[self.optPrefix.."BuffSize"] = tonumber(conf[self.optPrefix.."BuffSize"]) or 20
	XPerl_SetBuffSize(self)

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

	if (self == XPerl_Target) then
		XPerl_Target_Set_BlizzCPFrame(self)
	end

	XPerl_StatsFrameSetup(self)

	if (self:IsShown()) then
		XPerl_Target_UpdateDisplay(self)
	end
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 (conf.BlizzardCPMeter == 1) then
		-- This setup will put the buttons along the top of the portrait frame

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

		if (conf.BlizzardCPPosition == "top") then
			ComboFrame:SetPoint("TOPLEFT", self.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 (conf.BlizzardCPPosition == "bottom") then
			ComboFrame:SetPoint("BOTTOMLEFT", self.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 (conf.BlizzardCPPosition == "left") then
			ComboFrame:SetPoint("BOTTOMLEFT", self.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 (conf.BlizzardCPPosition == "right") then
			ComboFrame:SetPoint("BOTTOMRIGHT", self.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

-- XPerl_Update_RaidIcon
function XPerl_Update_RaidIcon(self, unit)
	local index = GetRaidTargetIndex(unit)
	if (index) then
		SetRaidTargetIconTexture(self, index)
		self:Show()
	else
		self:Hide()
	end
end
