local XPerl_Player_Events = {}
local isOutOfControl = nil
local conf
XPerl_RequestConfig(function(new) conf = new end)

----------------------
-- Loading Function --
----------------------
function XPerl_Player_OnLoad(self)
	XPerl_SetChildMembers(self)

	XPerl_BlizzFrameDisable(PlayerFrame)

	CombatFeedback_Initialize(self.hitIndicator.text, 30)

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

	local events = {"PLAYER_ENTERING_WORLD", "VARIABLES_LOADED", "PARTY_MEMBERS_CHANGED", "PARTY_LEADER_CHANGED",
			"PARTY_LOOT_METHOD_CHANGED", "RAID_ROSTER_UPDATE", "PLAYER_UPDATE_RESTING", "PLAYER_REGEN_ENABLED",
			"PLAYER_REGEN_DISABLED", "PLAYER_ENTER_COMBAT", "PLAYER_LEAVE_COMBAT", "PLAYER_LEVEL_UP", "PLAYER_DEAD",
			"PLAYER_XP_UPDATE", "UPDATE_FACTION", "PLAYER_AURAS_CHANGED", "PLAYER_CONTROL_LOST", "PLAYER_CONTROL_GAINED",
			"UNIT_COMBAT"}

	for i,event in pairs(events) do
		self:RegisterEvent(event)
	end

	XPerl_UnitEvents(self, XPerl_Player_Events, {"UNIT_SPELLMISS", "UNIT_FACTION", "UNIT_MODEL_CHANGED", "UNIT_FLAGS", "PLAYER_FLAGS_CHANGED"})
	XPerl_RegisterBasics(self, XPerl_Player_Events)

	self.statsFrame.druidBar:SetHeight(1)
	self.statsFrame.druidBar:Hide()

	--self.PlayerFlash = 0
	self.EnergyTime = 0
	self.EnergyLast = 0

	self:SetScript("OnUpdate", XPerl_Player_OnUpdate)
	self:SetScript("OnEvent", XPerl_Player_OnEvent)
	self:SetScript("OnShow", XPerl_Player_UpdatePortrait)

	self.time = 0

	XPerl_RegisterHighlight(self.highlight, 3)
	XPerl_RegisterPerlFrames(XPerl_Player, {self.nameFrame, self.statsFrame, self.levelFrame, self.portraitFrame, self.groupFrame})

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

	self.FlashFrames = {self.portraitFrame, self.nameFrame,
				self.levelFrame, self.statsFrame}

	XPerl_RegisterOptionChanger(XPerl_Player_Set_Bits, self)
	XPerl_Highlight:Register(XPerl_Player_HighlightCallback)
	self.IgnoreHighlightStates = {AGGRO = true}
end

-- XPerl_Player_HighlightCallback(updateName)
function XPerl_Player_HighlightCallback(updateName)
	if (UnitName("player") == updateName) then
		XPerl_Highlight:SetHighlight(XPerl_Player, updateName)
	end
end

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

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

-- XPerl_Player_UpdatePortrait
function XPerl_Player_UpdatePortrait(self)
	if (conf and conf.ShowPlayerPortrait == 1) then
		if (conf.ShowPlayerPortrait3D == 1) then
			self.portraitFrame.portrait:Hide()
			self.portraitFrame.portrait3D:Show()
			XPerlSetPortrait3D(self.portraitFrame.portrait3D, "player")
		else
			self.portraitFrame.portrait3D.last3DTime = nil
			self.portraitFrame.portrait:Show()
			self.portraitFrame.portrait3D:Hide()
			SetPortraitTexture(self.portraitFrame.portrait, "player")
		end
	end
end

-- XPerl_Player_UpdateManaType
local function XPerl_Player_UpdateManaType(self)
	XPerl_SetManaBarType(self)

	if (UnitPowerType("player") == 3) then
		self.EnergyEnabled = true
	else
		self.EnergyEnabled = nil
	end
	XPerl_Player_TickerShowHide(self)
end

-- XPerl_Player_UpdateLeader()
function XPerl_Player_UpdateLeader(self)
	if (IsPartyLeader()) then
		self.nameFrame.leaderIcon:Show()
	else
		self.nameFrame.leaderIcon:Hide()
	end

	if (conf.ShowPartyNumber == 1 and GetNumRaidMembers() > 0) then
		for i = 1,GetNumRaidMembers() do
			local name, rank, subgroup = GetRaidRosterInfo(i)
			if (name == UnitName("player")) then
				if (conf.ShowPartyNumberWithName == 0) then
					self.groupFrame.text:SetText(format(XPERL_RAID_GROUP, subgroup))
					self.groupFrame:Show()
					self.nameFrame.group:Hide()
					return
				else
					self.nameFrame.group:SetText(format(XPERL_RAID_GROUPSHORT, subgroup))
					self.nameFrame.group:Show()
					self.groupFrame:Hide()
					return
				end
			end
		end
	end

	self.nameFrame.group:Hide()
	self.groupFrame:Hide()
end

-- XPerl_Player_UpdateMasterLooter()
local function XPerl_Player_UpdateMasterLooter(self)
	local method, index = GetLootMethod()

	if (method == "master" and index == 0) then
		self.nameFrame.masterIcon:Show()
	else
		self.nameFrame.masterIcon:Hide()
	end
end

-- XPerl_Player_UpdateName()
local function XPerl_Player_UpdateName(self)
	self.nameFrame.text:SetText(UnitName("player"))
end

-- XPerl_Player_UpdateRep
local function XPerl_Player_UpdateRep(self)
	local name, reaction, min, max, value = GetWatchedFactionInfo()
	local color

	if (name) then
		color = FACTION_BAR_COLORS[reaction]
	else
		name = XPERL_LOC_NONEWATCHED
		max = 1
		min = 0
		value = 0
		color = FACTION_BAR_COLORS[4]
	end

	value = value - min
	max = max - min
	min = 0

	self.statsFrame.repBar:SetMinMaxValues(min, max)
	self.statsFrame.repBar:SetValue(value)

	self.statsFrame.repBar:SetStatusBarColor(color.r, color.g, color.b, 1)
	self.statsFrame.repBar.bg:SetVertexColor(color.r, color.g, color.b, 0.25)

	local perc = (value * 100) / max
	self.statsFrame.repBar.percent:SetText(format("%.1f"..PERCENT_SYMBOL, perc))

	if (max == 1) then
		self.statsFrame.repBar.text:SetText(name)
	else
		self.statsFrame.repBar.text:SetText(value.."/"..max)
	end
	--self.statsFrame.repBar.text:SetText(name)
end

-- XPerl_Player_UpdateXP
local function XPerl_Player_UpdateXP(self)
	local playerxp = UnitXP("player")
	local playerxpmax = UnitXPMax("player")
	local playerxprest = GetXPExhaustion() or 0
	self.statsFrame.xpBar:SetMinMaxValues(0, playerxpmax)
	self.statsFrame.xpRestBar:SetMinMaxValues(0, playerxpmax)
	self.statsFrame.xpBar:SetValue(playerxp)
	local xptext

	if (playerxpmax > 10000) then
		xptext = format("%.0fK/%.0fK", playerxp / 1000, playerxpmax / 1000)
	else
		xptext = playerxp.."/"..playerxpmax
	end

	if (playerxprest > 0) then
		if (playerxpmax > 10000) then
			xptext = xptext .. format("(+%.0fK)", playerxprest / 1000)
		else
			xptext = xptext .. format("(+%d)", playerxprest)
		end

		color = {r = 0.3, g = 0.3, b = 1}
	else
		color = {r = 0.6, g = 0, b = 0.6}
	end

	self.statsFrame.xpRestBar:SetValue(playerxp + playerxprest)
	self.statsFrame.xpBar:SetStatusBarColor(color.r, color.g, color.b, 1)
	self.statsFrame.xpRestBar:SetStatusBarColor(color.r, color.g, color.b, 0.5)
	self.statsFrame.xpBar.bg:SetVertexColor(color.r, color.g, color.b, 0.25)

	self.statsFrame.xpBar.text:SetText(xptext)

	local xppercenttext=((playerxp * 100.0) / playerxpmax)
	xppercenttext=format("%3.0f", xppercenttext)
	self.statsFrame.xpBar.percent:SetText(xppercenttext.."%")
end

-- XPerl_Player_UpdateCombat
local function XPerl_Player_UpdateCombat(self)
	if (UnitAffectingCombat("player")) then
		self.nameFrame.text:SetTextColor(1,0,0)
		self.nameFrame.combatIcon:SetTexCoord(0.5, 1.0, 0.0, 0.5)
		self.nameFrame.combatIcon:Show()
	else
		if (UnitIsPVP("player")) then
			self.nameFrame.text:SetTextColor(0,1,0)
		else
			XPerl_ColourFriendlyUnit(self.nameFrame.text, "player")
		end

		if (IsResting()) then
			self.nameFrame.combatIcon:SetTexCoord(0, 0.5, 0.0, 0.5)
			self.nameFrame.combatIcon:Show()
		else
			self.nameFrame.combatIcon:Hide()
		end
	end
end

-- XPerl_Player_UpdatePVP
local function XPerl_Player_UpdatePVP(self)
	local playerrankname, playerrank=GetPVPRankInfo(UnitPVPRank("player"), "player")
	if (playerrank and conf.ShowPlayerPVPRank==1) then
		self.nameFrame.pvpRankIcon:Show()
		if (playerrank==0) then
			self.nameFrame.pvpRankIcon:Hide()
		else
			self.nameFrame.pvpRankIcon:SetTexture(format("Interface\\PVPRankBadges\\PVPRank%02d", playerrank))
		end
	else
		self.nameFrame.pvpRankIcon:Hide()
	end

	if (conf.ShowPlayerClassIcon == 1) then
		local _, PlayerClass = UnitClass("player")
		local r, l, t, b = XPerl_ClassPos(PlayerClass)
		self.classFrame.tex:SetTexCoord(r, l, t, b)
	end

	-- PVP Status settings
	if (UnitAffectingCombat("player")) then
		self.nameFrame.text:SetTextColor(1,0,0)
	elseif (conf.ClassColouredNames == 0 and UnitIsPVP("player")) then
		self.nameFrame.text:SetTextColor(0,1,0)
	else
		XPerl_ColourFriendlyUnit(self.nameFrame.text, "player")
	end

	if (conf.ShowPlayerPVP == 1 and UnitIsPVP("player")) then
		self.nameFrame.pvpIcon:Show()
		self.nameFrame.pvpIcon:SetTexture("Interface\\TargetingFrame\\UI-PVP-"..UnitFactionGroup("player"))
	else
		self.nameFrame.pvpIcon:Hide()
	end
end

-- XPerl_Player_Feigning
local function XPerl_Player_Feigning (self)
	for buffnum=1,16 do
		local buff = UnitBuff("player", buffnum)
		if (not buff) then
			return
		end
		if (strfind(strlower(buff), "feigndeath")) then
			return true
		end
	end
end

-- XPerl_Player_DruidBarUpdate
local function XPerl_Player_DruidBarUpdate(self)
	local manaPct
	if (SimpleDruidBar) then
		self.statsFrame.druidBar:SetMinMaxValues(0, SimpleDruidBar.MaxMana)
		self.statsFrame.druidBar:SetValue(SimpleDruidBar.CurrMana)
		manaPct = (SimpleDruidBar.CurrMana * 100.0) / SimpleDruidBar.MaxMana
		self.statsFrame.druidBar.text:SetText(ceil(SimpleDruidBar.CurrMana).."/"..SimpleDruidBar.MaxMana)

		-- Doesn't hide the frame, but makes it not appear on screen. The code relies on IsShown() to function
		SimpleDruidBar.DISPLAY_BAR:ClearAllPoints()
	else
		self.statsFrame.druidBar:SetMinMaxValues(0,DruidBarKey.maxmana)
		self.statsFrame.druidBar:SetValue(DruidBarKey.keepthemana)
		manaPct = (DruidBarKey.keepthemana * 100.0) / DruidBarKey.maxmana
		self.statsFrame.druidBar.text:SetText(floor(DruidBarKey.keepthemana).."/"..DruidBarKey.maxmana)
	end

	manaPct = format("%3.0f", manaPct)
	self.statsFrame.druidBar.percent:SetText(manaPct.."%")

	local druidBarExtra
	if (UnitPowerType("player")>0) then
		self.statsFrame.druidBar.text:Show()
		if (conf.ShowPlayerPercent == 1) then
			self.statsFrame.druidBar.percent:Show()
		end
		self.statsFrame.druidBar:Show()
		self.statsFrame.druidBar:SetHeight(10)
		druidBarExtra = 1
	else
		self.statsFrame.druidBar.percent:Hide()
		self.statsFrame.druidBar.text:Hide()
		self.statsFrame.druidBar:Hide()
		self.statsFrame.druidBar:SetHeight(1)
		druidBarExtra = 0
	end

	local h = 40 + ((druidBarExtra + conf.ShowPlayerRepBar + conf.ShowPlayerXPBar) * 10)
	XPerl_Player.statsFrame:SetHeight(h)
	XPerl_StatsFrameSetup(self, {"druidBar", "xpBar", "repBar"})
end

-- XPerl_Player_UpdateMana
local function XPerl_Player_UpdateMana(self)
	local playermana = UnitMana("player")
	local playermanamax = UnitManaMax("player")
	self.statsFrame.manaBar:SetMinMaxValues(0, playermanamax)
	self.statsFrame.manaBar:SetValue(playermana)
	manaPct = (playermana * 100.0) / playermanamax
	manaPct =  format("%3.0f", manaPct)

	self.statsFrame.manaBar.text:SetText(playermana.."/"..playermanamax)
	if (UnitPowerType("player")>=1) then
		self.statsFrame.manaBar.percent:SetText(playermana)
	else
		self.statsFrame.manaBar.percent:SetText(manaPct.."%")
	end

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

	if (DruidBarKey or SimpleDruidBar) then
		local _, engClass = UnitClass("player")
		if (engClass == "DRUID") then
			XPerl_Player_DruidBarUpdate(self)
		end
	end
end

-- XPerl_Player_UpdateHealth
local function XPerl_Player_UpdateHealth(self)
	local playerhealth = UnitHealth("player")
	local playerhealthmax = UnitHealthMax("player")

	if (playerhealth > playerhealthmax) then
		-- New glitch with 1.12.1
		if (UnitIsDeadOrGhost("player")) then
			playerhealth = 0
		else
			playerhealth = playerhealthmax
		end
	end

	XPerl_SetHealthBar(self.statsFrame.healthBar, playerhealth, playerhealthmax, conf.HealerModePlayer, conf.HealerModePlayerType)

	local greyMsg
	if (UnitIsDead("player")) then
		if (XPerl_Player_Feigning()) then
			greyMsg = XPERL_LOC_FEIGNDEATH
		else
			greyMsg = XPERL_LOC_DEAD
			self.statsFrame.manaBar.text:Hide()
		end

	elseif (UnitIsGhost("player")) then
		greyMsg = XPERL_LOC_GHOST
		self.statsFrame.manaBar.text:Hide()

	elseif (UnitIsAFK("player")) then
		greyMsg = CHAT_MSG_AFK

	elseif (UnitIsAFK("player")) then
		greyMsg = CHAT_MSG_DND
	end

	if (greyMsg) then
		if (conf.ShowPlayerPercent == 1) then
			self.statsFrame.healthBar.percent:SetText(greyMsg)
			self.statsFrame.healthBar.percent:Show()
		else
			self.statsFrame.healthBar.text:SetText(greyMsg)
			self.statsFrame.healthBar.text:Show()
		end

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

	XPerl_PlayerStatus_OnUpdate(playerhealth, playerhealthmax)
end

-- XPerl_Player_UpdateLevel
local function XPerl_Player_UpdateLevel(self)
	self.levelFrame.text:SetText(UnitLevel("player"))
end

-- XPerl_PlayerStatus_OnUpdate
function XPerl_PlayerStatus_OnUpdate(val, max)
	if (conf.FullScreenStatus == 1) then
		local testLow = conf.FullScreenStatusWarn / 100
		local testHigh = conf.FullScreenStatusOK / 100

		if (val and max) then
			local test = val / max

			if ( test <= testLow and not XPerl_LowHealthFrame.flashing and not UnitIsDeadOrGhost("player")) then
				UIFrameFlash(XPerl_LowHealthFrame, 0.5, 0.5, 100)
				XPerl_LowHealthFrame.flashing = 1
			elseif ( (test >= testHigh and XPerl_LowHealthFrame.flashing) or UnitIsDeadOrGhost("player") ) then
				if (XPerl_LowHealthFrame.flashMode == "IN") then
					XPerl_LowHealthFrame.flashDuration = (XPerl_LowHealthFrame.flashTimer or 0) + 0
				else
					XPerl_LowHealthFrame.flashDuration = (XPerl_LowHealthFrame.flashTimer or 0) + 1
				end
				XPerl_LowHealthFrame.flashing = nil
			end
		else
			if (isOutOfControl and not XPerl_OutOfControlFrame.flashing and not UnitOnTaxi("player")) then
				UIFrameFlash(XPerl_OutOfControlFrame, 0.5, 0.5, 100)
				XPerl_OutOfControlFrame.flashing = 1
			elseif (not isOutOfControl and XPerl_OutOfControlFrame.flashing ) then
				if (XPerl_OutOfControlFrame.flashMode == "IN") then
					XPerl_OutOfControlFrame.flashDuration = (XPerl_OutOfControlFrame.flashTimer or 0) + 0
				else
					XPerl_OutOfControlFrame.flashDuration = (XPerl_OutOfControlFrame.flashTimer or 0) + 1
				end
				XPerl_OutOfControlFrame.flashing = nil
			end
		end
	else
		if (XPerl_LowHealthFrame.flashing) then
			XPerl_LowHealthFrame:Hide()
			XPerl_LowHealthFrame.flashing = nil
		end
		if (XPerl_OutOfControlFrame.flashing) then
			XPerl_OutOfControlFrame:Hide()
			XPerl_OutOfControlFrame.flashing = nil
		end
	end
end

-- XPerl_Player_OnUpdate
function XPerl_Player_OnUpdate(self)
	CombatFeedback_OnUpdate(arg1)
	if (self.PlayerFlash) then
		XPerl_Player_CombatFlash(self, arg1, false)
	end
end

-- XPerl_Player_UpdateBuffs
local function XPerl_Player_UpdateBuffs(self)
	XPerl_CheckDebuffs(self, "player")
	XPerl_Player_TickerShowHide(self)

	if (DruidBarKey or SimpleDruidBar) then
		-- For DruidBar addon, we update the mana bar on shapeshift
		local _, engClass = UnitClass("player")
		if (engClass == "DRUID") then
			XPerl_Player_UpdateMana(self)
		end
	end

	if (conf.FullScreenStatus == 1) then
		if (isOutOfControl and not UnitOnTaxi("player")) then
			XPerl_PlayerStatus_OnUpdate()
		end
	end
end

-- XPerl_Player_UpdateDisplay
function XPerl_Player_UpdateDisplay (self)
	XPerl_Player_UpdateXP(self)
	XPerl_Player_UpdateRep(self)
	XPerl_Player_UpdateManaType(self)
	XPerl_Player_UpdateLevel(self)
	XPerl_Player_UpdateName(self)
	XPerl_Player_UpdatePVP(self)
	XPerl_Player_UpdateCombat(self)
	XPerl_Player_UpdateLeader(self)
	XPerl_Player_UpdateMasterLooter(self)
	XPerl_Player_UpdateMana(self)
	XPerl_Player_UpdateHealth(self)
	XPerl_Player_UpdateBuffs(self)
end

-- EVENTS AND STUFF

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

-- PLAYER_ENTERING_WORLD
function XPerl_Player_Events:PLAYER_ENTERING_WORLD()
	XPerl_Player_UpdateDisplay(self)
end

-- UNIT_COMBAT
function XPerl_Player_Events:UNIT_COMBAT()
 	if (arg1 == "player") then
		if (conf.CombatHitIndicator == 1 and conf.ShowPlayerPortrait == 1) then
			CombatFeedback_OnCombatEvent(arg2, arg3, arg4, arg5)
		end

		if (arg2 == "HEAL") then
			XPerl_Player_CombatFlash(self, elapsed, true, true)
		elseif (arg4 and arg4 > 0) then
			XPerl_Player_CombatFlash(self, elapsed, true)
		end
	end
end

-- UNIT_SPELLMISS
function XPerl_Player_Events:UNIT_SPELLMISS()
	if (arg1 == "player") then
		if (conf.CombatHitIndicator == 1 and conf.ShowPlayerPortrait == 1) then
			CombatFeedback_OnSpellMissEvent(arg2)
		end
	end
end

-- UNIT_MODEL_CHANGED
function XPerl_Player_Events:UNIT_MODEL_CHANGED()
	if (arg1 == "player") then
		XPerl_Player_UpdatePortrait(self)
	end
end
--XPerl_Player_Events.UNIT_PORTRAIT_UPDATE = XPerl_Player_Events.UNIT_MODEL_CHANGED

-- VARIABLES_LOADED
function XPerl_Player_Events:VARIABLES_LOADED()
	self.doubleCheckAFK = 2		-- Check during 2nd UPDATE_FACTION, which are the last guarenteed events to come after logging in
	XPerl_Player_UpdatePortrait(self)
	self:UnregisterEvent(event)
end

-- PARTY_LOOT_METHOD_CHANGED
function XPerl_Player_Events:PARTY_LOOT_METHOD_CHANGED()
	XPerl_Player_UpdateLeader(self)
	XPerl_Player_UpdateMasterLooter(self)
end
XPerl_Player_Events.PARTY_MEMBERS_CHANGED = XPerl_Player_Events.PARTY_LOOT_METHOD_CHANGED
XPerl_Player_Events.PARTY_LEADER_CHANGED  = XPerl_Player_Events.PARTY_LOOT_METHOD_CHANGED

function XPerl_Player_Events:RAID_ROSTER_UPDATE()
	XPerl_Player_UpdateLeader(self)
	XPerl_Player_UpdateMasterLooter(self)
end

-- UNIT_HEALTH, UNIT_MAXHEALTH
function XPerl_Player_Events:UNIT_HEALTH()
	XPerl_Player_UpdateHealth(self)
end
XPerl_Player_Events.UNIT_MAXHEALTH = XPerl_Player_Events.UNIT_HEALTH
XPerl_Player_Events.PLAYER_DEAD    = XPerl_Player_Events.UNIT_HEALTH

-- UNIT_MANA, UNIT_MAXMANA, UNIT_RAGE, UNIT_MAXRAGE, UNIT_ENERGY
-- UNIT_MAXENERGY
function XPerl_Player_Events:UNIT_MANA()
	XPerl_Player_UpdateMana(self)
end
XPerl_Player_Events.UNIT_MAXMANA		= XPerl_Player_Events.UNIT_MANA
XPerl_Player_Events.UNIT_RAGE		= XPerl_Player_Events.UNIT_MANA
XPerl_Player_Events.UNIT_MAXRAGE         = XPerl_Player_Events.UNIT_MANA

function XPerl_Player_Events:UNIT_ENERGY()
	XPerl_Player_UpdateMana(self)

	local e = UnitMana("player")
	local m = UnitManaMax("player")
	if (e == self.EnergyLast + 20) then
		XPerl_Player.EnergyTime = GetTime()
	end
	self.EnergyLast = e

	XPerl_Player_TickerShowHide(self)
end
XPerl_Player_Events.UNIT_MAXENERGY       = XPerl_Player_Events.UNIT_ENERGY

-- UNIT_DISPLAYPOWER
function XPerl_Player_Events:UNIT_DISPLAYPOWER()
	XPerl_Player_UpdateManaType(self)
	XPerl_Player_UpdateMana(self)
	XPerl_Player_TickerShowHide(self)
end

-- UNIT_NAME_UPDATE
function XPerl_Player_Events:UNIT_NAME_UPDATE()
	XPerl_Player_UpdateName(self)
end

-- UNIT_LEVEL
function XPerl_Player_Events:UNIT_LEVEL()
	XPerl_Player_UpdateLevel(self)
	XPerl_Player_UpdateXP(self)
end
XPerl_Player_Events.PLAYER_LEVEL_UP = XPerl_Player_Events.UNIT_LEVEL

-- PLAYER_XP_UPDATE
function XPerl_Player_Events:PLAYER_XP_UPDATE()
	XPerl_Player_UpdateXP(self)
end

-- UPDATE_FACTION
function XPerl_Player_Events:UPDATE_FACTION()
	XPerl_Player_UpdateRep(self)

	if (self.doubleCheckAFK) then
		self.doubleCheckAFK = self.doubleCheckAFK - 1
		if (self.doubleCheckAFK <= 0) then
			XPerl_Player_UpdateHealth(self)
			self.doubleCheckAFK = nil
		end
	end
end

-- UNIT_FACTION
function XPerl_Player_Events:UNIT_FACTION()
	XPerl_Player_UpdatePVP(self)
end
XPerl_Player_Events.UNIT_FLAGS = XPerl_Player_Events.UNIT_FACTION

function XPerl_Player_Events:PLAYER_FLAGS_CHANGED(unit)
	XPerl_Player_UpdateHealth(self)
end

-- PLAYER_ENTER_COMBAT, PLAYER_LEAVE_COMBAT
function XPerl_Player_Events:PLAYER_ENTER_COMBAT()
	XPerl_Player_UpdateCombat(self)
end
XPerl_Player_Events.PLAYER_LEAVE_COMBAT = XPerl_Player_Events.PLAYER_ENTER_COMBAT

-- PLAYER_REGEN_ENABLED, PLAYER_REGEN_DISABLED
function XPerl_Player_Events:PLAYER_REGEN_ENABLED()
	XPerl_Player_UpdateCombat(self)
end
XPerl_Player_Events.PLAYER_REGEN_DISABLED = XPerl_Player_Events.PLAYER_REGEN_ENABLED
XPerl_Player_Events.PLAYER_UPDATE_RESTING = XPerl_Player_Events.PLAYER_REGEN_ENABLED

function XPerl_Player_Events:PLAYER_AURAS_CHANGED()
	XPerl_Player_UpdateBuffs(self)
end

-- PLAYER_CONTROL_LOST
function XPerl_Player_Events:PLAYER_CONTROL_LOST()
	if (conf.FullScreenStatus == 1 and not UnitOnTaxi("player")) then
		isOutOfControl = 1
	end
end

-- PLAYER_CONTROL_GAINED
function XPerl_Player_Events:PLAYER_CONTROL_GAINED()
	isOutOfControl = nil
	if (conf.FullScreenStatus == 1) then
		XPerl_PlayerStatus_OnUpdate()
	end
end

-- Moving stuff
function XPerl_Player_GetGap()
	if (XPerl_Target) then
		local playerLeft = XPerl_Player.statsFrame:GetRight() * XPerl_Player:GetEffectiveScale()
		local targetLeft = XPerl_Target:GetLeft() * XPerl_Target:GetEffectiveScale()
		local a = targetLeft - playerLeft
		return floor(floor((a + 0.01) * 100) / 100 + 4)
	end
	return 0
end

-- XPerl_Player_SetGap
function XPerl_Player_SetGap(newGap)
	if (not XPerl_Player or not XPerl_Target) then
		return
	end

	if (type(newGap) == "number") then
		newGap = newGap - 4

		local top = XPerl_Target:GetTop()
		local left = ((XPerl_Player.statsFrame:GetRight() * XPerl_Player:GetEffectiveScale()) + newGap) / XPerl_Target:GetEffectiveScale()

		XPerl_Target:ClearAllPoints()
		XPerl_Target:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", left, top)

		XPerl_Target:SetUserPlaced(true)

		if (XPerl_TargetTarget) then
			top = XPerl_TargetTarget:GetTop()
			left = ((XPerl_Target:GetRight() * XPerl_Target:GetEffectiveScale()) + newGap) / XPerl_TargetTarget:GetEffectiveScale()

			-- Can't use the CastClickOverlay for GetRight() as wow doesn't update anchors until it renders the frame, anchors
			-- are always 1 frame behind. Usually you won't notice, but when moving frames in this manner, it was ugly.
			-- So, we adjust right a little.
			if (XPerl_Target.levelFrame:IsShown()) then
				left = left + XPerl_Target.levelFrame:GetWidth()
			end

			XPerl_TargetTarget:ClearAllPoints()
			XPerl_TargetTarget:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", left, top)

			if (XPerl_TargetTargetTarget) then
				top = XPerl_TargetTargetTarget:GetTop()
				left = (XPerl_TargetTarget:GetRight() * XPerl_TargetTarget:GetEffectiveScale()) + newGap
				if (conf.ShowTargetTargetPercent == 0) then
					left = left - 20
				end
				left = left / XPerl_TargetTargetTarget:GetEffectiveScale()

				XPerl_TargetTargetTarget:ClearAllPoints()
				XPerl_TargetTargetTarget:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", left, top)

				XPerl_TargetTargetTarget:SetUserPlaced(true)
			end

			XPerl_TargetTarget:SetUserPlaced(true)
		end
	end
end

-- XPerl_Player_AlignTop
function XPerl_Player_AlignTop()
	if (not XPerl_Player or not XPerl_Target) then
		return
	end

	local playerLeft = XPerl_Player:GetLeft()
	local targetLeft = XPerl_Target:GetLeft()
	local playerTop = XPerl_Player:GetTop()
	local top = playerTop * XPerl_Player:GetEffectiveScale()
	local newTop

	if (playerLeft == nil) then
		playerLeft = 5
	end
	if (targetLeft == nil) then
		targetLeft = 220
	end

	-- We set this for 1 reason, so that all the related frames scale in the same direction should the user do that...
	XPerl_Player:ClearAllPoints()
	XPerl_Player:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", playerLeft, playerTop)

	XPerl_Player:SetUserPlaced(true)

	XPerl_Target:ClearAllPoints()
	newTop = top / XPerl_Target:GetEffectiveScale()
	XPerl_Target:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", targetLeft, newTop)

	XPerl_Target:SetUserPlaced(true)

	if (XPerl_TargetTarget) then
		local targettargetLeft = XPerl_TargetTarget:GetLeft()

		if (targettargetLeft == nil) then
			targettargetLeft = targetLeft + 200
		end

		XPerl_TargetTarget:ClearAllPoints()
		newTop = top / XPerl_TargetTarget:GetEffectiveScale()
		XPerl_TargetTarget:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", targettargetLeft, newTop)
		XPerl_TargetTarget:SetUserPlaced(true)

		if (XPerl_TargetTargetTarget) then
			local targettargettargetLeft = XPerl_TargetTargetTarget:GetLeft()
			if (targettargettargetLeft == nil) then
				targettargettargetLeft = targettargetLeft + 200
			end

			XPerl_TargetTargetTarget:ClearAllPoints()
			newTop = top / XPerl_TargetTargetTarget:GetEffectiveScale()
			XPerl_TargetTargetTarget:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", targettargettargetLeft, newTop)
			XPerl_TargetTargetTarget:SetUserPlaced(true)
		end
	end
end

-- XPerl_Player_Energy_TickWatch
function XPerl_Player_Energy_OnUpdate(self)

	local time = GetTime()
	local temp = time - XPerl_Player.EnergyTime
	local remainder = mod (temp, 2)

	self:SetValue(remainder)

	sparkPosition = self:GetWidth() * (remainder / 2)

	self.spark:SetPoint("CENTER", self, "LEFT", sparkPosition, 0)
end

-- XPerl_Player_TickerShowHide
function XPerl_Player_TickerShowHide(self)
       	local e = UnitMana("player")
       	local m = UnitManaMax("player")
       	if (self.EnergyEnabled and (e < m or UnitAffectingCombat("player") or IsStealthed()) and not UnitIsDeadOrGhost("player") and conf.EnergyTicker == 1) then
       		self.statsFrame.energyTicker:Show()
       	else
       		self.statsFrame.energyTicker:Hide()
       	end
end

-- XPerl_Player_Set_Bits()
function XPerl_Player_Set_Bits(self)
	if (conf.ShowPlayerPortrait==0) then
		self.portraitFrame:Hide()
		self.portraitFrame:SetWidth(3)
	else
		self.portraitFrame:Show()
		self.portraitFrame:SetWidth(60)
		XPerl_Player_UpdatePortrait(self)
	end

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

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

	if (conf.ShowPlayerValues == 0) then
		self.statsFrame.healthBar.text:Hide()
		self.statsFrame.manaBar.text:Hide()
		self.statsFrame.xpBar.text:Hide()
	else
		self.statsFrame.healthBar.text:Show()
		self.statsFrame.manaBar.text:Show()
		self.statsFrame.xpBar.text:Show()
	end

	if (conf.ShowPlayerClassIcon == 0) then
		self.classFrame:Hide()
	else
		self.classFrame:Show()
	end

	if (conf.ShowPlayerPVPRank==0) then
		self.nameFrame.pvpRankIcon:Hide()
	else
		self.nameFrame.pvpRankIcon:Show()
	end

	local h = 40 + (((self.statsFrame.druidBar:IsShown() or 0) + conf.ShowPlayerRepBar + conf.ShowPlayerXPBar) * 10)
	self.statsFrame:SetHeight(h)

	if (conf.ShowPlayerRepBar == 0) then
		self.statsFrame.repBar:Hide()
	else
		self.statsFrame.repBar:Show()
	end

	if (conf.ShowPlayerXPBar == 0) then
		self.statsFrame.xpBar:Hide()
		self.statsFrame.xpRestBar:Hide()
	else
		self.statsFrame.xpBar:Show()
		self.statsFrame.xpRestBar:Show()
	end

	self:SetWidth(conf.ShowPlayerPortrait * 60 + 158)
	self:SetScale(conf.Scale_PlayerFrame)

	self:SetAlpha(conf.Transparency)

	XPerl_StatsFrameSetup(self, {"druidBar", "xpBar", "repBar"})

	XPerl_Player_UpdateDisplay(self)
end
