local conf
XPerl_RequestConfig(function(new) conf = new end)

-- XPerl_TargetTarget_OnLoad
function XPerl_TargetTarget_OnLoad(self)
	XPerl_SetChildMembers(self)
	self.optPrefix = "Target"

	-- Events
	self:RegisterEvent("RAID_TARGET_UPDATE")
	if (self == XPerl_TargetTarget) then
		self.partyid = "targettarget"
		self:RegisterEvent("UNIT_TARGET")
		self:SetScript("OnUpdate", XPerl_TargetTarget_OnUpdate)
	else
		self.partyid = "targettargettarget"
		self:SetScript("OnUpdate", XPerl_TargetTargetTarget_OnUpdate)
	end

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

	RegisterUnitWatch(self)

	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

	self.time = 0
	self.targetname = ""
	self.targethp = 0
	self.targetmana = 0
	self.lastUpdate = 0

	--XPerl_InitFadeFrame(self)
	XPerl_RegisterHighlight(self.highlight, 2)
	XPerl_RegisterPerlFrames(self, {self.nameFrame, self.statsFrame, self.levelFrame})

	if (self == XPerl_TargetTarget) then
		XPerl_Highlight:Register(XPerl_TargetTarget_HighlightCallback)

		XPerl_RegisterOptionChanger(XPerl_TargetTarget_Set_Bits, "TargetTarget")
	end
end

-- XPerl_TargetTarget_HighlightCallback(updateName)
function XPerl_TargetTarget_HighlightCallback(updateName)
	if (XPerl_TargetTarget:IsShown() and UnitName("targettarget") == updateName and UnitIsFriend("player", "targettarget")) then
		XPerl_Highlight:SetHighlight(XPerl_TargetTarget, updateName)
	end
	if (XPerl_TargetTargetTarget and XPerl_TargetTargetTarget:IsShown() and UnitName("targettargettarget") == updateName and UnitIsFriend("player", "targettargettarget")) then
		XPerl_Highlight:SetHighlight(XPerl_TargetTargetTarget, updateName)
	end
end

-------------------------
-- The Update Function --
-------------------------
function XPerl_TargetTarget_UpdatePVP(self)
        local targetrankname, targetrank=GetPVPRankInfo(UnitPVPRank(self.partyid), self.partyid)
        if (targetrank and conf.ShowTargetPVPRank==1 and UnitIsPlayer(self.partyid)) then
		if (targetrank==0) then
                	self.nameFrame.pvpRankIcon:Hide()
		else
                	self.nameFrame.pvpRankIcon:Show()
			self.nameFrame.pvpRankIcon:SetTexture(format("Interface\\PVPRankBadges\\PVPRank%02d", targetrank))
		end
	else
                self.nameFrame.pvpRankIcon:Hide()
	end
        if (conf.ShowTargetPVP == 1 and UnitIsPVP(self.partyid)) then
		self.nameFrame.pvpIcon:SetTexture("Interface\\TargetingFrame\\UI-PVP-"..(UnitFactionGroup(self.partyid) or "FFA"))
                self.nameFrame.pvpIcon:Show()
	else
                self.nameFrame.pvpIcon:Hide()
	end
end

-- XPerl_TargetTarget_Buff_UpdateAll
local function XPerl_TargetTarget_Buff_UpdateAll(self)
	local show
	if (self == XPerl_TargetTarget) then
		show = conf.TargetTargetBuffs
	else
		show = conf.TargetTargetTargetBuffs
	end

	if (show == 1) then
		self.buffFrame:Show()
		XPerl_Targets_BuffUpdate(self)
	else
		self.buffFrame:Hide()
	end
end

-- XPerl_TargetTarget_RaidIconUpdate
local function XPerl_TargetTarget_RaidIconUpdate(unitid, frameRaidIcon, frameNameFrame)
	XPerl_Update_RaidIcon(frameRaidIcon, unitid)

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

-- XPerl_TargetTarget_UpdateDisplay
function XPerl_TargetTarget_UpdateDisplay(self,force)

	local show
	if (self == XPerl_TargetTarget) then
		show = conf.ShowTargetTarget
	else
		show = conf.ShowTargetTargetTarget
		if (show == 1 and conf.ShowTargetTarget == 0) then
			show = 0
		end
	end

	local partyid = self.partyid
	if (UnitExists("target") and show == 1 and UnitIsConnected(partyid)) then		-- (UnitName("target")~=nil) and (show==1) and (UnitIsConnected(self.unitid))) then
		self.targetname = UnitName(partyid)
		if (self.targetname ~= nil) then
			local t = GetTime()
			if (not force and t < self.lastUpdate + 0.3) then
				return
			end
			self.lastUpdate = t

	                XPerl_TargetTarget_UpdatePVP(self)

			-- Save these 2, so we know whether to update the frame later
			self.targethp = UnitHealth(partyid)
			self.targetmana = UnitMana(partyid)
			self.afk = UnitIsAFK(partyid)

                        XPerl_SetUnitNameColor(partyid, self.nameFrame.text)

                        if (conf.ShowTargetTargetLevel == 1) then
				local TargetTargetlevel = UnitLevel(partyid)
	                        local color = GetDifficultyColor(TargetTargetlevel)

				if (TargetTargetLevel == -1) then
					if (UnitClassification(partyid) == "worldboss") then
						TargetTargetLevel = "Boss"
					end
				elseif (UnitIsPlusMob(partyid) or UnitClassification(partyid) == "elite") then
                                        TargetTargetlevel = TargetTargetlevel.."+"
                                        self.levelFrame:SetWidth(33)
                                else
                                        self.levelFrame:SetWidth(27)
                                end

				self.levelFrame.text:SetText(TargetTargetlevel)

				if (TargetTargetLevel == "Boss") then
                                        self.levelFrame:SetWidth(self.levelFrame.text:GetStringWidth() + 6)
					color = {r = 1, g = 0, b = 0}
				end

        	                self.levelFrame.text:SetTextColor(color.r, color.g, color.b)
                        end

			-- Set name - Must do after level as the NameFrame can change size just above here.
			local TargetTargetname = self.targetname
			self.nameFrame.text:SetText(TargetTargetname)

			-- Set health
			XPerl_Target_SetHealth(self, conf.ShowTargetTargetPercent)

			-- Set mana
			if (not self.statsFrame.greyMana) then
				XPerl_Target_SetManaType(self)
			end
			XPerl_Target_SetMana(self)

			if (conf.ShowTargetTargetValues == 1) then
				self.statsFrame.healthBar.text:Show()
				self.statsFrame.manaBar.text:Show()
			else
				self.statsFrame.healthBar.text:Hide()
				self.statsFrame.manaBar.text:Hide()
			end

			XPerl_TargetTarget_RaidIconUpdate(partyid, self.nameFrame.raidIcon, self.nameFrame)

			XPerl_Targets_BuffPositions(self)
			XPerl_TargetTarget_Buff_UpdateAll(self)

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

			return
		else
			self.targetname = ""
		end
	else
		self.targetname = ""
	end
end

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

-- XPerl_TargetTarget_Update_Combat
local function XPerl_TargetTarget_Update_Combat(self)
        if (UnitAffectingCombat(self.partyid)) then
		self.nameFrame.combatIcon:Show()
        else
		self.nameFrame.combatIcon:Hide()
        end
end

-- XPerl_TargetTarget_OnUpdate
function XPerl_TargetTarget_OnUpdate(self, elapsed)

	local partyid = self.partyid
	local newHP = UnitHealth(partyid)
	local newMana = UnitMana(partyid)
	local newAFK = UnitIsAFK(partyid)

	if ((newHP ~= self.targethp) or (newMana ~= self.targetmana) or (newAFK ~= self.afk)) then
		XPerl_TargetTarget_UpdateDisplay(self)
	else
		self.time = elapsed + self.time
        	if (self.time >= 0.2) then
		        XPerl_TargetTarget_Update_Combat(self)
			XPerl_TargetTarget_Update_Control(self)
		        XPerl_TargetTarget_UpdatePVP(self)
			XPerl_TargetTarget_Buff_UpdateAll(self)
			XPerl_SetUnitNameColor(partyid, self.nameFrame.text)
			XPerl_UpdateSpellRange(self, partyid)

			self.time = 0
		end
	end
end

-- XPerl_TargetTargetTarget_OnUpdate
function XPerl_TargetTargetTarget_OnUpdate(self, elapsed)

	local partyid = self.partyid
	local newName = UnitName(partyid)
	local newHP = UnitHealth(partyid)
	local newMana = UnitMana(partyid)

	if (not newName) then
		newName = ""
		newHP = 0
		newMana = 0
	end

	if (self == XPerl_TargetTargetTarget and newName ~= self.targetname) then
		XPerl_NoFadeBars(true)
		XPerl_TargetTarget_UpdateDisplay(self,true)
		XPerl_NoFadeBars()

	elseif ((newHP ~= self.targethp) or (newMana ~= self.targetmana)) then
		XPerl_TargetTarget_UpdateDisplay(self)

	else
		self.time = elapsed + self.time
        	if (self.time >= 0.2) then
		        XPerl_TargetTarget_Update_Combat(self)
			XPerl_TargetTarget_Update_Control(self)
		        XPerl_TargetTarget_UpdatePVP(self)
			XPerl_TargetTarget_Buff_UpdateAll(self)
			XPerl_SetUnitNameColor(partyid, self.nameFrame.text)
			XPerl_UpdateSpellRange(self, partyid)

			self.time = 0
		end
	end
end

-------------------
-- Event Handler --
-------------------
function XPerl_TargetTarget_OnEvent(self, event)

	if (event == "RAID_TARGET_UPDATE") then
		XPerl_TargetTarget_RaidIconUpdate(self:GetAttribute("unit"), self.nameFrame.raidIcon, self.nameFrame)

	elseif (event == "UNIT_TARGET") then
		if (arg1 == "target") then
			XPerl_NoFadeBars(true)
			XPerl_TargetTarget_UpdateDisplay(this,true)
			XPerl_NoFadeBars()
		end
	end
end

--------------------
-- Target history --
--------------------

-- XPerl_TargetTarget_Update
function XPerl_TargetTarget_Update()

	local alpha = conf.Transparency
	local time = GetTime()

	local offset = -3
	if (conf.TargetTargetBuffs == 1) then
		if (UnitExists("targettarget")) then
			if (XPerl_UnitBuff("targettarget", 1)) then
				if (offset == -3) then
					offset = 0
				end
				offset = offset + 20
				if (UnitBuff("targettarget", 9)) then
					offset = offset + 20
				end
			end
			if (XPerl_UnitDebuff("targettarget", 1)) then
				if (offset == -3) then
					offset = 0
				end
				offset = offset + 24
			end
		end
	end
end

-- EnableDisable
local function EnableDisable(self)

	local opt
	if (self == XPerl_TargetTarget) then
		opt = conf.ShowTargetTarget
	else
		opt = conf.ShowTargetTargetTarget
	end

	if (opt == 1) then
		RegisterUnitWatch(self)
	else
		UnregisterUnitWatch(self)
		self:Hide()
	end
end

-- XPerl_TargetTarget_Set_Bits
function XPerl_TargetTarget_Set_Bits()
	if (not XPerl_TargetTarget) then
		return
	end

	local function Set(self)
		if (conf.ShowTargetTargetLevel==0) then
			self.levelFrame:Hide()
		else
			self.levelFrame:Show()
			self.levelFrame:SetWidth(27)
		end

		if (conf.ShowTargetTargetPercent == 0) then
			self:SetWidth(128)
			self.nameFrame:SetWidth(128)
			self.statsFrame:SetWidth(128)
			self.statsFrame.healthBar.percent:Hide()
			self.statsFrame.manaBar.percent:Hide()
		else
			self:SetWidth(160)
			self.nameFrame:SetWidth(160)
			self.statsFrame:SetWidth(160)
			self.statsFrame.healthBar.percent:Show()
			self.statsFrame.manaBar.percent:Show()
		end

		if (conf.ShowTargetTargetMana == 1) then
			self.statsFrame.manaBar:Show()
			self.statsFrame:SetHeight(40)
		else
			self.statsFrame.manaBar:Hide()
			self.statsFrame:SetHeight(30)
		end
		XPerl_StatsFrameSetup(self)

		conf.TargetBuffSize = tonumber(conf.TargetBuffSize) or 20
		XPerl_SetBuffSize(self)

		XPerl_ProtectedCall(EnableDisable, self)

		self:SetScale(conf.Scale_TargetTargetFrame)

		XPerl_StatsFrameSetup(self)

		if (self:IsShown()) then
			XPerl_TargetTarget_UpdateDisplay(self, true)
		end
	end

	if (conf.ShowTargetTargetTarget == 1) then
		if (not XPerl_TargetTargetTarget) then
			local ttt = CreateFrame("Button", "XPerl_TargetTargetTarget", UIParent, "XPerl_TargetTarget_Template")

			ttt:SetPoint("BOTTOMLEFT", XPerl_TargetTarget.statsFrame, "BOTTOMRIGHT", 5, 0)
			XPerl_RestorePosition(ttt)
		end
	end

	Set(XPerl_TargetTarget)
	if (XPerl_TargetTargetTarget) then
		Set(XPerl_TargetTargetTarget)
	end
end
