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

-- Set_FOM_FeedButton
-- Set Feed'O'Matic button to same location as happy icon
-- We do a convoluted method here rather than attaching it to the happiness frame,
-- because it's an action button which would lock the Happiness frame during combat
local function Set_FOM_FeedButton()
	FOM_FeedButton:SetParent(UIParent)
	FOM_FeedButton:SetScale(XPerl_Player_Pet.happyFrame:GetScale())

	FOM_FeedButton:ClearAllPoints()
	if (conf.ShowPlayerPetName == 1 or conf.ShowPlayerPetPortrait == 1) then
		FOM_FeedButton:SetPoint("BOTTOMRIGHT", XPerl_Player_Pet.portraitFrame, "BOTTOMLEFT", 2, 0)
	else
		FOM_FeedButton:SetPoint("BOTTOMRIGHT", XPerl_Player_Pet.statsFrame, "BOTTOMLEFT", 2, 0)
	end
	FOM_FeedButton:SetHeight(XPerl_Player_Pet.happyFrame:GetHeight())
	FOM_FeedButton:SetWidth(XPerl_Player_Pet.happyFrame:GetWidth())

	FOM_FeedButton:Show()
end

-- XPerl_Player_Pet_OnLoad
function XPerl_Player_Pet_OnLoad(self)
	XPerl_SetChildMembers(self)

	XPerl_BlizzFrameDisable(PetFrame)

	self.buffSetup = {
		debuffOnEnter = XPerl_Player_Pet_SetDeBuffTooltip,
		buffOnEnter = XPerl_Player_Pet_SetBuffTooltip,
		buffOnLeave = XPerl_PlayerTipHide,
		buffSizeOpt = "PlayerPetBuffSize",
		debuffSizeMod = 0.3,
		debuffAnchor1 = function(self, b) b:SetPoint("TOPLEFT", 0, -(conf.PlayerPetBuffSize + 1)) end,
		buffAnchor1 = function(self, b) b:SetPoint("TOPLEFT", 0, 0) end,
	}

	CombatFeedback_Initialize(self.hitIndicator.text, 30)

        XPerl_SecureUnitButton_OnLoad(self, "pet", XPerl_ShowGenericMenu)
        XPerl_SecureUnitButton_OnLoad(self.nameFrame, "pet", XPerl_ShowGenericMenu)

	RegisterUnitWatch(self)

	local events = {"UNIT_PET", "PET_ATTACK_START", "UNIT_COMBAT", "UNIT_SPELLMISS"}
	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)
	if (FOM_FeedButton) then
		self:SetScript("OnShow",
			function(self)
				XPerl_Player_Pet_UpdatePortrait(self)
				XPerl_ProtectedCall(Set_FOM_FeedButton)
			end)
	else
		self:SetScript("OnShow", XPerl_Player_Pet_UpdatePortrait)
	end

	if (XPerl_ArcaneBar_RegisterFrame) then
		XPerl_ArcaneBar_RegisterFrame(self.nameFrame, "pet", "ArcaneBarPlayer")
	end

	XPerl_RegisterHighlight(self.highlight, 2)
	XPerl_RegisterPerlFrames(self, {self.nameFrame, self.statsFrame, self.portraitFrame, self.levelFrame, self.happyFrame})
	self.FlashFrames = {self.nameFrame, self.levelFrame, self.statsFrame, self.portraitFrame}

	XPerl_RegisterOptionChanger(XPerl_Player_Pet_Set_Bits, self)
end

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

	if (petname == UNKNOWNOBJECT) then
		self.nameFrame.text:SetText("")
	else
		self.nameFrame.text:SetText(petname)
	end

	if (UnitIsPVP("player")) then
	        self.nameFrame.text:SetTextColor(0, 1, 0, conf.TextTransparency)
	else
	        self.nameFrame.text:SetTextColor(0.5, 0.5, 1, conf.TextTransparency)
	end
end

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

	self.statsFrame.xpBar:SetStatusBarColor(0.3, 0.3, 1, 1)
	self.statsFrame.xpBar.bg:SetVertexColor(0.3, 0.3, 1, 0.25)

	self.statsFrame.xpBar:SetMinMaxValues(0, petxpmax)
	self.statsFrame.xpBar:SetValue(petxp)

        self.levelFrame.text:SetText(petlevel)
end

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

	XPerl_SetHealthBar(self.statsFrame.healthBar, pethealth, pethealthmax, conf.HealerModePlayer, conf.HealerModePlayerType)

	if (UnitIsDead("pet")) then
		self.statsFrame.healthBar.text:SetText(XPERL_LOC_DEAD)
		self.statsFrame.manaBar.text:Hide()
	end
end

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

	self.statsFrame.manaBar:SetMinMaxValues(0, petmanamax)
	self.statsFrame.manaBar:SetValue(petmana)

	self.statsFrame.manaBar.text:SetText(petmana.."/"..petmanamax)

	if (conf.ShowPlayerPetValues == 1) then
		self.statsFrame.manaBar.text: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 (conf.ShowPlayerPetPortrait == 1) then
		if (conf.ShowPlayerPetPortrait3D == 1) then
			self.portraitFrame.portrait:Hide()
			self.portraitFrame.portrait3D:Show()
			XPerlSetPortrait3D(self.portraitFrame.portrait3D, "pet")
		else
			self.portraitFrame.portrait3D.last3DTime = nil
			self.portraitFrame.portrait:Show()
			self.portraitFrame.portrait3D:Hide()
			SetPortraitTexture(self.portraitFrame.portrait, "pet")
		end
	end
end

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

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

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 = XPerl_GetBuffButton(self, buffnum, 0, buff)

			if (buff) then
				button.icon:SetTexture(buff)

				if (buffApplications > 1) then
					button.count:SetText(buffApplications)
					button.count:Show()
				else
					button.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 = XPerl_GetBuffButton(self, buffnum, 1, debuff)
			if (debuff) then
				button.icon:SetTexture(debuff)

				if ( debuffApplications > 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()

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

		XPerl_CheckDebuffs(self, "pet")
	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
		self.happyFrame.icon.tex:SetTexCoord(0.375, 0.5625, 0, 0.359375)
	elseif ( happiness == 2 ) then
		self.happyFrame.icon.tex:SetTexCoord(0.1875, 0.375, 0, 0.359375)
	elseif ( happiness == 3 ) then
		self.happyFrame.icon.tex:SetTexCoord(0, 0.1875, 0, 0.359375)
	end
	if ( happiness ~= nil ) then
		self.happyFrame.icon.tooltip = getglobal("PET_HAPPINESS"..happiness)
		self.happyFrame.icon.tooltipDamage = format(PET_DAMAGE_PERCENTAGE, damagePercentage)
		if ( loyaltyRate < 0 ) then
			self.happyFrame.icon.tooltipLoyalty = LOSING_LOYALTY
		elseif ( loyaltyRate > 0 ) then
			self.happyFrame.icon.tooltipLoyalty = GAINING_LOYALTY
		else
			self.happyFrame.icon.tooltipLoyalty = nil
		end
	end

	if (conf.PetHappiness == 1 and (conf.PetHappinessSad == 0 or happiness < 3)) then
		self.happyFrame:Show()

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

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

-- XPerl_Player_Pet_UpdateCombat
local function XPerl_Player_Pet_UpdateCombat(self)
	if (UnitExists("pet")) then
                if (UnitAffectingCombat("pet")) then
			self.nameFrame.combatIcon:Show()
                else
                        self.nameFrame.combatIcon: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_SetManaBarType(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_SetManaBarType(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 (conf.PetCombatHitIndicator == 1 and conf.ShowPlayerPetPortrait == 1) then
			CombatFeedback_OnCombatEvent(arg2, arg3, arg4, arg5)
		end

		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_SPELLMISS
function XPerl_Player_Pet_Events:UNIT_SPELLMISS()
	if (arg1 == "pet") then
		if (conf.PetCombatHitIndicator == 1 and conf.ShowPlayerPetPortrait == 1) then
			CombatFeedback_OnSpellMissEvent(arg2)
		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(self)
	if (conf.ShowPlayerPetPortrait==0) then
		self.portraitFrame:Hide()
		self.portraitFrame:SetWidth(3)
	else
		self.portraitFrame:Show()
		self.portraitFrame:SetWidth(50)
		XPerl_Player_Pet_UpdatePortrait(self)
	end

	if (conf.ShowPlayerPetName == 1) then
		self.nameFrame:Show()
		self.nameFrame:SetHeight(24)
	else
		self.nameFrame:Hide()
		self.nameFrame:SetHeight(2)
	end

	if (conf.ShowPlayerPetName == 1 or conf.ShowPlayerPetPortrait == 1) then
		self.happyFrame:SetPoint("BOTTOMRIGHT", self.portraitFrame, "BOTTOMLEFT", 2, 0)

		if (conf.ShowPetLevel == 1) then
        		self.levelFrame:SetPoint("TOPRIGHT", self.portraitFrame, "TOPLEFT", 2, 0)
		end
	else
		self.happyFrame:SetPoint("BOTTOMRIGHT", self.statsFrame, "BOTTOMLEFT", 2, 0)

		if (conf.ShowPetLevel == 1) then
        		self.levelFrame:SetPoint("TOPRIGHT", self.happyFrame, "TOPLEFT", 2, 0)
		end
	end

	if (FOM_FeedButton) then
		Set_FOM_FeedButton()
	end

	if (conf.ShowPetXP==0) then
		self.statsFrame.xpBar:Hide()
		self.statsFrame:SetHeight(34)
	else
		self.statsFrame.xpBar:Show()
		self.statsFrame:SetHeight(44)
	end

	if (conf.ShowPetLevel == 0) then
        	self.levelFrame:Hide()
	else
        	self.levelFrame:Show()
	end

	if (conf.ShowPetXP == 1 or conf.ShowPlayerPetPortrait == 0 or conf.ShowPlayerPetName == 0) then
		self.buffFrame:SetPoint("TOPLEFT", self.statsFrame, "BOTTOMLEFT", 2, 0)
	else
		self.buffFrame:SetPoint("TOPLEFT", self.portraitFrame, "BOTTOMLEFT", 2, 0)
	end

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

	self.highlight:ClearAllPoints()
	if (conf.ShowPlayerPetPortrait == 1 or conf.ShowPlayerPetName == 1) then
		self.highlight:SetPoint("BOTTOMLEFT", self.portraitFrame)
	else
		self.highlight:SetPoint("BOTTOMLEFT", self.statsFrame)
	end
	self.highlight:SetPoint("TOPRIGHT", self.nameFrame)

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

	self:SetScale(conf.Scale_PetFrame)

	XPerl_StatsFrameSetup(self, {"xpBar"}, 2)

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