aUF = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceHook-2.1", "AceDB-2.0", "AceConsole-2.0", "FuBarPlugin-2.0")
aUF.Layouts = {}
aUF.indexLayouts = {}
setmetatable(aUF.Layouts, { __newindex = function(self,k,v)
	if v == nil then
	else
		tinsert(aUF.indexLayouts,k)
	end
	rawset(self, k, v)
end })	

-----------------------------------------------------------------------
-- Locals
-----------------------------------------------------------------------

local _G = getfenv(0)
local print = function(msg) if msg then DEFAULT_CHAT_FRAME:AddMessage(msg) end end
local L = AceLibrary("AceLocale-2.2"):new("ag_UnitFrames")
local tablet = AceLibrary("Tablet-2.0")
local events,coreEvents = {}, {}

------------
-- SYSTEM --
------------

aUF.hasIcon = "Interface\\PVPFrame\\\PVP-ArenaPoints-Icon"
aUF.defaultPosition = "RIGHT"
aUF.hideWithoutStandby = true
aUF.independentProfile = true
aUF.hasNoColor = true
aUF.cannotDetachTooltip = true

function aUF:OnInitialize()
	local revision = tonumber(("$Revision: 30719 $"):sub(12, -3)) or 1
	if not self.version then self.version = GetAddOnMetadata("ag_UnitFrames", "Version") end
	self.version = self.version .. "." .. revision
	self.revision = revision	
	
	_G.AG_UNITFRAMES_REVISION = aUF.revision
	_G.AG_UNITFRAMES_VERSION = aUF.version

	self.version = tostring(self.version) .. " |cffff8888r" .. tostring(self.revision) .. "|r"
	
	self.dewdrop = AceLibrary("Dewdrop-2.0")
	self:RegisterDB("aUFDB")
	self:RegisterDefaults('profile', aUF_DEFAULT_OPTIONS)

	-- Needed to create the AceOptions table
	self.wowClasses = {"player","pet","party","partypet","target","targettarget","targettargettarget","raid","focus","focustarget"}
	self.subgroups = {}
	
	self.mainMenu = aUF:CreateMenu()
	self:RegisterChatCommand({ "/aguf", "/ag_unitframes" }, self.mainMenu )
	self.OnMenuRequest = self.mainMenu	
end

function aUF:OnEnable(firstEnable)
	self.units = {}
	self.feedback = {}
	self.HelperFunctions = {}
	self.auraUpdatePool = {}

	self:SecureHook("SecurePartyHeader_Update","HeaderUpdate")
	self:SecureHook("SecureRaidGroupHeader_Update","HeaderUpdate")
	aUF:ScheduleRepeatingEvent("agUF_auraPoolSchedule",self.AuraPool, 0.05, self)
	
	if firstEnable then
		self:SetupVariables()

		aUF:CreateUnit("player","Player")
		aUF:CreateUnit("pet","Pet")
		aUF:CreateUnit("target","Combo")
		aUF:CreateUnit("targettarget","Metro")
		aUF:CreateUnit("targettargettarget","Metro")
		aUF:CreateUnit("focus","Focus")
		aUF:CreateUnit("focustarget","Metro")
		
		for k,v in pairs(self.db.profile.subgroups) do
			if v.Exists == true and not aUF.subgroups[k] then
				aUF:CreateSubgroup(k,"raid","Vanilla",self.db.profile.subgroups[k])
			end
		end
	end
	aUF:CreateSubgroup("party","party","Vanilla",self.db.profile.partygroup)
	aUF:CreateSubgroup("partypet","partypet","Vanilla",self.db.profile.partypetgroup)
	
	self:UpdateBlizzVisibility()
	self:RegisterEvents()
end

local function GetOnOffText(var)
	return var and "|cff00ff00"..L["On"].."|r" or "|cffff0000"..L["Off"].."|r"
end

function aUF:OnTooltipUpdate()
	local cat = tablet:AddCategory("columns", 2)
	cat:AddLine("text", L["lock"], "text2", GetOnOffText(aUF.db.profile.Locked))

	tablet:SetHint(L["|cffeda55fClick|r to toggle frame lock."])
end

function aUF:OnClick()
	self.db.profile.Locked = not self.db.profile.Locked
	self:UpdateDisplay()
end

function aUF:HeaderUpdate(frame)
	if (frame.object and frame.object.UpdateTitle) then
		frame.object:UpdateTitle()
	end
end

function aUF:OnProfileEnable()	
	for k,v in pairs(self.db.profile.subgroups) do
		self.subgroups[k].database = v
	end
	self:CallUnitMethods("Reset")
end

function aUF:SetRaidset(option)
	set = tonumber(self.db.profile.CurrentRaidSet)
	if not (InCombatLockdown()) and set then
		if option == "prev" then
			if set <= 1 then
				self.db.profile.CurrentRaidSet = "10"
			else
				self.db.profile.CurrentRaidSet = tostring(set - 1)
			end
		elseif option == "next" then
			if tonumber(set) >= 10 then
				self.db.profile.CurrentRaidSet = "1"
			else
				self.db.profile.CurrentRaidSet = tostring(set + 1)
			end
		else
			self.db.profile.CurrentRaidSet = tostring(option)
		end
		for k,v in pairs(self.subgroups) do
			v:SetVisibility()
		end
		self:Print(string.format("Raidset %s activated.",self.db.profile.CurrentRaidSet))
	elseif set then
		self:Print("You cannot change the raid set while in combat.")
	end
end
--------------------------------------
-- OBJECT CREATION/METHOD EXECUTION --
--------------------------------------

function aUF:CreateUnit(unit,class,name,unitdb)
	local frame = CreateFrame("Button", "aUF"..(name or unit),UIParent, (class == "Metro" and "AGUnitMetroTemplate") or "AGUnitTemplate")
	self.units[frame:GetName()] = self.classes["aUFunit"..class or ""]:new(frame,unit,unitdb)
	return self.units[frame:GetName()]
end

function aUF:CreateSubgroup(name,type,class,groupdb,unitdb,reset)
	aUF.subgroups[name] = aUF.classes.aUFgroup:new(name,type,class,groupdb,unitdb,reset)
	return aUF.subgroups[name]
end

function aUF:CreateNewGroup()
	local i = 1
	local k = "group"..i
	while (self.db.profile.subgroups["group"..i] and self.db.profile.subgroups["group"..i].Exists == true) do
		i = i + 1
		k = "group"..i

	end
	aUF:CreateSubgroup(k,"raid","Vanilla",aUF.db.profile.subgroups[k],nil,true)

	return k
end

function aUF:FindObjects(sortBy, object)
	local table = {}
	if not object then object = "units" end
	if self[object] then
		for _,v in pairs(self[object]) do
			if v[sortBy] then
				if not table[v[sortBy]] then
					table[v[sortBy]] = {}
				end
				tinsert(table[v[sortBy]],v)
			end
		end
	end
	return table
end

function aUF:CallUnitMethods(func,arg,find,type,object)
	if not func then return end
	if find and type then
		if aUF:FindObjects(type)[find] then
			for _,unitObject in pairs(aUF:FindObjects(type,object)[find]) do
				if unitObject[func] and unitObject.unit then
					unitObject[func](unitObject,arg)
				end
			end
		end
	else
		if not object then object = "units" end
		if self[object] then
			for _,unitObject in pairs(self[object]) do
				if unitObject[func] and unitObject.unit then
					unitObject[func](unitObject,arg)
				end
			end
		end
	end
end

-----------------------
-- EVENT REGISTERING --
-----------------------

function aUF:RegisterEvents()
	self:aUFRegisterEvent("RAID_ROSTER_UPDATE")
	self:aUFRegisterEvent("PLAYER_REGEN_ENABLED")
end

function aUF:RAID_ROSTER_UPDATE()
	local inRaid = self.inRaid
	if GetNumRaidMembers()>0 then
		self.inRaid = true
	else
		self.inRaid = false
	end

	if inRaid ~= self.inRaid then
		if InCombatLockdown() then
			self.raidDirty = true
		elseif self.subgroups then
			for k,v in pairs(self.subgroups) do
				v:SetVisibility()
			end
		end
	end
end

function aUF:PLAYER_REGEN_ENABLED()
	if self.raidDirty and self.subgroups then
		for k,v in pairs(self.subgroups) do
			v:SetVisibility()
		end
		self.raidDirty = nil
	end
end

------------------
-- EVENT SYSTEM --
------------------

function aUF:aUFRegisterEvent(event)
	if not coreEvents[event] then
		coreEvents[event] = {}
	end

	coreEvents[event] = method or event

	self["pool"..event] = function(self,unit) self:TriggerEvent(event,unit) end
	self:RegisterEvent(event,"pool"..event)
end

function aUF:aUFUnregisterEvent(event,method)
	coreEvents[event] = nil

	if events[event] then
		if next(events[event]) == nil then
			if self:IsEventRegistered(event) then
				self:UnregisterEvent(event)
			end
		end
	end
end

function aUF:ObjectRegisterEvent(object,event,method)
	if not events[event] then
		events[event] = {}
	end

	if not events[event][object] then
		events[event][object] = method or event
	elseif not (type(events[event][object]) == "table") then
		local oldEvent = events[event][object]
		events[event][object] = {}
		events[event][object][oldEvent] = true
		events[event][object][method or event] = true
	else
		events[event][object][method or event] = true
	end

	self["pool"..event] = function(self,unit,...) self:TriggerEvent(event,unit,...) end
	self:RegisterEvent(event,"pool"..event)
end

function aUF:ObjectUnregisterEvent(object,event,method)
	if events[event] and events[event][object] then
		if method and type(events[event][object]) == "table" then
			events[event][object][method] = nil
			local i = 0
			for k,v in pairs(events[event][object]) do
				i = i + 1
			end
			if i == 0 then
				events[event][object] = nil
			end
		else
			events[event][object] = nil
		end

		if next(events[event]) == nil and not coreEvents[event] then
			if self:IsEventRegistered(event) then
				self:UnregisterEvent(event)
			end
		end
	end
end

function aUF:TriggerEvent(event,unit,...)
	if coreEvents[event] and self[coreEvents[event]] then
		self[coreEvents[event]](self, ...)
	end
	if not events[event] then return end
	if unit and (self.unitid[unit]) then
		for object,_ in pairs(self.unitid[unit]) do
			local method = events[event][object]
				if method then
				if type(method) == "string" then
					object[method](object,unit,event,...)
				elseif type(method) == "table" then
					for k,v in pairs(method) do
						if type(k) == "string" then
							object[k](object,unit,event,...)
						else
							k(...)
						end
					end
				else
					method(...)
				end
			end
		end
	else
		for object,method in pairs(events[event]) do
			if method then
				if type(method) == "string" then
					object[method](object,nil,event,...)
				elseif type(method) == "table" then
					for k,v in pairs(method) do
						if type(k) == "string" then
							object[k](object,unit,event,...)
						else
							k(...)
						end
					end
				else
					method(...)
				end
			end
		end
	end
end

-------------------
-- UNIT EVENTS --
-------------------

function aUF:AuraPool()
	local n = 0
	for k,v in pairs(self.auraUpdatePool) do
		if n < 5 then
			k:UpdateAuras(nil,nil,true)
			self.auraUpdatePool[k] = nil
			n = n + 1
		else
			break
		end
	end
end

function aUF:FeedbackUpdate()
	local maxalpha = 0.6
	local found
	for objectName,v in pairs(self.feedback) do
		found = true
		local unitOjbect = aUF.units[objectName]
		if unitOjbect then
			local elapsedTime = GetTime() - unitOjbect.feedbackStartTime
			if ( elapsedTime < COMBATFEEDBACK_FADEINTIME ) then
				local alpha = maxalpha*(elapsedTime / COMBATFEEDBACK_FADEINTIME)
				unitOjbect.HitIndicator:SetAlpha(alpha)
			elseif ( elapsedTime < (COMBATFEEDBACK_FADEINTIME + COMBATFEEDBACK_HOLDTIME) ) then
				unitOjbect.HitIndicator:SetAlpha(maxalpha)
			elseif ( elapsedTime < (COMBATFEEDBACK_FADEINTIME + COMBATFEEDBACK_HOLDTIME + COMBATFEEDBACK_FADEOUTTIME) ) then
				local alpha = maxalpha - maxalpha*((elapsedTime - COMBATFEEDBACK_HOLDTIME - COMBATFEEDBACK_FADEINTIME) / COMBATFEEDBACK_FADEOUTTIME)
				unitOjbect.HitIndicator:SetAlpha(alpha)
			else
				unitOjbect.HitIndicator:Hide()
				aUF.feedback[objectName] = nil
			end
		else
			aUF.feedback[objectName] = nil
		end
	end
	if not found then
		self:CancelScheduledEvent("agUF_CombatSchedule")
	end
end

-----------
-- Units --
-----------

function aUF:RegisterUnit(object, unit)
	-- prepare unitid table
	if not self.unitid then
		self.unitid = {}
	end

	-- prepare unitid[unit] storage
	if (not self.unitid[unit]) then
		self.unitid[unit] = {}
	end

	-- remove current reference
	aUF:UnregisterUnit(object)

	-- register new unit
	self.unitid[unit][object] = true
end

function aUF:UnregisterUnit(object)
	if type(self.unitid) ~= "table" then return end
	for id,objs in pairs(self.unitid) do
		if (objs[object]) then
			objs[object] = nil
		end
	end
end

-----------
-- HOOKS --
-----------

aUF.hooks = {}

function aUF.hooks.hookShowHide(frame)
	local show, hide = frame.Show, frame.Hide
	frame.Show = function(self)
		if (not self.isVisibleFlag) then
			show(self)
			self.isVisibleFlag = true
		end
	end
	frame.Hide = function(self)
		if (self.isVisibleFlag) then
			hide(self)
			self.isVisibleFlag = false
		end
	end
	frame.WillHide = function(self)
		self.doShow = false
	end
	frame.WillShow = function(self)
		self.doShow = true
	end
	frame.DoShowHide = function(self)
		if (self.doShow) then self:Show() else self:Hide() end
	end

	frame:Show()
end

function aUF.hooks.hookSetTexture(frame)
	local settexture = frame.SetTexture
	frame.SetTexture = function(self, texture)
		if (self.lasttexture ~= texture) then
			self.lasttexture = texture
			settexture(self, texture)
		end
	end
end

--------------
-- WATCHDOG --
--------------

local work,helpers = {},{}

function aUF:Parse(format)
	if not format then
		return nil
	end

	local formatArgs, formatEvents, formatString = {},{}

	for s,data,e in format:gmatch("()(%b[])()") do
		local tag = data:sub(2, -2)
		local func,event

		if type(aUF.UnitInformation[tag]) == "table" then
			func = aUF.UnitInformation[tag].func
			event = aUF.UnitInformation[tag].event
		else
			func = aUF.UnitInformation[tag]
		end

		if func then
			table.insert(formatArgs, func)
			if event then
				if type(event) == "table" then
					for k,v in pairs(event) do
						table.insert(formatEvents, v)
					end
				elseif type(event) == "string" then
					table.insert(formatEvents, event)
				end
			end
		else
			error(string.format("\"%s\" is not a valid format tag.", data))
		end
	end

	formatString = format:gsub("%%", "%%%%")
	formatString = formatString:gsub("%b[]", "%%s")

	-- Lets avoid unpacking extra results
	local num = table.getn(formatArgs)
	local tmp = work[num]
	if not tmp then
		tmp = {}
		work[num] = tmp
	end

	if num == 0 then
		return { func = function(unit, fontstring)
			fontstring:SetText(formatString)
		end, events = nil }
	else
		return {func = function(unit, fontstring)
			for i,func in ipairs(formatArgs) do
				work[i] = func(unit)
			end
			fontstring:SetText(string.format(formatString, unpack(work)))
		end, events = formatEvents }
	end
end

function aUF:GetTagFunction(tag)
	-- Check if this is just a unit tag
	if aUF.UnitInformation[tag] then return aUF.UnitInformation[tag] end

	local s,e,tag,args = tag:find("^(%a+)%s+(.*)$")
	if not tag then
		-- Not a pattern we can recognize
		return nil
	end

	-- Bind the unit function to a local for closure purposes
	local func,event
	if type(aUF.UnitInformation[tag]) == "table" then
		func = aUF.UnitInformation[tag].func
		event = aUF.UnitInformation[tag].event
	else
		func = aUF.UnitInformation[tag]
	end

	if not func then
		return nil
	end
	local _,_,width = args:find("^(%d+)$")
	if width then
		local id = string.format("%s-%d", tag, width)
		local hFunc = helpers[id]
		if not hFunc then
			hFunc = function(unit)
				return func(unit):sub(1, width)
			end
			helpers[id] = hFunc
		end
		return hFunc
	end

	local _,_,oc,ec = args:find("^(.)(.)$")
	if oc then
		local id = string.format("%s-%s%s", tag, oc, ec)
		local hFunc = helpers[id]
		if not hFunc then
			hFunc = function(unit)
				local t = func(unit)
				if t ~= "" then return
					string.format("%s%s%s",oc,t,ec)
				else
					return t
				end
			end
			helpers[id] = hFunc
		end
		return hFunc
	end
end

-- Core watchdog tags

function aUF:Tag_agmana(unit,flag)
	local currValue,maxValue = UnitMana(unit),UnitManaMax(unit)
	if maxValue == 0 then
		return ""
	end
	local perc = currValue/maxValue * 100
	local manaDiff = maxValue - currValue
	local text = ""

	if ( not UnitExists(unit) or UnitIsDead(unit) or UnitIsGhost(unit) or not UnitIsConnected(unit) ) then
		return ""
	end

	if currValue > maxValue then
		maxValue = currValue
	end

	if flag == 1 then
		return string.format("%.0f%%", perc)
	elseif flag == 2 then
		return self:formatLargeValue(currValue).."|cffff7f7f-".. self:formatLargeValue(manaDiff) .."|r"
	elseif flag == 3 then
		return self:formatLargeValue(currValue)
	else
		return self:formatLargeValue(currValue).."/"..self:formatLargeValue(maxValue)
	end

	return text
end

function aUF:Tag_aghp(unit,flag)
	local currValue,maxValue = UnitHealth(unit),UnitHealthMax(unit)
	if maxValue == 0 then
		return ""
	end
	local perc = currValue/maxValue * 100
	local text = ""
	local MHfound = false
	if ( UnitIsDead(unit) ) then
		return L["dead"]
	elseif ( UnitIsGhost(unit) ) then
		return L["ghost"]
	elseif ( not UnitIsConnected(unit) or maxValue == 1 ) then
		return L["disc"]
	end
	if ( not UnitIsFriend("player", unit) ) then
		if (MobHealth3) then
			currValue,maxValue,MHfound = MobHealth3:GetUnitHealth(unit, currValue,maxValue)
		elseif ( MobHealth_GetTargetCurHP and MobHealth_GetTargetMaxHP ) then
			local curr = MobHealth_GetTargetCurHP()
			local max = MobHealth_GetTargetMaxHP()
			if (curr and max) then
				MHfound = true
				currValue = curr
				maxValue = max
			end
		end
	end
	if currValue > maxValue then
		maxValue = currValue
	end

	local hpDiff = maxValue - currValue

	if not flag and MHfound and not UnitIsFriend("player", unit) then
		return self:formatLargeValue(currValue) .." (".. perc .."%)"
	end

	if not (flag == 1) and (MHfound or unit == "pet" or unit == "player" or UnitInParty(unit) or UnitInRaid(unit)) then
		if flag == 2 then
			if hpDiff > 0 then
				return self:formatLargeValue(currValue).."|cffff7f7f-".. self:formatLargeValue(hpDiff) .."|r"
			else
				return self:formatLargeValue(currValue)
			end
		elseif flag == 3 and hpDiff > 0 then
			return "|cffff7f7f-"..self:formatLargeValue(hpDiff).."|r"
		elseif flag == 3 then
			return ""
		elseif flag == 4 then
			return self:formatLargeValue(currValue)
		else
			return self:formatLargeValue(currValue).."/"..self:formatLargeValue(maxValue)
		end
	else
		return string.format("%.0f%%", perc)
	end
	return text
end

---------------
-- UTILITIES --
---------------


function aUF:UnitSuffix(unit,suffix)
	if not suffix then return unit end
	if unit then
		unit = unit..suffix
		if string.find(unit,"pet") then
			unit = gsub(unit, "^([^%d]+)([%d]+)[pP][eE][tT]","%1pet%2")
		end
		return unit
	else
		return nil
	end
end

function aUF:UtilFactionColors(unit)
	local r, g, b = 0,0,0
	local a = 0.5
	if ( UnitPlayerControlled(unit) ) then
		if ( UnitCanAttack(unit, "player") ) then
			if ( not UnitCanAttack("player", unit) ) then
				r = self.ManaColor[0].r
				g = self.ManaColor[0].g
				b = self.ManaColor[0].b
			else
				r = self.ManaColor[1].r
				g = self.ManaColor[1].g
				b = self.ManaColor[1].b
			end
		elseif ( UnitCanAttack("player", unit) ) then
				r = self.ManaColor[3].r
				g = self.ManaColor[3].g
				b = self.ManaColor[3].b
		elseif ( UnitIsPVP(unit) ) then
			r = self.HealthColor.r
			g = self.HealthColor.g
			b = self.HealthColor.b
		else
			r = self.ManaColor[0].r
			g = self.ManaColor[0].g
			b = self.ManaColor[0].b
		end
	elseif ( UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) ) or UnitIsDead(unit) then
		r = 0.5
		g = 0.5
		b = 0.5
	else
		local reaction = UnitReaction(unit, "player")
		if ( reaction ) then
			if reaction == 5 or reaction == 6 or reaction == 7 then
				r = self.HealthColor.r
				g = self.HealthColor.g
				b = self.HealthColor.b
			elseif reaction == 4 then
				r = self.ManaColor[3].r
				g = self.ManaColor[3].g
				b = self.ManaColor[3].b
			elseif reaction == 1 or reaction == 2 or reaction == 3 then
				r = self.ManaColor[1].r
				g = self.ManaColor[1].g
				b = self.ManaColor[1].b
			else
				r = UnitReactionColor[reaction].r
				g = UnitReactionColor[reaction].g
				b = UnitReactionColor[reaction].b
			end
		end
	end
	return {r = r,g = g,b = b}
end

function aUF:GiveHex(r,g,b)
	local r=min(r*255,255)
	local g=min(g*255,255)
	local b=min(b*255,255)
	return string.format("|cff%2x%2x%2x", r, g, b) or ""
end

function aUF:GetRaidColors(class)
	if RAID_CLASS_COLORS[class] then
		local tbl = RAID_CLASS_COLORS[class]
		return string.format("|cff%2x%2x%2x", min(tbl.r*255,255), min(tbl.g*255,255), min(tbl.b*255,255)) or ""
	else
		return "|r"
	end
end

function aUF:formatLargeValue(value)
	if value < 9999 then
		return value
	elseif value < 999999 then
		return string.format("%.1fk", value / 1000)
	else
		return string.format("%.2fm", value / 1000000)
	end
end

function aUF:UnitDebuff(unit,id,filter)
	if not unit then return end
	local _,_,aura, count, t = UnitDebuff(unit,id)

	if filter == 1 then
		local _, eClass = UnitClass("player")
		if ( self.CanDispel[eClass] and self.CanDispel[eClass][t] == true or ( eClass == "PRIEST" and (aura == "Interface\\Icons\\Spell_Holy_AshesToAshes")) ) then
			return aura, count or 0, t
		end
	else
		return aura, count or 0, t
	end
end

function aUF:tonum(val, base)
	return tonumber((val or 0), base) or 0
end

function aUF:round(num)
	return floor(aUF:tonum(num)+.5)
end


-----------------------------
-- DISABLE BLIZZARD FRAMES --
-----------------------------

function aUF:UpdateBlizzVisibility()
	if aUF.db.profile.BlizFramesVisibility.HidePlayerFrame == true then
		aUF:HideBlizzPlayer()
	else
		aUF:ShowBlizzPlayer()
	end
	if aUF.db.profile.BlizFramesVisibility.HidePartyFrame == true then
		aUF:HideBlizzParty()
	else
		aUF:ShowBlizzParty()
	end
	if aUF.db.profile.BlizFramesVisibility.HideTargetFrame == true then
		aUF:HideBlizzTarget()
	else
		aUF:ShowBlizzTarget()
	end
	if aUF.db.profile.BlizzCastbar == true then
		aUF:ShowBlizzCast()
	else
		aUF:HideBlizzCast()
	end
end

function aUF:HideBlizzPlayer()
	PlayerFrame:UnregisterEvent("UNIT_LEVEL")
	PlayerFrame:UnregisterEvent("UNIT_COMBAT")
	PlayerFrame:UnregisterEvent("UNIT_SPELLMISS")
	PlayerFrame:UnregisterEvent("UNIT_PVP_UPDATE")
	PlayerFrame:UnregisterEvent("UNIT_MAXMANA")
	PlayerFrame:UnregisterEvent("PLAYER_ENTER_COMBAT")
	PlayerFrame:UnregisterEvent("PLAYER_LEAVE_COMBAT")
	PlayerFrame:UnregisterEvent("PLAYER_UPDATE_RESTING")
	PlayerFrame:UnregisterEvent("PARTY_MEMBERS_CHANGED")
	PlayerFrame:UnregisterEvent("PARTY_LEADER_CHANGED")
	PlayerFrame:UnregisterEvent("PARTY_LOOT_METHOD_CHANGED")
	PlayerFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
	PlayerFrame:UnregisterEvent("PLAYER_REGEN_DISABLED")
	PlayerFrame:UnregisterEvent("PLAYER_REGEN_ENABLED")
	PlayerFrameHealthBar:UnregisterEvent("UNIT_HEALTH")
	PlayerFrameHealthBar:UnregisterEvent("UNIT_MAXHEALTH")
	PlayerFrameManaBar:UnregisterEvent("UNIT_MANA")
	PlayerFrameManaBar:UnregisterEvent("UNIT_RAGE")
	PlayerFrameManaBar:UnregisterEvent("UNIT_FOCUS")
	PlayerFrameManaBar:UnregisterEvent("UNIT_ENERGY")
	PlayerFrameManaBar:UnregisterEvent("UNIT_HAPPINESS")
	PlayerFrameManaBar:UnregisterEvent("UNIT_MAXMANA")
	PlayerFrameManaBar:UnregisterEvent("UNIT_MAXRAGE")
	PlayerFrameManaBar:UnregisterEvent("UNIT_MAXFOCUS")
	PlayerFrameManaBar:UnregisterEvent("UNIT_MAXENERGY")
	PlayerFrameManaBar:UnregisterEvent("UNIT_MAXHAPPINESS")
	PlayerFrameManaBar:UnregisterEvent("UNIT_DISPLAYPOWER")
	PlayerFrame:UnregisterEvent("UNIT_NAME_UPDATE")
	PlayerFrame:UnregisterEvent("UNIT_PORTRAIT_UPDATE")
	PlayerFrame:UnregisterEvent("UNIT_DISPLAYPOWER")
	PlayerFrame:Hide()
end

function aUF:ShowBlizzPlayer()
	PlayerFrame:RegisterEvent("UNIT_LEVEL")
	PlayerFrame:RegisterEvent("UNIT_COMBAT")
	PlayerFrame:RegisterEvent("UNIT_SPELLMISS")
	PlayerFrame:RegisterEvent("UNIT_PVP_UPDATE")
	PlayerFrame:RegisterEvent("UNIT_MAXMANA")
	PlayerFrame:RegisterEvent("PLAYER_ENTER_COMBAT")
	PlayerFrame:RegisterEvent("PLAYER_LEAVE_COMBAT")
	PlayerFrame:RegisterEvent("PLAYER_UPDATE_RESTING")
	PlayerFrame:RegisterEvent("PARTY_MEMBERS_CHANGED")
	PlayerFrame:RegisterEvent("PARTY_LEADER_CHANGED")
	PlayerFrame:RegisterEvent("PARTY_LOOT_METHOD_CHANGED")
	PlayerFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
	PlayerFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
	PlayerFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
	PlayerFrameHealthBar:RegisterEvent("UNIT_HEALTH")
	PlayerFrameHealthBar:RegisterEvent("UNIT_MAXHEALTH")
	PlayerFrameManaBar:RegisterEvent("UNIT_MANA")
	PlayerFrameManaBar:RegisterEvent("UNIT_RAGE")
	PlayerFrameManaBar:RegisterEvent("UNIT_FOCUS")
	PlayerFrameManaBar:RegisterEvent("UNIT_ENERGY")
	PlayerFrameManaBar:RegisterEvent("UNIT_HAPPINESS")
	PlayerFrameManaBar:RegisterEvent("UNIT_MAXMANA")
	PlayerFrameManaBar:RegisterEvent("UNIT_MAXRAGE")
	PlayerFrameManaBar:RegisterEvent("UNIT_MAXFOCUS")
	PlayerFrameManaBar:RegisterEvent("UNIT_MAXENERGY")
	PlayerFrameManaBar:RegisterEvent("UNIT_MAXHAPPINESS")
	PlayerFrameManaBar:RegisterEvent("UNIT_DISPLAYPOWER")
	PlayerFrame:RegisterEvent("UNIT_NAME_UPDATE")
	PlayerFrame:RegisterEvent("UNIT_PORTRAIT_UPDATE")
	PlayerFrame:RegisterEvent("UNIT_DISPLAYPOWER")
	PlayerFrame:Show()
end

function aUF:HideBlizzParty()
	------ If we use :Hook on on secure code it will get tainted, but that doesn't
	------ matter as we do not care about the blizzard frames (at the moment).
	------ We're just trying to kill it, and a tainted hook will do that fine!
	------ We force a tainted hook by adding true to the argument list of :Hook!
	-- >> We can no longer prevent the default from happening by hooking and not
	-- >> calling the original for secure objects
	if not(self.raidHook) then
		self:Hook("RaidOptionsFrame_UpdatePartyFrames", function() end,true)
		self.raidHook = true
	end
	for i=1,4 do
		local frame = getglobal("PartyMemberFrame"..i)
		frame:UnregisterAllEvents()
		frame:Hide()
	end
end

function aUF:ShowBlizzParty()
	if self.raidHook then
		self:Unhook("RaidOptionsFrame_UpdatePartyFrames")
	end
	self.raidHook = nil
	for i=1,4 do
		local frame = getglobal("PartyMemberFrame"..i)
		frame:RegisterEvent("PARTY_MEMBERS_CHANGED")
		frame:RegisterEvent("PARTY_LEADER_CHANGED")
		frame:RegisterEvent("PARTY_MEMBER_ENABLE")
		frame:RegisterEvent("PARTY_MEMBER_DISABLE")
		frame:RegisterEvent("PARTY_LOOT_METHOD_CHANGED")
		frame:RegisterEvent("UNIT_PVP_UPDATE")
		frame:RegisterEvent("UNIT_AURA")
		frame:RegisterEvent("UNIT_PET")
		frame:RegisterEvent("VARIABLES_LOADED")
		frame:RegisterEvent("UNIT_NAME_UPDATE")
		frame:RegisterEvent("UNIT_PORTRAIT_UPDATE")
		frame:RegisterEvent("UNIT_DISPLAYPOWER")

		UnitFrame_OnEvent("PARTY_MEMBERS_CHANGED")

		PartyMemberFrame_UpdateMember()
	end
end

function aUF:HideBlizzTarget()
	TargetFrame:UnregisterEvent("PLAYER_TARGET_CHANGED")
	TargetFrame:UnregisterEvent("PLAYER_FOCUS_CHANGED")
	TargetFrame:UnregisterEvent("UNIT_HEALTH")
	TargetFrame:UnregisterEvent("UNIT_LEVEL")
	TargetFrame:UnregisterEvent("UNIT_FACTION")
	TargetFrame:UnregisterEvent("UNIT_CLASSIFICATION_CHANGED")
	TargetFrame:UnregisterEvent("UNIT_AURA")
	TargetFrame:UnregisterEvent("PLAYER_FLAGS_CHANGED")
	TargetFrame:UnregisterEvent("PARTY_MEMBERS_CHANGED")
	TargetFrame:Hide()

	ComboFrame:UnregisterEvent("PLAYER_FOCUS_CHANGED")
	ComboFrame:UnregisterEvent("PLAYER_TARGET_CHANGED")
	ComboFrame:UnregisterEvent("PLAYER_COMBO_POINTS")
end

function aUF:ShowBlizzTarget()
	TargetFrame:RegisterEvent("PLAYER_TARGET_CHANGED")
	TargetFrame:RegisterEvent("PLAYER_FOCUS_CHANGED")
	TargetFrame:RegisterEvent("UNIT_HEALTH")
	TargetFrame:RegisterEvent("UNIT_LEVEL")
	TargetFrame:RegisterEvent("UNIT_FACTION")
	TargetFrame:RegisterEvent("UNIT_CLASSIFICATION_CHANGED")
	TargetFrame:RegisterEvent("UNIT_AURA")
	TargetFrame:RegisterEvent("PLAYER_FLAGS_CHANGED")
	TargetFrame:RegisterEvent("PARTY_MEMBERS_CHANGED")
	TargetFrame:Show()

	ComboFrame:RegisterEvent("PLAYER_FOCUS_CHANGED")
	ComboFrame:RegisterEvent("PLAYER_TARGET_CHANGED")
	ComboFrame:RegisterEvent("PLAYER_COMBO_POINTS")
end

function aUF:ShowBlizzCast()
	CastingBarFrame:RegisterEvent("UNIT_SPELLCAST_START")
	CastingBarFrame:RegisterEvent("UNIT_SPELLCAST_STOP")
	CastingBarFrame:RegisterEvent("UNIT_SPELLCAST_FAILED")
	CastingBarFrame:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED")
	CastingBarFrame:RegisterEvent("UNIT_SPELLCAST_DELAYED")
	CastingBarFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START")
	CastingBarFrame:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE")
end

function aUF:HideBlizzCast()
	CastingBarFrame:UnregisterEvent("UNIT_SPELLCAST_START")
	CastingBarFrame:UnregisterEvent("UNIT_SPELLCAST_STOP")
	CastingBarFrame:UnregisterEvent("UNIT_SPELLCAST_FAILED")
	CastingBarFrame:UnregisterEvent("UNIT_SPELLCAST_INTERRUPTED")
	CastingBarFrame:UnregisterEvent("UNIT_SPELLCAST_DELAYED")
	CastingBarFrame:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START")
	CastingBarFrame:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE")
end
