local XPerl_Party_Pet_Events = {}
local PartyPetFrames = {}
local conf
XPerl_RequestConfig(function(new) conf = new end)

----------------------
-- Loading Function --
----------------------
function XPerl_Party_Pet_OnLoadEvents(self)
	self.time = 0
	XPerl_Party_Pet_EventFrame:RegisterEvent("UNIT_COMBAT")
	XPerl_Party_Pet_EventFrame:RegisterEvent("UNIT_PET")
	XPerl_Party_Pet_EventFrame:RegisterEvent("PARTY_MEMBERS_CHANGED")

	-- Set here to reduce amount of function calls made
	XPerl_Party_Pet_EventFrame:SetScript("OnEvent", XPerl_Party_Pet_OnEvent)
	XPerl_Party_Pet_EventFrame:SetScript("OnUpdate", XPerl_Party_Pet_OnUpdate)

	XPerl_RegisterOptionChanger(XPerl_Party_Pet_Set_Bits, "PartyPet")

	XPerl_Highlight:Register(XPerl_Party_Pet_HighlightCallback)
end

-- XPerl_Party_Pet_HighlightCallback
function XPerl_Party_Pet_HighlightCallback(updateName)
	for i = 1,GetNumPartyMembers() do
		if (UnitName("partypet"..i) == updateName) then
			XPerl_Highlight:SetHighlight(getglobal("XPerl_partypet"..i), updateName)
		end
	end
end

-- XPerl_Party_Pet_OnLoad
function XPerl_Party_Pet_OnLoad(self)
	XPerl_SetChildMembers(self)

	self.ownerid = "party"..self:GetID()
	self.partyid = "partypet"..self:GetID()
	PartyPetFrames[self.partyid] = self

	self.buffSetup = {
		debuffOnEnter = XPerl_Party_Pet_SetDeBuffTooltip,
		buffOnEnter = XPerl_Party_Pet_SetBuffTooltip,
		buffOnLeave = XPerl_PlayerTipHide,
		buffSizeOpt = 12,
		debuffSizeMod = 0,
		debuffAnchor1 = function(self, b) b:SetPoint("TOPLEFT", 0, -14) end,
		buffAnchor1 = function(self, b) b:SetPoint("TOPLEFT", 0, 0) end,
	}

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

	XPerl_UnitEvents(self, XPerl_Party_Pet_Events, {"UNIT_FACTION", "UNIT_AURA", "UNIT_DYNAMIC_FLAGS", "UNIT_FLAGS"})
	XPerl_RegisterBasics(self, XPerl_Party_Pet_Events)

	XPerl_RegisterHighlight(self.highlight, 2)
	XPerl_RegisterPerlFrames(this, {self.nameFrame, self.statsFrame})

	this.FlashFrames = {self.nameFrame, self.statsFrame}

	self:SetScript("OnShow",
		function(self)
			XPerl_Party_Pet_UpdateDisplay(self)
			XPerl_Party_SetDebuffLocation(self:GetParent())
		end)
	self:SetScript("OnHide",
		function(self)
			XPerl_Party_SetDebuffLocation(self:GetParent())
		end)

	self.time = 0
end

-------------------------
-- The Update Function --
-------------------------

-- XPerl_Party_Pet_CheckPet
-- returns true if full update required (frame shown)

-- XPerl_Party_Pet_UpdateName
local function XPerl_Party_Pet_UpdateName(self)
	local Partypetname = UnitName(self.partyid)

	if (Partypetname ~= nil) then
		self.nameFrame.text:SetText(Partypetname)
		if (UnitIsPVP(self.ownerid)) then
			self.nameFrame.text:SetTextColor(0,1,0)
		else
			self.nameFrame.text:SetTextColor(0.5,0.5,1)
		end
	end
end

-- XPerl_Party_Pet_UpdateHealth
local function XPerl_Party_Pet_UpdateHealth(self)
	local Partypethealth = UnitHealth(self.partyid)
	local Partypethealthmax = UnitHealthMax(self.partyid)

	local healthPct = Partypethealth / Partypethealthmax
	local phealthPct = format("%3.0f", healthPct * 100)

	self.statsFrame.healthBar:SetMinMaxValues(0, Partypethealthmax)
	self.statsFrame.healthBar:SetValue(Partypethealth)
	XPerl_SetSmoothBarColor(self.statsFrame.healthBar, healthPct)

	if (not UnitIsDead(self.partyid)) then
		if (conf.HealerModeParty == 1) then
			if (conf.HealerModePartyType == 1) then
				self.statsFrame.healthBar.text:SetText(format("%d/%d", Partypethealth - Partypethealthmax, Partypethealthmax))
			else
				self.statsFrame.healthBar.text:SetText(Partypethealth - Partypethealthmax)
			end
		else
			self.statsFrame.healthBar.text:SetText(format("%d",(100*(Partypethealth / Partypethealthmax))+0.5).."%")
		end

		self.statsFrame.healthBar.text:Show()
	end
end

-- XPerl_Party_Pet_UpdateMana
local function XPerl_Party_Pet_UpdateMana(self)
	local Partypetmana = UnitMana(self.partyid)
	local Partypetmanamax = UnitManaMax(self.partyid)

	self.statsFrame.manaBar:SetMinMaxValues(0, Partypetmanamax)
	self.statsFrame.manaBar:SetValue(Partypetmana)

	pmanaPct = (Partypetmana * 100.0) / Partypetmanamax
	pmanaPct =  format("%3.0f", pmanaPct)
	if (UnitPowerType(self.partyid) >= 1) then
		self.statsFrame.manaBar.text:SetText(Partypetmana)
	else
		self.statsFrame.manaBar.text:SetText(format("%d",(100*(Partypetmana / Partypetmanamax))+0.5).."%")
	end
	if (conf.ShowPartyPetPercent == 1) then
		self.statsFrame.manaBar.text:Show()
	else
		self.statsFrame.manaBar.text:Hide()
	end
end

-- XPerl_Party_Pet_UpdateLevel
local function XPerl_Party_Pet_UpdateLevel(self)
	local Partypetlevel = UnitLevel(self.partyid)
	local color = GetDifficultyColor(Partypetlevel)

	if (Partypetlevel == 0) then
		Partypetlevel = ""
	end

	self.nameFrame.level:SetText(Partypetlevel)
	self.nameFrame.level:SetTextColor(color.r,color.g,color.b)
end

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

-- XPerl_Party_Pet_Buff_UpdateAll
function XPerl_Party_Pet_Buff_UpdateAll(self)
	if (conf.ShowPartyPetBuffs == 1) then
		if (UnitExists(self.partyid)) then
			self.buffFrame:Show()

			for buffnum=1,10 do
				local name, rank, buff = XPerl_UnitBuff(self.partyid, buffnum, conf.PartyCastableBuffs)
				if (buff) then
					local button = XPerl_GetBuffButton(self, buffnum, 0, buff)
					button.icon:SetTexture(buff)
					button:Show()
				elseif (button) then
					local button = self.buffFrame.buff and self.buffFrame.buff[buffnum]
					if (button) then
				    		button:Hide()
					end
				end
			end
			for buffnum=1,8 do
				local name, rank, buff = XPerl_UnitDebuff(self.partyid, buffnum, conf.PartyCurableDebuffs)
				if (buff) then
					local button = XPerl_GetBuffButton(self, buffnum, 1, buff)
					button.icon:SetTexture(buff)
					button:Show()
				elseif (button) then
					local button = self.buffFrame.debuff and self.buffFrame.debuff[buffnum]
					if (button) then
						button:Hide()
					end
				end
			end
		else
			self.buffFrame:Hide()
		end
	else
		self.buffFrame:Hide()
	end

	XPerl_CheckDebuffs(self, self.partyid)
end

-- XPerl_Party_Pet_SetBuffTooltip
function XPerl_Party_Pet_SetBuffTooltip(self)
	local partyid = self:GetParent():GetParent():GetAttribute("unit")
	GameTooltip:SetOwner(self,"ANCHOR_BOTTOMRIGHT",30,0)
	XPerl_TooltipSetUnitBuff(GameTooltip, partyid, self:GetID(), conf.PartyCastableBuffs)
end

-- XPerl_Party_Pet_SetDeBuffTooltip
function XPerl_Party_Pet_SetDeBuffTooltip(self)
	local partyid = self:GetParent():GetParent():GetAttribute("unit")
	GameTooltip:SetOwner(self,"ANCHOR_BOTTOMRIGHT",30,0)
	XPerl_TooltipSetUnitDebuff(GameTooltip, partyid, self:GetID(), conf.PartyCurableDebuffs)
end

-- XPerl_Party_Pet_UpdateDisplayAll
function XPerl_Party_Pet_UpdateDisplayAll()
	for i,frame in pairs(PartyPetFrames) do
		if (frame:IsShown()) then
			XPerl_Party_Pet_UpdateDisplay(frame)
		end
	end
end

-- XPerl_Party_Pet_UpdateDisplay
function XPerl_Party_Pet_UpdateDisplay(self)
	XPerl_Party_Pet_UpdateName(self)
	XPerl_Party_Pet_UpdateHealth(self)
	XPerl_Party_Pet_UpdateLevel(self)
	XPerl_SetManaBarType(self)
	XPerl_Party_Pet_UpdateMana(self)
	XPerl_Party_Pet_UpdateCombat(self)
	XPerl_Party_Pet_Buff_UpdateAll(self)
	XPerl_UpdateSpellRange(self)
end

--------------------
-- Click Handlers --
--------------------

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

-- XPerl_Party_Pet_UpdateCombat
function XPerl_Party_Pet_UpdateCombat(self)
        if (UnitIsVisible(self.partyid) and UnitAffectingCombat(self.partyid)) then
		self.nameFrame.level:Hide()
		self.nameFrame.combatIcon:Show()
        else
		self.nameFrame.combatIcon:Hide()
		if (conf.ShowPartyPetLevel == 1) then
			self.nameFrame.level:Show()
		end
        end
	XPerl_Party_Pet_Update_Control(self)
end

-- XPerl_Party_Pet_CombatFlash
local function XPerl_Party_Pet_CombatFlash(f, elapsed, argNew, argGreen)
	if (XPerl_CombatFlashSet (elapsed, f, argNew, argGreen)) then
		XPerl_CombatFlashSetFrames(f)
	end
end

-- XPerl_Party_Pet_OnUpdate
function XPerl_Party_Pet_OnUpdate(self, elapsed)
	for i,f in pairs(PartyPetFrames) do
		if (f:IsShown()) then
			if (f.PlayerFlash) then
				XPerl_Party_Pet_CombatFlash(f, arg1, false)
			end
			f.time = f.time + elapsed
			if (f.time > 0.2) then
				f.time = 0
				XPerl_UpdateSpellRange(f)
			end
		end
	end
end

-------------------
-- Event Handler --
-------------------

-- XPerl_Party_Pet_OnEvent
function XPerl_Party_Pet_OnEvent(self, event)
	local func = XPerl_Party_Pet_Events[event]
	if (func) then
		if (strmatch(event, "^UNIT_")) then
			local f = PartyPetFrames[arg1]
			if (f) then
				func(f)
			end
		else
			func()
		end
	else
XPerl_ShowMessage("EXTRA EVENT")
	end
end

-- UNIT_COMBAT
function XPerl_Party_Pet_Events:UNIT_COMBAT()
	if (arg2 == "HEAL") then
		XPerl_Party_Pet_CombatFlash(self, 0, true, true)
	elseif (arg4 and arg4 > 0) then
		XPerl_Party_Pet_CombatFlash(self, 0, true)
	end
end

-- PARTY_MEMBERS_CHANGED
function XPerl_Party_Pet_Events:PARTY_MEMBERS_CHANGED()
	XPerl_Party_Pet_UpdateDisplayAll()
end

-- UNIT_PET
function XPerl_Party_Pet_Events:UNIT_PET()
	if (arg1 == self.ownerid) then
		XPerl_Party_Pet_UpdateDisplay(self)
	end
end

-- UNIT_FLAGS
function XPerl_Party_Pet_Events:UNIT_FLAGS()
	XPerl_Party_Pet_UpdateCombat(self)
end

XPerl_Party_Pet_Events.UNIT_DYNAMIC_FLAGS = XPerl_Party_Pet_Events.UNIT_FLAGS

-- UNIT_NAME_UPDATE
function XPerl_Party_Pet_Events:UNIT_NAME_UPDATE()
	XPerl_Party_Pet_UpdateName(self)
end

-- UNIT_FACTION
function XPerl_Party_Pet_Events:UNIT_FACTION()
	XPerl_Party_Pet_UpdateName(self)
	XPerl_Party_Pet_UpdateCombat(self)
end

-- UNIT_LEVEL
function XPerl_Party_Pet_Events:UNIT_LEVEL()
	XPerl_Party_Pet_UpdateLevel(self)
end

-- UNIT_HEALTH
function XPerl_Party_Pet_Events:UNIT_HEALTH()
	XPerl_Party_Pet_UpdateHealth(self)
end

-- UNIT_MAXHEALTH
function XPerl_Party_Pet_Events:UNIT_MAXHEALTH()
	XPerl_Party_Pet_UpdateHealth(self)
	XPerl_Party_Pet_UpdateLevel(self)
end

-- UNIT_AURA
function XPerl_Party_Pet_Events:UNIT_AURA()
	XPerl_Party_Pet_Buff_UpdateAll(self)
end

-- UNIT_DISPLAYPOWER
function XPerl_Party_Pet_Events:UNIT_DISPLAYPOWER()
	XPerl_SetManaBarType(self)
end

-- UNIT_MANA
function XPerl_Party_Pet_Events:UNIT_MANA()
	XPerl_Party_Pet_UpdateMana(self)
end

XPerl_Party_Pet_Events.UNIT_MAXMANA	= XPerl_Party_Pet_Events.UNIT_MANA
XPerl_Party_Pet_Events.UNIT_RAGE	= XPerl_Party_Pet_Events.UNIT_MANA
XPerl_Party_Pet_Events.UNIT_MAXRAGE	= XPerl_Party_Pet_Events.UNIT_MANA
XPerl_Party_Pet_Events.UNIT_FOCUS	= XPerl_Party_Pet_Events.UNIT_MANA
XPerl_Party_Pet_Events.UNIT_MAXFOCUS	= XPerl_Party_Pet_Events.UNIT_MANA
XPerl_Party_Pet_Events.UNIT_ENERGY	= XPerl_Party_Pet_Events.UNIT_MANA
XPerl_Party_Pet_Events.UNIT_MAXENERGY	= XPerl_Party_Pet_Events.UNIT_MANA

-- EnableDisable()
local function EnableDisable()

	for i,frame in pairs(PartyPetFrames) do
		if (conf.ShowPartyPets == 1) then
			RegisterUnitWatch(frame)
		else
			UnregisterUnitWatch(frame)
			frame:Hide()
		end
	end
end

-- XPerl_Party_Pet_Set_Bits
function XPerl_Party_Pet_Set_Bits()
	local function Set(self)
		if (conf.ShowPartyPetName == 1) then
			self.nameFrame:Show()
			self.nameFrame:SetHeight(20)
		else
			self.nameFrame:Hide()
			self.nameFrame:SetHeight(4)
		end

		if (conf.ShowPartyPetMana == 1) then
			self.statsFrame:SetHeight(33)
			self.statsFrame.manaBar:Show()
		else
			self.statsFrame:SetHeight(23)
			self.statsFrame.manaBar:Hide()
		end

		if (conf.ShowPartyPetLevel == 1) then
			self.nameFrame.level:Show()
		else
			self.nameFrame.level:Hide()
		end

		XPerl_Party_Pet_Buff_UpdateAll(self)

		self:SetScale(conf.Scale_PartyPets)

		XPerl_StatsFrameSetup(self)

		if (self:IsShown()) then
			XPerl_Party_Pet_UpdateDisplay(self)
		end
	end

	for k,v in pairs(PartyPetFrames) do
		Set(v)
	end

	XPerl_ProtectedCall(EnableDisable)
end
