aUF = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceHook-2.0", "AceDB-2.0", "AceConsole-2.0")
aUF.Layouts = {}

local L = AceLibrary("AceLocale-2.0"):new("ag_UnitFrames")
local AceOO = AceLibrary("AceOO-2.0")

local print = function(msg) if msg then DEFAULT_CHAT_FRAME:AddMessage(msg) end end

-- SYSTEM

function aUF:OnInitialize()
	self:RegisterDB("aUFDB")
	self:RegisterDefaults('profile', aUF_DEFAULT_OPTIONS)
	
	self:SetupVariables()
	self:UpdateBlizzVisibility()
	self:InitMenu()
	self:RegisterEvents()
	self:LoadStringFormats()
	if UnitInRaid("player") == 1 then
		self:RAID_ROSTER_UPDATE()
	end
	aUF:ScheduleRepeatingEvent("agUF_auraPoolSchedule",self.AuraPool, 0.3, self)	
end

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

function aUF:Reset()
	self:ResetDB("profile")
	self:LoadStringFormats()
	self:CallUnitMethods("Reset")
	self:CallUnitMethods("Reset",nil,nil,nil,"subgroups")
end

function aUF:OnProfileEnable()
	self:CallUnitMethods("Reset")					
end

-- EVENT REGISTERING

function aUF:RegisterEvents()
	self:RegisterEvent("PLAYER_LOGIN")
	self:RegisterEvent("PARTY_MEMBERS_CHANGED")
	self:RegisterEvent("RAID_ROSTER_UPDATE")
	self:RegisterEvent("UNIT_PET","PARTY_MEMBERS_CHANGED")
	self:RegisterEvent("PLAYER_TARGET_CHANGED")

	self:RegisterEvent("agUF_UpdateGroups")		
end

function aUF:SetupVariables()
	self.auraUpdates = 0
	self.auraUpdatePool = {}
	
	self.feedback = {}
	
	self.imagePath = "Interface\\AddOns\\ag_UnitFrames\\images\\"
	self.fontPath = "Interface\\AddOns\\ag_UnitFrames\\fonts\\"
	
	self.wowClasses = {"player","pet","party","partypet","target","targettarget","raid","raidpet"}
	
	-- Which auras can the player see?
	self.CanDispel = {
		["PRIEST"] = {
			["Magic"] = true,
			["Disease"] = true,
		},
		["SHAMAN"] = {
			["Poison"] = true,
			["Disease"] = true,
		},
		["PALADIN"] = {
			["Magic"] = true,
			["Poison"] = true,
			["Disease"] = true,
		},
		["MAGE"] = {
			["Curse"] = true,
		},
		["DRUID"] = {
			["Curse"] = true,
			["Poison"] = true,
		}			
	}
	
	-- Various constants like colors, textures...
	
	self.DebuffColor = {
		["Magic"] = {
			r = 1,
			g = 0,
			b = 0,
		},
		["Disease"] = {
			r = 0.25,
			g = 1,
			b = 0,		
		},
		["Poison"] = {
			r = 0,
			g = 0.25,
			b = 1,		
		},	
		["Curse"] = {
			r = 0.75,
			g = 0,
			b = 0.75,		
		}	
	}
	
	self.RepColor = {
		[1] = {r = 226/255, g = 45/255, b = 75/255},
		[2] = {r = 226/255, g = 45/255, b = 75/255},
		[3] = {r = 0.75, g = 0.27, b = 0},
		[4] = {r = 1, g = 1, b = 34/255},
		[5] = {r = 0.2, g = 0.8, b = 0.15},
		[6] = {r = 0.2, g = 0.8, b = 0.15},
		[7] = {r = 0.2, g = 0.8, b = 0.15},
		[8] = {r = 0.2, g = 0.8, b = 0.15},
	}
	
	self.HealthColor = {
		r = 0.11,
		g = 0.84,
		b = 0.3,
	}
	
	self.ManaColor = {
		[0] = { r = 48/255, g = 113/255, b = 191/255}, -- Mana
		[1] = { r = 226/255, g = 45/255, b = 75/255}, -- Rage
		[2] = { r = 255/255, g = 210/255, b = 0}, -- Focus
		[3] = { r = 255, g = 220/255, b = 25/255}, -- Energy
		[4] = { r = 0.00, g = 1.00, b = 1.00} -- Happiness
	}
	
	self.Borders = {
		["Classic"] 	= {["texture"] = "Interface\\Tooltips\\UI-Tooltip-Border",["size"] = 16,["insets"] = 5},
		["Nurfed"]	 	= {["texture"] = "Interface\\DialogFrame\\UI-DialogBox-Border",["size"] = 16,["insets"] = 5},
		["Hidden"] 		= {["texture"] = "",["size"] = 0,["insets"] = 3},
	}
	self.Bars	= {
		["Default"]		= self.imagePath.."AceBarFrames.tga",
		["Classic"]		= "Interface\\TargetingFrame\\UI-StatusBar",
		["Smooth"]		= self.imagePath.."smooth.tga",
		["Bumps"]		= self.imagePath.."Bumps.tga",
		["Perl"]			= self.imagePath.."Perl.tga",
		["Gloss"]			= self.imagePath.."Gloss.tga",
		["Wisps"]		= self.imagePath.."Wisps.tga",
		["Bars"]			= self.imagePath.."Bars.tga",
		["Smudge"]	= self.imagePath.."Smudge.tga",
		["Dabs"]			= self.imagePath.."Dabs.tga",
		["Rain"]			= self.imagePath.."Rain.tga",
		["Hatched"]	= self.imagePath.."Hatched.tga",
		["Cracked"]	= self.imagePath.."Cracked.tga",
		["Grid"]			= self.imagePath.."Grid.tga",
		["Button"]		= self.imagePath.."Button.tga",
		["Skewed"]		= self.imagePath.."Skewed.tga",
		["Diagonal"]	= self.imagePath.."Diagonal.tga",
		["Cloud"]			= self.imagePath.."Cloud.tga",
		["Water"]			= self.imagePath.."Water.tga",
		["Charcoal"]			= self.imagePath.."Charcoal.tga",
		["BantoBar"]			= self.imagePath.."BantoBar.tga",
	}

	self.RaidColors = {
		["DRUID"]	= "|cffff7c0a",
		["HUNTER"]	= "|cffaad372",
		["MAGE"]	= "|cff68ccef",
		["PALADIN"]	= "|cfff48cba",
		["PRIEST"]	= "|cffffffff",
		["ROGUE"]	= "|cfffff468",
		["SHAMAN"]	= "|cfff48cba",
		["WARLOCK"]	= "|cff9382C9",
		["WARRIOR"]	= "|cffc69b6d",
	}

	self.RaidRole = {
		["DRUID"]	= "healer",
		["HUNTER"]	= "dps",
		["MAGE"]	= "dps",
		["PALADIN"]	= "healer",
		["PRIEST"]	= "healer",
		["ROGUE"]	= "dps",
		["SHAMAN"]	= "healer",
		["WARLOCK"]	= "dps",
		["WARRIOR"]	= "tank",
	}

	self.UnitInformation = {
	["name"] = function(u) local type = string.gsub(u, "%d", "") if self.db.profile[type].RaidColorName and UnitIsPlayer(u) then local _,x=UnitClass(u) return string.format("%s%s%s",aUF.RaidColors[x] or "",UnitName(u) or "","|cFFFFFFFF") else return UnitName(u) or "" end end,
	
	["status"] = function (u) if UnitIsDead(u) then return "Dead" elseif UnitIsGhost(u) then return "Ghost" elseif (not UnitIsConnected(u)) then return "Offline" elseif (UnitAffectingCombat(u)) then return "Combat" elseif (u== "player" and IsResting()) then return "Resting" else return "" end end,
	["statuscolor"] = function (u) if UnitIsDead(u) then return "|cffff0000" elseif UnitIsGhost(u) then return "|cff9d9d9d" elseif (not UnitIsConnected(u)) then return "|cffff8000" elseif (UnitAffectingCombat(u)) then return "|cffFF0000" elseif (u== "player" and IsResting()) then return WatchDog:GetHex(UnitReactionColor[4]) else return "" end end,
	["happycolor"] = function (u) local x=GetPetHappiness() return ( (x==2) and "|cffFFFF00" or (x==1) and "|cffFF0000" or "" ) end,

    ["aghp"] = function(u) return self:Tag_aghp(u) or "" end,
    ["agpercenthp"] = function(u) return self:Tag_aghp(u,1) or "" end,
    ["agmissinghp"] = function(u) return self:Tag_aghp(u,2) or "" end,
    ["agsmarthp"] = function(u) return self:Tag_aghp(u,3) or "" end,
	
    ["agmana"] = function(u) return self:Tag_agmana(u) or "" end,
    ["agpercentmana"] = function(u) return self:Tag_agmana(u,1) or "" end,
    ["agmissingmana"] = function(u) return self:Tag_agmana(u,2) or "" end,
    ["agsmartmana"] = function(u) return self:Tag_agmana(u,3) or "" end,
	
	["agclass"] = function (u) if UnitIsPlayer(u) then return (UnitClass(u) or "Unknown") else return (UnitCreatureFamily(u) or UnitCreatureType(u) or "") end end,
	["agrace"] = function (u) if string.find(u,"target") then return UnitRace(u) or "" else return "" end end,
	["agtype"] = function (u) if (UnitIsPlusMob(u)) then return aUF:TargetGetMobType(u) or "" else return "" end end,
	
	["curhp"] = function (u) return UnitHealth(u) or 0 end,
	["maxhp"] = function (u) return UnitHealthMax(u) or 1 end,
	["percenthp"] = function (u) local hpmax = UnitHealthMax(u) return (hpmax ~= 0) and floor((UnitHealth(u) / hpmax) * 100) or 0 end,
	["missinghp"] = function (u) return UnitHealthMax(u) - UnitHealth(u) or 0 end,
	
	["curmana"] = function (u) return UnitMana(u) or 1 end,
	["maxmana"] = function (u) return UnitManaMax(u) or 0 end,
	["percentmana"] = function (u) local mpmax = UnitManaMax(u) return (mpmax ~= 0) and floor((UnitMana(u) / mpmax) * 100) or 0 end,
	["missingmana"] = function (u) return UnitHealthMax(u) - UnitHealth(u) or 0 end,

	["typemana"] = function (u) local p=UnitPowerType(u) return ( (p==1) and "Rage" or (p==2) and "Focus" or (p==3) and "Energy" or "Mana" ) end,
	["level"] = function (u) local x = UnitLevel(u) return ((x>0) and x or "??") end,
	["class"] = function (u) return (UnitClass(u) or "Unknown") end,
	["creature"] = function (u) return (UnitCreatureFamily(u) or UnitCreatureType(u) or "Unknown") end,
	["smartclass"] = function (u) if UnitIsPlayer(u) then return self.UnitInformation["class"](u) else return self.UnitInformation["creature"](u) end end,
	["combos"] = function (u) return (GetComboPoints() or 0) end,
	["combos2"] = function (u) return string.rep("@", GetComboPoints()) end,
	["classification"] = function (u) if UnitClassification(u) == "rare" then return "Rare " elseif UnitClassification(u) == "eliterare" then return "Rare Elite " elseif UnitClassification(u) == "elite" then return "Elite " elseif UnitClassification(u) == "worldboss" then return "Boss " else return "" end end, 
	["faction"] = function (u) return (UnitFactionGroup(u) or "") end,
	["connect"] = function (u) return ( (UnitIsConnected(u)) and "" or "Offline" ) end,
	["race"] = function (u) return ( UnitRace(u) or "") end,
	["pvp"] = function (u) return ( UnitIsPVP(u) and "PvP" or "" ) end,
	["plus"] = function (u) return ( UnitIsPlusMob(u) and "+" or "" ) end,
	["sex"] = function (u) local x = UnitSex(u) return ( (x==0) and "Male" or (x==1) and "Female" or "" ) end,
	["rested"] = function (u) return (GetRestState()==1 and "Rested" or "") end,
	["leader"] = function (u) return (UnitIsPartyLeader(u) and "(L)" or "") end,
	["leaderlong"] = function (u) return (UnitIsPartyLeader(u) and "(Leader)" or "") end,
	
	["happynum"] = function (u) return (GetPetHappiness() or 0) end,
	["happytext"] = function (u) return ( getglobal("PET_HAPPINESS"..(GetPetHappiness() or 0)) or "" ) end,
	["happyicon"] = function (u) local x=GetPetHappiness() return ( (x==3) and ":)" or (x==2) and ":|" or (x==1) and ":(" or "" ) end,
		
	["curxp"] = function (u) return (UnitXP(u) or "") end,
	["maxxp"] = function (u) return (UnitXPMax(u) or "") end,
	["percentxp"] = function (u) local x=UnitXPMax(u) if (x>0) then return floor( UnitXP(u)/x*100+0.5) else return 0 end end,
	["missingxp"] = function (u) return (UnitXPMax(u) - UnitXP(u)) end,
	["restedxp"] = function (u) return (GetXPExhaustion() or "") end,

	["tappedbyme"] = function (u) if UnitIsTappedByPlayer("target") then return "*" else return "" end end,
	["istapped"] = function (u) if UnitIsTapped(u) and (not UnitIsTappedByPlayer("target")) then return "*" else return "" end end,
	["pvpranknum"] = function (u) if (UnitPVPRank(u) >= 1) then return ((UnitPVPRank(u)-4) or "") else return "" end end,
	["pvprank"] = function (u) if (UnitPVPRank(u) >= 1) then return (GetPVPRankInfo(UnitPVPRank(u), u) or "" ) else return "" end end,
	["fkey"] = function (u)
		local _,_,fkey = string.find(u, "^party(%d)$")
		if u == "player" then
			fkey = 0
		end
		if not fkey then
			return ""
		else
			return "F"..(fkey+1)
		end
	end,
	["white"] = function (u) return "|cFFFFFFFF" end,
	["aggro"] = function (u)
		local x = (UnitReaction("player",u) or 5)
		return self:GiveHex(UnitReactionColor[x].r, UnitReactionColor[x].g, UnitReactionColor[x].b)
	end,
	["difficulty"] = function (u) if UnitCanAttack("player",u) then local x = (UnitLevel(u)>0) and UnitLevel(u) or 99 local color = GetDifficultyColor(x) return aUF:GiveHex(color.r,color.g,color.b) else return "" end end,
	["colormp"] = function (u) local x = ManaBarColor[UnitPowerType(u)] return self:GiveHex(x.r, x.g, x.b) end,  
	["inmelee"] = function (u) if PlayerFrame.inCombat then return "|cffFF0000" else return "" end end,
	["incombat"] = function (u) if UnitAffectingCombat(u) then return "|cffFF0000" else return "" end end,
	["raidcolor"] = function (u) local _,x=UnitClass(u) if x and UnitIsPlayer(u) then return (self.RaidColors[x] or "") else return "" end end,
	}
	
	self.formats = {
		["Health"] = {
			["Absolute"]	= "[aghp]",
			["Difference"]	= "[agmissinghp]",
			["Percent"]		= "[agpercenthp]",
			["Smart"]		= "[agsmarthp]",
			["Hide"]		= "",
		},
		["Mana"] = {
			["Absolute"]	= "[agmana]",
			["Difference"]	= "[agmissingmana]",
			["Percent"]		= "[agpercentmana]",
			["Smart"]		= "[agsmartmana]",
			["Hide"]		= "",
		},
		["Name"] = {
			["Default"]	= "[name]",
			["Hide"]		= "",			
		},
		["Class"] = {
			["Default"]	= "[agtype][difficulty][level][white] [raidcolor][agclass][white] [agrace]",
			["Hide"]		= "",			
		}		
	}
	
	
	self.HelperFunctions = {}
	self.units = {}
	self.subgroups = {}
	self.changedSubgroups = {}
end

-- EVENTS

function aUF:PLAYER_LOGIN()
	aUF:CreateObject("player","player","XP")
	aUF:CreateObject("pet","pet","XP")
	aUF:CreateObject("target","target","Combo")
	aUF:CreateObject("targettarget","targettarget","Metro")
	
	self:PARTY_MEMBERS_CHANGED()
end

function aUF:PLAYER_TARGET_CHANGED()
	if self.units.target then
		self.units.target:UpdateAll()
	end
	if self.units.targettarget then
		if UnitExists("target")	then
			self.units.targettarget:Start()
		else
			self.units.targettarget:Stop()
		end
	end
end

function aUF:PARTY_MEMBERS_CHANGED()
	for i = 1,4 do
		if aUF:CheckVisibility("party"..i) == true then
			aUF:CreateObject("party"..i)
		end
		if aUF:CheckVisibility("partypet"..i) == true then
			aUF:CreateObject("partypet"..i)
		end		
	end
end

function aUF:RAID_ROSTER_UPDATE()
	for i = 1,40 do
		if aUF:CheckVisibility("raid"..i) == true then
			aUF:CreateObject("raid"..i,"raid"..i,"Raid")
		end			
	end	
	self:PARTY_MEMBERS_CHANGED()
end

function aUF:agUF_UpdateGroups()
	for name in self.changedSubgroups do
		if string.find(name,"party") then
			self.subgroups[name].raid = false
		end		
		self.subgroups[name]:Update()
	end
	self.changedSubgroups = {}
end

-- UTILITY FUNCTIONS

function aUF:CreateObject(name,unit,type,db)
	if not self.units[name] then
		if not unit then
			unit = name
		end
		if not type then
			self.units[name] = self.classes.aUFunit:new(name,unit,db)
		else
			self.units[name] = self.classes["aUFunit"..type]:new(name,unit,db)
		end
	end
end

function aUF:FindObjects(sortBy,object)
	local table = {}
	if not object then object = "units" end
	if self[object] then
		for _,v in 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 aUF:FindObjects(type,object)[find] do
				if unitObject[func] then
					unitObject[func](unitObject,arg)
				end
			end
		end
	else
		if not object then object = "units" end
		if self[object] then
			for _,unitObject in self[object] do
				unitObject[func](unitObject,arg)		
			end
		end
	end
end

function aUF:CheckVisibility(unit)
	local _,_,type = string.find(unit, "(%a+)")
	
--	if  self.db.profile[type].AlwaysShow == true then
--		return true
--	end
	-- Special cases
	   -- Hide targettarget if player is targetting self
	if unit == "targettarget" then
		if UnitName("player") == UnitName("target") then
			return false
		end
		-- Hide partyframes in raid
	elseif type == "party" then
		if self.db.profile.RaidHideParty == true and UnitInRaid("player") == 1 then
			return false
		end
	elseif type == "partypet" then
		if self.db.profile.RaidHideParty == true and UnitInRaid("player") == 1 then
			return false
		end	
		local parent = string.gsub(unit,"pet","")
		if aUF:CheckVisibility(parent) == false then
			return false
		end
	elseif type == "raidpet" then
		local parent = string.gsub(unit,"pet","")
		if not aUF:CheckVisibility(parent) then
			return false
		end
	end
		
	if (UnitExists(unit) and not self.db.profile[type].HideFrame == true) then
		return true
	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)
	r=r*255
	g=g*255
	b=b*255
	return string.format("|cff%2x%2x%2x", r, g, b) or ""
end

function aUF:GetRaidColors(class)
	if self.RaidColors[class] then
		return self.RaidColors[class]
	else 
		return "|r"
	end
end

function aUF:TargetGetMobType(unit)
	local classification = UnitClassification(unit)
	if ( classification == "worldboss" ) then
		return "Boss "
	elseif ( classification == "rareelite"  ) then
		return "Rare-Elite "
	elseif ( classification == "elite"  ) then
		return "Elite "
	elseif ( classification == "rare"  ) then
		return "Rare "
	else
		return nil;
	end
end

function aUF:UnitDebuff(unit,id,filter)
	local aura, count, t = UnitDebuff(unit,id)
	local _, eClass = UnitClass("player")
	
	if filter == 1 then
		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:FeedbackUpdate()
	local maxalpha = 0.6
	local found
	for objectName,v in self.feedback do
		found = true
		local unitOjbect = aUF.units[objectName]
		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
	end
	if not found then 
		self:CancelScheduledEvent("agUF_CombatSchedule")
	end
end

-- Dewdrop stuff

function aUF:CreateMenu()
	self.dewdrop = AceLibrary("Dewdrop-2.0")

	local unitTable = {}
	unitTable.UnitHeader = {
		name = L"unitsettings",
		type = 'header',
		desc = "desc",
		order = 1,
	}	
	for order,unit in ipairs(self.wowClasses) do
		unitTable[unit] = aUF:CreateDewdrop(unit,(order + 1),true)
	end
	
	local agDewdropMenu = {
		type= 'group',
		args = {
			AddonHeader = {
				name = L"addonname",
				type = 'header',
				desc = "desc",
				order = 1,
			},		
			Units = {
				name = L"units",
				type = 'group',
				desc = L"UnitDesc",
				args = unitTable,
				order = 2,
			},			
			Borders = {
				name = L"borders",
				type = 'text',
				desc = L"BordersDesc",
				get = function()
					return self.db.profile.BorderStyle
				end,
				set = function(option)
					self.db.profile.BorderStyle = option
					self:CallUnitMethods("BorderBackground")
					self:CallUnitMethods("BorderBackground",nil,nil,nil,"subgroups")
				end,
				validate = {"Classic", "Nurfed", "Hidden"},
				order = 3,
			},
			FrameColors = {
				type= 'group',
				name = L"framecolors",
				desc = L"framecolorsdesc",
				args = {
					partybg = {
						name = L"partybg",
						type = 'color',
						desc = L"partybgdesc",
						hasAlpha = true,
						get = function()
							return self.db.profile.PartyFrameColors.r, self.db.profile.PartyFrameColors.g, self.db.profile.PartyFrameColors.b, self.db.profile.PartyFrameColors.a
						end,
						set = function(r, g, b, a)
							self.db.profile.PartyFrameColors.r, self.db.profile.PartyFrameColors.g, self.db.profile.PartyFrameColors.b, self.db.profile.PartyFrameColors.a = r, g, b, a
							self:CallUnitMethods("BorderBackground")
							self:CallUnitMethods("BorderBackground",nil,nil,nil,"subgroups")
						end,
						order = 1,
					},
					targetbg = {
						name = L"targetbg",
						type = 'color',
						desc = L"targetbgdesc",
						hasAlpha = true,
						get = function()
							return self.db.profile.TargetFrameColors.r, self.db.profile.TargetFrameColors.g, self.db.profile.TargetFrameColors.b, self.db.profile.TargetFrameColors.a
						end,
						set = function(r, g, b, a)
							self.db.profile.TargetFrameColors.r, self.db.profile.TargetFrameColors.g, self.db.profile.TargetFrameColors.b, self.db.profile.TargetFrameColors.a = r, g, b, a
							self:CallUnitMethods("BorderBackground")
							self:CallUnitMethods("BorderBackground",nil,nil,nil,"subgroups")
						end,
						order = 2,
					},
					border = {
						name = L"bordercolor",
						type = 'color',
						desc = L"bordercolordesc",
						hasAlpha = true,
						get = function()
							return self.db.profile.FrameBorderColors.r, self.db.profile.FrameBorderColors.g, self.db.profile.FrameBorderColors.b, self.db.profile.FrameBorderColors.a
						end,
						set = function(r, g, b, a)
							self.db.profile.FrameBorderColors.r, self.db.profile.FrameBorderColors.g, self.db.profile.FrameBorderColors.b, self.db.profile.FrameBorderColors.a = r, g, b, a
							self:CallUnitMethods("BorderBackground")
							self:CallUnitMethods("BorderBackground",nil,nil,nil,"subgroups")
						end,
						order = 3,
					},
				},
				order = 4,
			},
			BarColors = {
				type= 'group',
				args = {
					Health = {
						name = L"health",
						type = 'color',
						desc = L"healthDesc",
						get = function()
							return self.db.profile.HealthColor.r, self.db.profile.HealthColor.g, self.db.profile.HealthColor.b
						end,
						set = function(r, g, b)
							self.db.profile.HealthColor.r, self.db.profile.HealthColor.g, self.db.profile.HealthColor.b = r, g, b
							self:CallUnitMethods("StatusBarsColor")
						end,
						order = 1,
					},
					Mana = {
						name = L"mana",
						type = 'color',
						desc = L"manaDesc",
						get = function()
							return self.db.profile.ManaColor[0].r, self.db.profile.ManaColor[0].g, self.db.profile.ManaColor[0].b
						end,
						set = function(r, g, b)
							self.db.profile.ManaColor[0].r, self.db.profile.ManaColor[0].g, self.db.profile.ManaColor[0].b = r, g, b
							self:CallUnitMethods("StatusBarsColor")
						end,
						order = 2,
					},
					Rage = {
						name = L"rage",
						type = 'color',
						desc = L"rageDesc",
						get = function()
							return self.db.profile.ManaColor[1].r, self.db.profile.ManaColor[1].g, self.db.profile.ManaColor[1].b
						end,
						set = function(r, g, b)
							self.db.profile.ManaColor[1].r, self.db.profile.ManaColor[1].g, self.db.profile.ManaColor[1].b = r, g, b
							self:CallUnitMethods("StatusBarsColor")
						end,
						order = 3,
					},
					Energy = {
						name = L"energy",
						type = 'color',
						desc = L"energyDesc",
						get = function()
							return self.db.profile.ManaColor[3].r, self.db.profile.ManaColor[3].g, self.db.profile.ManaColor[3].b
						end,
						set = function(r, g, b)
							self.db.profile.ManaColor[3].r, self.db.profile.ManaColor[3].g, self.db.profile.ManaColor[3].b = r, g, b
							self:CallUnitMethods("StatusBarsColor")
						end,
						order = 4,
					},
					PetFocus = {
						name = L"petfocus",
						type = 'color',
						desc = L"petfocusDesc",
						get = function()
							return self.db.profile.ManaColor[2].r, self.db.profile.ManaColor[2].g, self.db.profile.ManaColor[2].b
						end,
						set = function(r, g, b)
							self.db.profile.ManaColor[2].r, self.db.profile.ManaColor[2].g, self.db.profile.ManaColor[2].b = r, g, b
							self:CallUnitMethods("StatusBarsColor")
						end,
						order = 5,
					},					
				},
				order = 5,
				name = L"barcolors",
				desc = L"barcolorsDesc",
			},
			BarStyle = {
				name = L"barstyle",
				type = 'text',
				desc = L"BarStyleDesc",
				get = function()
					return self.db.profile.BarStyle
				end,
				set = function(option)
					self.db.profile.BarStyle = option
					self:CallUnitMethods("BarTexture")					
				end,
				validate = {"Classic", "Default","Smooth", "Bars", "Bumps", "Button", "Cloud", "Cracked", "Dabs", "Diagonal", "Gloss", "Grid", "Hatched", "Perl", "Rain", "Skewed", "Smudge", "Water", "Wisps","Charcoal","BantoBar"},
				order = 6,
			},		
			ShowPvPIcon = {
				name = L"pvpicon",
				type = 'toggle',
				desc = L"ShowPVPIconDesc",
				get = function()
					return self.db.profile.ShowPvPIcon
				end,
				set = function(option)
					self.db.profile.ShowPvPIcon = option
					self:CallUnitMethods("UpdatePvP",true)					
				end,
				order = 7,				
			},		
			ShowGroupIcons = {
				name = L"groupicon",
				type = 'toggle',
				desc = L"ShowGroupIconsDesc",
				get = function()
					return self.db.profile.ShowGroupIcons
				end,
				set = function(option)
					self.db.profile.ShowGroupIcons = option
					self:CallUnitMethods("LabelsCheckLeader")					
				end,
				order = 8,				
			},
            HighlightSelected = {
				name = L"highlightselected",
				type = 'toggle',
				desc = L"HighlightSelectedDesc",
				get = function()
					return self.db.profile.HighlightSelected
				end,
				set = function(option)
					self.db.profile.HighlightSelected = option
				end,
				order = 9,				
			},			
			Locked = {
				name = L"lock",
				type = 'toggle',
				desc = L"LockedDesc",
				get = function()
					return self.db.profile.Locked
				end,
				set = function(option)
					self.db.profile.Locked = option
				end,
				order = 12,				
			},		
		}
	}
	self.dewdrop:InjectAceOptionsTable(self, agDewdropMenu)
	return agDewdropMenu
end

function aUF:InitMenu()
	if not self.menu then
		self.menu = aUF:CreateMenu()
	end
	
	local agSlashMenu = {
		type = "group",
		args = {
			config = {
				name = L('config'),
				desc = L('configdesc'),
				type = 'execute',
				func = function()
					self.dewdrop:Open(UIParent, 'children', function() self.dewdrop:FeedAceOptionsTable(self.menu) end,'cursorX', true, 'cursorY', true)
				end,
			},
			reset = {
				name = L('reset'),
				desc = L('resetdesc'),
				type = 'execute',
				func = function()
					self:Reset()
				end,
			}			
		}
	}
	
	self:RegisterChatCommand({ "/aguf", "/ag_unitframes" }, agSlashMenu )
end

function aUF:CreateDewdrop(type,order,mainmenu)
	local class = type
    local prettyname = L(class)

	local strings = {"Health","Mana","Name","Class"}
--	local strings = {"Health","Mana"}

	local stringArgs = {}

	for k,v in strings do
		local name = v
		local order = k
		local validate
		if v == "Health" or v == "Mana" then
			validate = {"Absolute", "Difference", "Percent", "Smart","Custom", "Hide"}
		else
			validate = {"Default","Custom", "Hide"}
		end
		stringArgs[v] = {
			name = name.." Text",
			type = 'group',
			desc = L"UnitDesc",
			order = order,
			args = {
				StatusTextStyle = {
					name = "Style",
					type = 'text',
					desc = L"StatusTextDesc",
					get = function()
						return self.db.profile[class][name.."Style"]
					end,
					set = function(option)
						self.db.profile[class][name.."Style"] = option
						
						self:SetStringFormats(class)
						self:CallUnitMethods("UpdateTextStrings",nil,class,"type")				
					end,
					validate = validate,
					order = 1,				
				},								
				HealthCustom = {
					name = "Custom",
					type = 'text',
					desc = L"StatusTextDesc",
					get = function()
						return self.db.profile[class][name.."Format"]
					end,
					set = function(option)
						self.db.profile[class][name.."Format"] = option
						
						self:SetStringFormats(class)				
						self:CallUnitMethods("UpdateTextStrings",nil,class,"type")				
					end,
					usage = "",
					order = 2,
				}
			}
		}
	end



	local table = {
		name = prettyname, 
		type = 'group',
		desc = prettyname.." Settings",
		order = order,
		args = {
			UnitHeader = {
				name = prettyname.." "..L"layoutsettings",
				type = 'header',
				desc = "desc",
				order = 1,
			},
			FrameStyle = {
				name = L"framestyle",
				type = 'text',
				desc = L"FrameStyleDesc",
				validate = {},
				get = function()
					return self.db.profile[class].FrameStyle
				end,
				set = function(option)
					self.db.profile[class].FrameStyle = option
					self:CallUnitMethods("ApplyTheme",nil,class,"type")				
					self:CallUnitMethods("UpdateName",true,class,"type")					
				end,
				order = 2,
			},

			Width = {
				name = L"widthadjust",
				type = 'range',
				desc = L"widthadjustDesc",
				min = 50,
				max = 400,
				step = 1,
				get = function()
					return self.db.profile[class].Width
				end,
				set = function(option)
					self.db.profile[class].Width = option
					self:CallUnitMethods("SetWidth",nil,class,"type")
				end,
				order = 3,
			},
			
			StatusTextStyle = {
				name = "Status Text",
				type = 'group',
				desc = L"UnitDesc",
				order = 5,
				args = stringArgs,
			},
			Scale = {
				name = L"scale",
				type = 'range',
				desc = L"ScaleDesc",
				min = 0.5,
				max = 2,
				step = 0.01,
				isPercent = true,
				get = function()
					return self.db.profile[class].Scale
				end,
				set = function(option)
					self.db.profile[class].Scale = option
					self:CallUnitMethods("LoadScale",nil,class,"type")
					self:CallUnitMethods("LoadPosition",nil,class,"type")					
				end,
				order = 7,
			},
			ClassColorBars = {
				name = L"classcolorbar",
				type = 'toggle',
				desc = L"ClassColorBarsDesc",
				get = function()
					return self.db.profile[class].ClassColorBars
				end,
				set = function(option)
					self.db.profile[class].ClassColorBars = option
					self:CallUnitMethods("StatusBarsColor",nil,class,"type")				
				end,
				order = 20,				
			},
			RaidColorName = {
				name = L"raidcolorname",
				type = 'toggle',
				desc = L"RaidColorNameDesc",
				get = function()
					return self.db.profile[class].RaidColorName
				end,
				set = function(option)
					self.db.profile[class].RaidColorName = option
					self:CallUnitMethods("UpdateTextStrings",nil,class,"type")				
				end,
				order = 21,				
			},
			ShowCombat = {
				name = L"showcombat",
				type = 'toggle',
				desc = L"ShowCombatDesc",
				get = function()
					return self.db.profile[class].ShowCombat
				end,
				set = function(option)
					self.db.profile[class].ShowCombat = option
				end,
				order = 23,				
			},				
			ShowInCombatIcon = {
			        name = L"showincombat",
			        type =  'toggle',
			        desc = L"ShowInCombatDesc",
			        get = function ()
				        return self.db.profile[class].ShowInCombatIcon
				end,
				set = function(option)
					self.db.profile[class].ShowInCombatIcon = option
				end,
			        order = 24,
			},
			ShowRaidTargetIcon = {
			        name = L"showraidicon",
			        type =  'toggle',
			        desc = L"ShowRaidIconDesc",
			        get = function ()
				        return self.db.profile[class].ShowRaidTargetIcon
				end,
				set = function(option)
					self.db.profile[class].ShowRaidTargetIcon = option
					self:CallUnitMethods("UpdateRaidTargetIcon",true,class,"type")	
				end,
			        order = 25,
			},
			LongStatusbars = {
				name = L"longbars",
				type = 'toggle',
				desc = L"LongBarsDesc",
				get = function()
					return self.db.profile[class].LongStatusbars
				end,
				set = function(option)
					self.db.profile[class].LongStatusbars = option
					self:CallUnitMethods("ApplyTheme",nil,class,"type")
				end,
				order = 26,
			},
			HideMana = {
				name = L"hidemana",
				type = 'toggle',
				desc = L"HideManaDesc",
				get = function()
					return self.db.profile[class].HideMana
				end,
				set = function(option)
					self.db.profile[class].HideMana = option
					self:CallUnitMethods("ApplyTheme",nil,class,"type")
					self:CallUnitMethods("UpdateName",true,class,"type")					
				end,
				order = 27,
			},
			HideFrame = {
				name = L"hideframe",
				type = 'toggle',
				desc = L"HideFrameDesc",
				get = function()
					return self.db.profile[class].HideFrame
				end,
				set = function(option)
					self.db.profile[class].HideFrame = option
					self:RAID_ROSTER_UPDATE()
					self:CallUnitMethods("UpdateAll",nil,class,"type")				
				end,
				order = 29,
			},
			Spacing1 = {
				name = " ",
				type = 'header',
				order = 35,
			},			
			AuraHeader = {
				name = L"aurasettings",
				type = 'header',
				order = 39,
			},			
			AuraStyle = {
				name = L"aurastyle",
				type = 'text',
				desc = L"AuraStyleDesc",
				get = function()
					return self.db.profile[class].AuraStyle
				end,
				set = function(option)
					self.db.profile[class].AuraStyle = option
					self:CallUnitMethods("UpdateAuras",true,class,"type")				
					self:CallUnitMethods("AuraPosition",true,class,"type")					
				end,
				validate = {OneLine = L"oneline", TwoLines = L"twolines", Hide = L"hide"},
				order = 40,				
			},
			AuraPos = {
				name = L"aurapos",
				type = 'text',
				desc = L"AuraPosDesc",
				get = function()
					return self.db.profile[class].AuraPos
				end,
				set = function(option)
					self.db.profile[class].AuraPos = option
					self:CallUnitMethods("UpdateAuras",true,class,"type")				
					self:CallUnitMethods("AuraPosition",true,class,"type")
				end,
				validate = {"Right", "Left", "Above", "Below"},
				order = 41,				
			},			
			DebuffColoring = {
				name = L"debuffcoloring",
				type = 'toggle',
				desc = L"DebuffColoringDesc",
				get = function()
					return self.db.profile[class].AuraDebuffC
				end,
				set = function(option)
					self.db.profile[class].AuraDebuffC = option
					self:CallUnitMethods("UpdateAuras",true,class,"type")								
				end,
				order = 42,
			},				
			AuraFilter = {
				name = L"aurafilter",
				type = 'toggle',
				desc = L"AuraFilterDesc",
				get = function()
					if self.db.profile[class].AuraFilter == 1 then
						return true
					else
						return false
					end
				end,
				set = function(option)
					if option == true then
						self.db.profile[class].AuraFilter = 1
					else
						self.db.profile[class].AuraFilter = 0
					end
					self:CallUnitMethods("UpdateAuras",true,class,"type")				
				end,
				order = 43,
			}	
		}
	}
	-- Inject themes from the theme table
	local themetable = {}
	for k, v in self.Layouts do
		tinsert(themetable,k)
	end
	table.args.FrameStyle.validate = themetable
	
	-- PLAYER/PET
	--[[
	if class == "player" then
		local ShowRestingIcon = {
				name = L"showresting",
				type = 'toggle',
				desc = L"ShowRestingDesc",
				get = function()
					return self.db.profile[class].ShowRestingIcon
				end,
				set = function(option)
					self.db.profile[class].ShowRestingIcon = option
					self:CallUnitMethods("UpdateResting",nil,class,"type")	
				end,
				order = 26,
			}
		table.args.ShowRestingIcon = ShowRestingIcon
	end
	]]
	if class == "player" or class == "pet" then
		local ShowXP = {
				name = L"showxp",
				type = 'toggle',
				desc = L"ShowXPDesc",
				get = function()
					return self.db.profile[class].ShowXP
				end,
				set = function(option)
					self.db.profile[class].ShowXP = option
					self:CallUnitMethods("ApplyTheme",nil,class,"type")	
				end,
				order = 26,
			}
		table.args.ShowXP = ShowXP
	end

	if class == "pet" then
		local PetGrouping = {
				name = L"petgrouping",
				type = 'text',
                desc = L"PetGroupingDesc",
				get = function()
					return self.db.profile.PetGrouping
				end,
				set = function(option)
					self.db.profile.PetGrouping = option
					self:CallUnitMethods("UpdateAll")				
				end,
				validate = {["withplayer"] = L"withplayer", ["nogroup"] = L"nogroup"},				
				order = 6,
			}	
		table.args.PetGrouping = PetGrouping
	end
	
	if class == "pet" or class == "partypet" or class == "raidpet" then
		table.args.RaidColorName = nil
		table.args.ClassColorBars = nil
	end
	
	-- TARGET
	if string.find(class,"target") then	
		local TargetShowHostile = {
				name = L"targetshowhostile",
				type = 'toggle',
				desc = L"TargetHostileDesc",
				get = function()
					return self.db.profile.TargetShowHostile
				end,
				set = function(option)
					self.db.profile.TargetShowHostile = option
					self:CallUnitMethods("StatusBarsColor",nil,class,"type")
				end,
				order = 22,				
			}
		table.args.TargetShowHostile = TargetShowHostile
	end	
		
	-- PARTY
	if class == "party" then
		local RaidHideParty = {
				name = L"raidhideparty",
				type = 'toggle',
				desc = L"RaidHidePartyDesc",
				get = function()
					return self.db.profile.RaidHideParty
				end,
				set = function(option)
					self.db.profile.RaidHideParty = option
					self:CallUnitMethods("UpdateAll",nil,"party","type")				
					self:CallUnitMethods("UpdateAll",nil,"partypet","type")				
				end,
				order = 28,
			}
		table.args.RaidHideParty = RaidHideParty
		
		local PartyGrouping = {
				name = L"partygrouping",
				type = 'text',
                desc = L"PartyGroupingDesc",
				get = function()
					return self.db.profile.PartyGrouping
				end,
				set = function(option)
					self.db.profile.PartyGrouping = option
					self:PARTY_MEMBERS_CHANGED()
					self:CallUnitMethods("UpdateAll")				
				end,
				validate = {["withplayer"] = L"withplayer", ["withoutplayer"] = L"withoutplayer", ["nogroup"] = L"nogroup"},				
				order = 6,
			}	
		table.args.PartyGrouping = PartyGrouping
	end
	
	-- RAID
	if class == "raid" then
		local RaidGrouping = {
				name = L"raidgrouping",
				type = 'text',
                desc = L"RaidGroupingDesc",
				get = function()
					return self.db.profile.RaidGrouping
				end,
				set = function(option)
					self.db.profile.RaidGrouping = option
					self:CallUnitMethods("UpdateAll")				
				end,
				validate = {["bysubgroup"] = L"bysubgroup", ["byclass"] = L"byclass", ["byrole"] = L"byrole", ["nogroup"] = L"nogroup", ["onebiggroup"] = L"onebiggroup"},				
				order = 6,
			}	
		table.args.RaidGrouping = RaidGrouping
	end
	
	if not mainmenu then
		table.args.UnitHeader.name = L(class).." "..L"frame"
		local EndSpacing = {
			name = " ",
			type = 'header',
			order = 51,
		}
		table.args.EndSpacing = EndSpacing
	end
	
	return table
end

function aUF:LoadStringFormats()
	for order,unit in ipairs(self.wowClasses) do
		self:SetStringFormats(unit)
	end
end

function aUF:SetStringFormats(type)
	local db = self.db.profile[type]
	local strings = {"Health","Mana","Name","Class"}
	if not aUF.HelperFunctions[type] then
		aUF.HelperFunctions[type] = {}
	end
		
	for k,v in strings do
		local format
		if db[v.."Style"] == "Custom" then
				format = db[v.."Format"]
		else
			format = self.formats[v][db[v.."Style"]]
		end
		aUF.HelperFunctions[type][v.."Text"] = self:Parse(format)
	end
end


-- Clads code-- Clads code-- Clads code-- Clads code
-- Clads code-- Clads code-- Clads code-- Clads code

-- Code Begins here
local work = {}
local strgsub, strsub, strgfind, strformat, strfind = string.gsub, string.sub, string.gfind, string.format, string.find

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

   local formatArgs, formatString = {}
   
   for s,data,e in strgfind(format, "()(%b[])()") do
      local tag = strsub(data, 2, -2)
      local func = aUF:GetTagFunction(tag)
      if func then
         table.insert(formatArgs, func)
      else
         error(strformat("\"%s\" is not a valid format tag.", data))
      end
    end
   
    formatString = strgsub(format, "%%", "%%%%")
    formatString = strgsub(formatString, "%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 function(unit, fontstring)
            fontstring:SetText(formatString)
        end
    else
       return function(unit, fontstring)
          for i,func in ipairs(formatArgs) do 
             work[i] = func(unit)
          end
          fontstring:SetText(strformat(formatString, unpack(work)))
       end
    end
end

local helpers = {}

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 = strfind(tag, "^(%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 = aUF.UnitInformation[tag]
   if not func then
      -- Not a tag we support
      return nil
   end
   local _,_,width = strfind(args, "^(%d+)$")
   if width then
      local id = strformat("%s-%d", tag, width)
      local hFunc = helpers[id]
      if not hFunc then
         hFunc = function(unit)
            return strsub(func(unit), 1, width)
         end
         
         helpers[id] = hFunc
      end
      return hFunc
   end
   
   local _,_,oc,ec = strfind(args, "^(.)(.)$")
   if oc then
      local id = strformat("%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
               strformat("%s%s%s",oc,t,ec)
            else
               return t
            end
         end
         
         helpers[id] = hFunc
      end
      return hFunc
   end
end

function aUF:Tag_agmana(unit,flag)
	local currValue,maxValue = UnitMana(unit),UnitManaMax(unit)
	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 currValue > 9999 then
		currValue = string.format("%.1fk", currValue / 1000)
	end
	if maxValue > 9999 then
		maxValue = string.format("%.1fk", maxValue / 1000)
	end
	
	if flag == 1 then
		return string.format("%.0f%%", perc)
	elseif flag == 2 then
		if manaDiff > 9999 then
			manaDiff = string.format("%.1fk", manaDiff / 1000)
		end	
		return (currValue.."|cffff7f7f-"..manaDiff.."|r")
	elseif flag == 3 then
		return currValue	
	else
		return (currValue.."/"..maxValue)
	end
	
	return text
end
	
function aUF:Tag_aghp(unit,flag)
	local currValue,maxValue = UnitHealth(unit),UnitHealthMax(unit)
	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 (MobHealth3 and not UnitIsFriend("player", unit) ) then
		currValue,maxValue,MHfound = MobHealth3:GetUnitHealth(unit, currValue,maxValue)
	end
	if currValue > maxValue then
		maxValue = currValue
	end	
	local hpDiff = maxValue - currValue
	if currValue > 9999 then
		currValue = string.format("%.1fk", currValue / 1000)
	end
	if maxValue > 9999 then
		maxValue = string.format("%.1fk", maxValue / 1000)
	end	
	
	if not flag and MHfound and not UnitIsFriend("player", unit) then
		return 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
				if hpDiff > 9999 then
					hpDiff = string.format("%.1fk", hpDiff / 1000)
				end			
				return (currValue.."|cffff7f7f-"..hpDiff.."|r")
			else
				return currValue
			end
		elseif flag == 3 and hpDiff > 0 then
			if hpDiff > 9999 then
				hpDiff = string.format("%.1fk", hpDiff / 1000)
			end
			return "|cffff7f7f-"..hpDiff.."|r"
		elseif flag == 3 then
			return ""
		else
			return (currValue.."/"..maxValue)
		end
	else
		return string.format("%.0f%%", perc)
	end
	return text
end






-- Blizzard hide and show

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	
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()
	self:Hook("RaidOptionsFrame_UpdatePartyFrames", function() end)
	for i=1,4 do
		local frame = getglobal("PartyMemberFrame"..i)
		frame:UnregisterAllEvents()
		frame:Hide()
	end
end

function aUF:ShowBlizzParty()
	self:Unhook("RaidOptionsFrame_UpdatePartyFrames")
	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("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_TARGET_CHANGED")
	ComboFrame:UnregisterEvent("PLAYER_COMBO_POINTS")
end

function aUF:ShowBlizzTarget()
	TargetFrame:RegisterEvent("PLAYER_TARGET_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_TARGET_CHANGED")
	ComboFrame:RegisterEvent("PLAYER_COMBO_POINTS")
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
