local XPerl_Player_Pet_Events = {}

----------------------
-- Loading Function --
----------------------
function XPerl_Player_Pet_OnLoad(self)

	-- Events
	self.partyid = "pet"

	local events = {"UNIT_PET", "PET_ATTACK_START"}
	for i,event in pairs(events) do
		self:RegisterEvent(event)
	end

	XPerl_UnitEvents(self, XPerl_Player_Pet_Events, {"UNIT_FACTION", "UNIT_MODEL_CHANGED", "UNIT_FLAGS", "UNIT_DYNAMIC_FLAGS",
						"UNIT_AURA", "UNIT_FOCUS", "UNIT_MAXFOUS", "UNIT_PET_EXPERIENCE", "UNIT_HAPPINESS", })
	XPerl_RegisterBasics(self, XPerl_Player_Pet_Events)

	self.time = 0

	-- Set here to reduce amount of function calls made
	self:SetScript("OnEvent", XPerl_Player_Pet_OnEvent)
	self:SetScript("OnUpdate", XPerl_Player_Pet_OnUpdate)
	self:SetScript("OnShow", XPerl_Player_Pet_UpdatePortrait)

	XPerl_RegisterHighlight(XPerl_Player_Pet_CastClickOverlay, 2)
	XPerl_RegisterPerlFrames(self, {"NameFrame", "StatsFrame", "PortraitFrame", "LevelFrame", "HappyFrame"})

	self.FlashFrames = {XPerl_Player_Pet_NameFrame, XPerl_Player_Pet_LevelFrame,
				XPerl_Player_Pet_StatsFrame, XPerl_Player_Pet_PortraitFrame}
end

-- XPerl_Player_Pet_UpdateName
local function XPerl_Player_Pet_UpdateName()
	local petname = UnitName("pet")

	if (petname == UNKNOWNOBJECT) then
		XPerl_Player_Pet_NameFrame_NameBarText:SetText("")
	else
		XPerl_Player_Pet_NameFrame_NameBarText:SetText(petname)
	end

	if (UnitIsPVP("player")) then
	        XPerl_Player_Pet_NameFrame_NameBarText:SetTextColor(0, 1, 0, XPerlConfig.TextTransparency)
	else
	        XPerl_Player_Pet_NameFrame_NameBarText:SetTextColor(0.5, 0.5, 1, XPerlConfig.TextTransparency)
	end
end

-- XPerl_Player_Pet_UpdateLevel
local function XPerl_Player_Pet_UpdateLevel(self)
	local petlevel = UnitLevel("pet")
	local petxp, petxpmax = GetPetExperience()

	XPerl_Player_Pet_StatsFrame_XPBar:SetStatusBarColor(0.3, 0.3, 1, 1)
	XPerl_Player_Pet_StatsFrame_XPBarBG:SetVertexColor(0.3, 0.3, 1, 0.25)

	XPerl_Player_Pet_StatsFrame_XPBar:SetMinMaxValues(0, petxpmax)
	XPerl_Player_Pet_StatsFrame_XPBar:SetValue(petxp)

        XPerl_Player_Pet_LevelFrameText:SetText(petlevel)
end

-- XPerl_Player_Pet_UpdateHealth
local function XPerl_Player_Pet_UpdateHealth(self)
	local pethealth = UnitHealth("pet")
	local pethealthmax = UnitHealthMax("pet")

	XPerl_SetHealthBar(XPerl_Player_Pet_StatsFrame_HealthBar, pethealth, pethealthmax, XPerlConfig.HealerModePlayer, XPerlConfig.HealerModePlayerType)

	if (UnitIsDead("pet")) then
		XPerl_Player_Pet_StatsFrame_HealthBarText:SetText(XPERL_LOC_DEAD)
		XPerl_Player_Pet_StatsFrame_ManaBarText:Hide()
	end
end

local function XPerl_Player_Pet_UpdateManaType(self)
	XPerl_SetManaBarType("pet", XPerl_Player_Pet_StatsFrame_ManaBar)
end

-- XPerl_Player_Pet_UpdateMana()
local function XPerl_Player_Pet_UpdateMana(self)
	local petmana = UnitMana("pet")
	local petmanamax = UnitManaMax("pet")

	XPerl_Player_Pet_StatsFrame_ManaBar:SetMinMaxValues(0, petmanamax)
	XPerl_Player_Pet_StatsFrame_ManaBar:SetValue(petmana)

	XPerl_Player_Pet_StatsFrame_ManaBarText:SetText(petmana.."/"..petmanamax)

	if (XPerlConfig.ShowPlayerPetValues == 1) then
		XPerl_Player_Pet_StatsFrame_ManaBarText:Show()
	end
end

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

-- XPerl_Player_Pet_UpdatePortrait()
function XPerl_Player_Pet_UpdatePortrait(self)
	if (XPerlConfig.ShowPlayerPetPortrait == 1) then
		if (XPerlConfig.ShowPlayerPetPortrait3D == 1) then
			XPerl_Player_Pet_PortraitFrame_Portrait:Hide()
			XPerl_Player_Pet_PortraitFrame_Portrait3D:Show()
			XPerlSetPortrait3D(XPerl_Player_Pet_PortraitFrame_Portrait3D, "pet")
		else
			XPerl_Player_Pet_PortraitFrame_Portrait3D.last3DTime = nil
			XPerl_Player_Pet_PortraitFrame_Portrait:Show()
			XPerl_Player_Pet_PortraitFrame_Portrait3D:Hide()
			SetPortraitTexture(XPerl_Player_Pet_PortraitFrame_Portrait, "pet")
		end
	end
end

-- XPerl_Player_Pet_OnUpdate
function XPerl_Player_Pet_OnUpdate(self)
	if (self.PlayerFlash) then
		XPerl_Player_Pet_CombatFlash(self, arg1, false)
	end
end

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

	local buffType
	if (debuff == 1) then
		buffType = "DeBuff"
	else
		buffType = "Buff"
	end
	local name = "XPerl_Player_Pet_BuffFrame_"..buffType..buffnum
	local button = getglobal(name)

	if (not button and createIfAbsent) then
		button = CreateFrame("Button", name, XPerl_Player_Pet_BuffFrame, "XPerl_"..buffType.."Template")
		button:SetID(buffnum)

		local size = XPerlConfig.PlayerPetBuffSize * (1 + (0.3 * debuff))
		button:SetHeight(size)
		button:SetWidth(size)

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

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

	return button
end

local function XPerl_Player_Pet_Buff_UpdateAll(self)
	if (UnitExists("pet")) then
		for buffnum=1,10 do
			local name, rank, buff, buffApplications = UnitBuff("pet", buffnum)
			local button = GetBuffButton(buffnum, 0, buff)

			if (buff) then
				local icon = getglobal(button:GetName().."Icon")
				local count = getglobal(button:GetName().."Count")
				icon:SetTexture(buff)

				if ( buffApplications > 1 ) then
					count:SetText(buffApplications)
					count:Show()
				else
					count:Hide()
				end
				button:Show()

			elseif (button) then
				button:Hide()
			end
		end

		for buffnum=1,8 do
			local name, rank, debuff, debuffApplications, debuffType = UnitDebuff("pet", buffnum)
			local button = GetBuffButton(buffnum, 1, debuff)
			if (debuff) then
				local icon = getglobal(button:GetName().."Icon")
				local count = getglobal(button:GetName().."Count")
				local border = getglobal(button:GetName().."Border")

				icon:SetTexture(debuff)

				if ( debuffApplications > 1 ) then
					count:SetText(debuffApplications)
					count:Show()
				else
					count:Hide()
				end

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

			elseif (button) then
				button:Hide()
			end
		end

		XPerl_CheckDebuffs(self)
	end
end

function XPerl_Player_Pet_SetBuffTooltip (self)
	GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")
	GameTooltip:SetUnitBuff("pet", self:GetID())
end

function XPerl_Player_Pet_SetDeBuffTooltip (self)
	GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT")
	GameTooltip:SetUnitDebuff("pet", self:GetID())
end

---------------
-- Happiness --
---------------
function XPerl_Player_Pet_SetHappiness(self)
	local happiness, damagePercentage, loyaltyRate = GetPetHappiness()

	if (not happiness) then
		happiness = 3
	end

	if ( happiness == 1 ) then
		XPerl_Player_Pet_HappyFrame_PetHappinessTexture:SetTexCoord(0.375, 0.5625, 0, 0.359375)
	elseif ( happiness == 2 ) then
		XPerl_Player_Pet_HappyFrame_PetHappinessTexture:SetTexCoord(0.1875, 0.375, 0, 0.359375)
	elseif ( happiness == 3 ) then
		XPerl_Player_Pet_HappyFrame_PetHappinessTexture:SetTexCoord(0, 0.1875, 0, 0.359375)
	end
	if ( happiness ~= nil ) then
		XPerl_Player_Pet_HappyFrame_PetHappiness.tooltip = getglobal("PET_HAPPINESS"..happiness)
		XPerl_Player_Pet_HappyFrame_PetHappiness.tooltipDamage = format(PET_DAMAGE_PERCENTAGE, damagePercentage)
		if ( loyaltyRate < 0 ) then
			XPerl_Player_Pet_HappyFrame_PetHappiness.tooltipLoyalty = getglobal("LOSING_LOYALTY")
		elseif ( loyaltyRate > 0 ) then
			XPerl_Player_Pet_HappyFrame_PetHappiness.tooltipLoyalty = getglobal("GAINING_LOYALTY")
		else
			XPerl_Player_Pet_HappyFrame_PetHappiness.tooltipLoyalty = nil
		end
	end

	if (XPerlConfig.PetHappiness == 1 and (XPerlConfig.PetHappinessSad == 0 or happiness < 3)) then
		XPerl_Player_Pet_HappyFrame:Show()

		if (XPerlConfig.PetFlashWhenSad == 1 and happiness < 3) then
			if (not UIFrameIsFlashing(XPerl_Player_Pet_HappyFrame)) then
				UIFrameFlash(XPerl_Player_Pet_HappyFrame, 0.5, 0.5, 30, 1, 0, 1)
			end
		else
			if (UIFrameIsFlashing(XPerl_Player_Pet_HappyFrame)) then
				UIFrameFlashStop(XPerl_Player_Pet_HappyFrame)
                		UIFrameFlashUpdate(1)
			end
		end
	else
		if (UIFrameIsFlashing(XPerl_Player_Pet_HappyFrame)) then
			UIFrameFlashStop(XPerl_Player_Pet_HappyFrame)
                	UIFrameFlashUpdate(1)
		end
		XPerl_Player_Pet_HappyFrame:Hide()
	end
end

-- XPerl_Player_Pet_Update_Control
local function XPerl_Player_Pet_Update_Control(self)
        if (UnitIsCharmed("pet")) then
		XPerl_Player_Pet_NameFrame_Warning:Show()
	else
		XPerl_Player_Pet_NameFrame_Warning:Hide()
	end
end

-- XPerl_Player_Pet_UpdateCombat
local function XPerl_Player_Pet_UpdateCombat(self)
	if (UnitExists("pet")) then
                if (UnitAffectingCombat("pet")) then
                        XPerl_Player_Pet_NameFrame_ActivityStatus:Show()
                else
                        XPerl_Player_Pet_NameFrame_ActivityStatus:Hide()
                end
		XPerl_Player_Pet_Update_Control(self)
        end
end

function XPerl_Player_Pet_UpdateDisplay(self)
	XPerl_Player_Pet_UpdatePortrait(self)
	XPerl_Player_Pet_UpdateName(self)
	XPerl_Player_Pet_UpdateHealth(self)
	XPerl_Player_Pet_UpdateManaType(self)
	XPerl_Player_Pet_UpdateMana(self)
	XPerl_Player_Pet_UpdateLevel(self)
	XPerl_Player_Pet_SetHappiness(self)
	XPerl_Player_Pet_Buff_UpdateAll(self)
	XPerl_Player_Pet_UpdateCombat(self)
end

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

-- UNIT_AURA
function XPerl_Player_Pet_Events:UNIT_AURA()
	XPerl_Player_Pet_Buff_UpdateAll(self)
end

-- UNIT_PET
function XPerl_Player_Pet_Events:UNIT_PET()
	XPerl_Player_Pet_UpdateDisplay(XPerl_Player_Pet)
end

XPerl_Player_Pet_Events.PET_STABLE_SHOW = XPerl_Player_Pet_Events.UNIT_PET

-- UNIT_NAME_UPDATE
function XPerl_Player_Pet_Events:UNIT_NAME_UPDATE()
	XPerl_Player_Pet_UpdateName(self)
end

-- UNIT_MODEL_CHANGED
function XPerl_Player_Pet_Events:UNIT_MODEL_CHANGED()
	XPerl_Player_Pet_UpdatePortrait(self)
end
--XPerl_Player_Pet_Events.UNIT_PORTRAIT_UPDATE = XPerl_Player_Pet_Events.UNIT_MODEL_CHANGED

-- UNIT_HEALTH, UNIT_MAXHEALTH
function XPerl_Player_Pet_Events:UNIT_HEALTH()
	XPerl_Player_Pet_UpdateHealth(self)
end
XPerl_Player_Pet_Events.UNIT_MAXHEALTH = XPerl_Player_Pet_Events.UNIT_HEALTH

-- UNIT_RAGE
function XPerl_Player_Pet_Events:UNIT_RAGE()
	XPerl_Player_Pet_UpdateMana(self)
end

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

-- UNIT_LEVEL
function XPerl_Player_Pet_Events:UNIT_LEVEL()
	XPerl_Player_Pet_UpdateLevel(self)
end

XPerl_Player_Pet_Events.UNIT_PET_EXPERIENCE = XPerl_Player_Pet_Events.UNIT_LEVEL

-- UNIT_DISPLAYPOWER
function XPerl_Player_Pet_Events:UNIT_DISPLAYPOWER()
	XPerl_Player_Pet_UpdateManaType(self)
end

-- UNIT_HAPPINESS
-- Happiness events come while you have a pet up, each 2 secs
function XPerl_Player_Pet_Events:UNIT_HAPPINESS()
	--XPerl_Player_Pet_UpdateDisplay();	-- Update all, fixes bug with stables in 1.11
	XPerl_Player_Pet_SetHappiness(self)
	XPerl_Player_Pet_UpdateCombat(self)
end

-- PET_ATTACK_START
function XPerl_Player_Pet_Events:PET_ATTACK_START()
	XPerl_Player_Pet_UpdateCombat(XPerl_Player_Pet)
end

-- UNIT_COMBAT
function XPerl_Player_Pet_Events:UNIT_COMBAT()
	if (arg1 == "pet") then
		if (arg2 == "HEAL") then
			XPerl_Player_Pet_CombatFlash(XPerl_Player_Pet, 0, true, true)
		elseif (arg4 and arg4 > 0) then
			XPerl_Player_Pet_CombatFlash(XPerl_Player_Pet, 0, true)
		end
	end
end

-- UNIT_DYNAMIC_FLAGS
function XPerl_Player_Pet_Events:UNIT_FACTION()
	XPerl_Player_Pet_UpdateName(self)
	XPerl_Player_Pet_UpdateCombat(self)
end

XPerl_Player_Pet_Events.UNIT_FLAGS = XPerl_Player_Pet_Events.UNIT_FACTION
XPerl_Player_Pet_Events.UNIT_DYNAMIC_FLAGS = XPerl_Player_Pet_Events.UNIT_FACTION

-- XPerl_Player_Pet_Set_Bits
function XPerl_Player_Pet_Set_Bits()
	if (XPerlConfig.ShowPlayerPetPortrait==0) then
		XPerl_Player_Pet_PortraitFrame:Hide()
		XPerl_Player_Pet_PortraitFrame:SetWidth(3)
	else
		XPerl_Player_Pet_PortraitFrame:Show()
		XPerl_Player_Pet_PortraitFrame:SetWidth(50)
		XPerl_Player_Pet_UpdatePortrait(self)
	end

	if (XPerlConfig.ShowPlayerPetName == 1) then
		XPerl_Player_Pet_NameFrame:Show()
		XPerl_Player_Pet_NameFrame:SetHeight(24)
	else
		XPerl_Player_Pet_NameFrame:Hide()
		XPerl_Player_Pet_NameFrame:SetHeight(2)
	end

	if (XPerlConfig.ShowPlayerPetName == 1 or XPerlConfig.ShowPlayerPetPortrait == 1) then
		XPerl_Player_Pet_HappyFrame:SetPoint("BOTTOMRIGHT", XPerl_Player_Pet_PortraitFrame, "BOTTOMLEFT", 2, 0)

		if (XPerlConfig.ShowPetLevel == 1) then
        		XPerl_Player_Pet_LevelFrame:SetPoint("TOPRIGHT", XPerl_Player_Pet_PortraitFrame, "TOPLEFT", 2, 0)
		end
	else
		XPerl_Player_Pet_HappyFrame:SetPoint("BOTTOMRIGHT", XPerl_Player_Pet_StatsFrame, "BOTTOMLEFT", 2, 0)

		if (XPerlConfig.ShowPetLevel == 1) then
        		XPerl_Player_Pet_LevelFrame:SetPoint("TOPRIGHT", XPerl_Player_Pet_HappyFrame, "TOPLEFT", 2, 0)
		end
	end

	if (XPerlConfig.ShowPetXP==0) then
		XPerl_Player_Pet_StatsFrame_XPBar:Hide()
		XPerl_Player_Pet_StatsFrame:SetHeight(34)
	else
		XPerl_Player_Pet_StatsFrame_XPBar:Show()
		XPerl_Player_Pet_StatsFrame:SetHeight(44)
	end

	if (XPerlConfig.ShowPetLevel == 0) then
        	XPerl_Player_Pet_LevelFrame:Hide()
	else
        	XPerl_Player_Pet_LevelFrame:Show()
	end

	if (XPerlConfig.ShowPetXP == 1 or XPerlConfig.ShowPlayerPetPortrait == 0 or XPerlConfig.ShowPlayerPetName == 0) then
		XPerl_Player_Pet_BuffFrame:SetPoint("TOPLEFT", XPerl_Player_Pet_StatsFrame, "BOTTOMLEFT", 2, 0)
	else
		XPerl_Player_Pet_BuffFrame:SetPoint("TOPLEFT", XPerl_Player_Pet_PortraitFrame, "BOTTOMLEFT", 2, 0)
	end

	if (XPerlConfig.ShowPlayerPetValues == 1) then
        	XPerl_Player_Pet_StatsFrame_HealthBarText:Show()
        	XPerl_Player_Pet_StatsFrame_ManaBarText:Show()
	else
        	XPerl_Player_Pet_StatsFrame_HealthBarText:Hide()
        	XPerl_Player_Pet_StatsFrame_ManaBarText:Hide()
	end

	XPerl_Player_Pet_CastClickOverlay:ClearAllPoints()
	if (XPerlConfig.ShowPlayerPetPortrait == 1 or XPerlConfig.ShowPlayerPetName == 1) then
		XPerl_Player_Pet_CastClickOverlay:SetPoint("BOTTOMLEFT", XPerl_Player_Pet_PortraitFrame)
	else
		XPerl_Player_Pet_CastClickOverlay:SetPoint("BOTTOMLEFT", XPerl_Player_Pet_StatsFrame)
	end
	XPerl_Player_Pet_CastClickOverlay:SetPoint("TOPRIGHT", XPerl_Player_Pet_NameFrame)

	XPerlConfig.PlayerPetBuffSize = tonumber(XPerlConfig.PlayerPetBuffSize) or 20
	XPerl_SetBuffSize("XPerl_Player_Pet_", XPerlConfig.PlayerPetBuffSize, XPerlConfig.PlayerPetBuffSize * 1.3)
end
