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

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

-- UNIT CLASS

---- init
---- CreateFrame (creates the unit frame)
---- LoadPosition (loads frame position from DB)
---- ApplyTheme (reads and applies theme from ag_Themes.lua)
---- BorderBackground (sets a border and a background for the unit frame)

---- UpdateAll (calls all update methods for the unit)
---- UpdateName (updates the name string)
---- UpdateClass (updates the class string)
---- UpdateHealth (updates the health bar)
---- UpdatePower (updates the mana bar)

---- OnDragStop
---- OnDragStart

aUF.classes = {}
aUF.classes.aUFunit = AceOO.Class("AceEvent-2.0","AceHook-2.0")
aUF.classes.aUFunitXP = AceOO.Class(aUF.classes.aUFunit)
aUF.classes.aUFunitCombo = AceOO.Class(aUF.classes.aUFunit)
aUF.classes.aUFunitMetro = AceOO.Class(aUF.classes.aUFunit)
aUF.classes.aUFunitRaid = AceOO.Class(aUF.classes.aUFunit)

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.hookSetText(frame)
	local settext = frame.SetText
	frame.SetText = function(self, text)
		if (self.lasttext ~= text) then
			self.lasttext = text
			settext(self, text)
		end
	end
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

--[[function aUF.hooks.hookSetVertexColor(frame)
	local setvertexcolor = frame.SetVertexColor;
	frame.SetVertexColor = function(self, r, g, b)
		if (self.lastr ~= r or self.lastg ~= g or self.lastb ~= b) then
			self.lastr, self.lastg, self.lastb = r, g, b
			setvertexcolor(self, r, g, b)
		end
	end
end]]

function aUF.classes.aUFunit.prototype:init(name,unit,db)
	aUF.classes.aUFunit.super.prototype.init(self)
	
	self.name = name
	self:CreateFrame()
	self:Reset(unit,db)
	self.eventsRegistered = false
	self:RegisterEvents(true)
end

function aUF.classes.aUFunit.prototype:Reset(unit,db)
	if unit then
		self.unit = unit
		if not db then
			self.type = string.gsub(unit, "%d", "")
		else
			self.type = db
		end
		_,_,self.number = string.find(unit, "(%d+)")
		if not self.number then
			self.number = 1
		end
		if string.find(unit,"pet") then
			if self.type == "partypet" or self.type == "raidpet" then
				self.parent = string.gsub(unit,"pet","")
			else
				self.parent = "player"
			end
		end
	end
	self.flags = {}
	self.aCount = 0
	self.database = aUF.db.profile[self.type]
	self:LoadScale()
	self:LoadPosition()
	self:ApplyTheme()
	self:BorderBackground()
	self:BarTexture()
	self:StatusBarsColor()
	self:UpdateAll()
end

function aUF.classes.aUFunit.prototype:RegisterEvents(allEvents,unregister)
	if not unregister and self.eventsRegistered == false then
		if self.unit == "player" or self.unit == "target" then
			self:RegisterEvent("UNIT_HEALTH", "UpdateHealth")
			self:RegisterEvent("UNIT_MANA",	"UpdatePower")
			self:RegisterEvent("UNIT_RAGE", "UpdatePower")
			self:RegisterEvent("UNIT_FOCUS", "UpdatePower")
			self:RegisterEvent("UNIT_ENERGY", "UpdatePower")
		else
			self:RegisterBucketEvent("UNIT_HEALTH",0.3, "UpdateHealth")
			self:RegisterBucketEvent({"UNIT_MANA","UNIT_RAGE","UNIT_FOCUS","UNIT_ENERGY"},0.5, "UpdatePower")
		end
		self:RegisterEvent("UNIT_AURA", "UpdateAuras")		
		self:RegisterEvent("UNIT_COMBAT","UnitCombat")
		self:RegisterEvent("UNIT_SPELLMISS","UnitSpellmiss")		
		self:RegisterEvent("UNIT_LEVEL", "UpdateTextStrings")
		self:RegisterEvent("UNIT_NAME_UPDATE", "UpdateTextStrings")
		self:RegisterEvent("UPDATE_FACTION", "UpdatePvP")
		self:RegisterEvent("PLAYER_FLAGS_CHANGED", "UpdatePvP")
		self:RegisterEvent("UNIT_FACTION", "UpdatePvP")
		self:RegisterEvent("PARTY_LEADER_CHANGED", "LabelsCheckLeader")
		self:RegisterEvent("PARTY_LOOT_METHOD_CHANGED", "LabelsCheckLoot")
		self:RegisterEvent("RAID_TARGET_UPDATE", "UpdateRaidTargetIcon")
	
		-- Specific Events :(
		if self.type == "player" then
		   self:RegisterEvent("PLAYER_REGEN_ENABLED", "UpdateInCombat")
		   self:RegisterEvent("PLAYER_REGEN_DISABLED", "UpdateInCombat")
		   self:RegisterEvent("PLAYER_UPDATE_RESTING", "UpdateResting")
		else
			if not self.inCombatSchedule then
				self.inCombatSchedule = self:ScheduleRepeatingEvent(self.UpdateInCombat, 0.5, self)
			end
		end
		if self.type == "partypet" or self.type == "pet" then
			self:RegisterEvent("UNIT_PET","UpdatePetAll")
		end
		
		if self.type == "pet" then
			self:RegisterEvent("UNIT_HAPPINESS","StatusBarsColor")
		end
			
		if allEvents == true then
			self:RegisterEvent("PLAYER_TARGET_CHANGED","UpdateHighlight")
			self:RegisterEvent("PARTY_MEMBERS_CHANGED","UpdateAll")
			self:RegisterEvent("RAID_ROSTER_UPDATE","UpdateAll")
			self:RegisterEvent("agUF_UpdateGroups", "UpdateVisibility")
		end
		self.eventsRegistered = true
	elseif self.eventsRegistered == true and unregister then
		local events = {
		   "UNIT_AURA", "UNIT_HEALTH", "UNIT_MANA", "UNIT_RAGE",
		   "UNIT_FOCUS", "UNIT_ENERGY", "UNIT_COMBAT", "UNIT_SPELLMISS",
		   "UNIT_LEVEL", "UNIT_NAME_UPDATE", "UPDATE_FACTION",
		   "PLAYER_FLAGS_CHANGED",
		   "PARTY_LEADER_CHANGED", "PARTY_LOOT_METHOD_CHANGED",
		   "PLAYER_REGEN_ENABLED", "PLAYER_REGEN_DISABLED",
		   "PLAYER_UPDATE_RESTING", "RAID_TARGET_UPDATE",
		}
		for k,v in pairs(events) do
			if self:IsEventRegistered(v) then
				self:UnregisterEvent(v)
			end
		end
		if self.inCombatSchedule then
			self:CancelScheduledEvent(self.inCombatSchedule)
			self.inCombatSchedule = nil
		end
		self:UnregisterAllBucketEvents()
		self.eventsRegistered = false
	end
end

function aUF.classes.aUFunit.prototype:CreateFrame()
	local frameName = "aUF"..self.name
	self.framename = frameName
	
	self.frame = CreateFrame("Button",frameName,UIParent,"AGUnitTemplate")
	self.frame.name = self.name
	
	self.ClassText = getglobal(frameName.."_ClassText")
	self.NameLabel = getglobal(frameName.."_NameLabel")
	self.HitIndicator = getglobal(frameName.."_HitIndicator")
	self.HealthBar_BG = getglobal(frameName.."_HealthBar_BG")
	self.ManaBar_BG = getglobal(frameName.."_ManaBar_BG")
	self.XPBar_BG = getglobal(frameName.."_XPBar_BG")
	self.HealthBar = getglobal(frameName.."_HealthBar")
		self.HealthBar:SetScript("OnValueChanged",function() self:StatusBarsOnValueChanged(arg1) end)
		self.HealthBar:SetMinMaxValues(0,100)
	self.ManaBar = getglobal(frameName.."_ManaBar")
		self.ManaBar:SetMinMaxValues(0,100)
	self.XPBar = getglobal(frameName.."_XPBar")
		self.XPBar:SetMinMaxValues(0, 100)
	self.HealthText = getglobal(frameName.."_HealthText")
	self.ManaText = getglobal(frameName.."_ManaText")
	self.StatusText = getglobal(frameName.."_StatusText")
	self.Highlight = getglobal(frameName.."Highlight")
		self.Highlight:SetAlpha(0.5)
	self.DebuffHighlight = getglobal(frameName.."Debuff")
		self.DebuffHighlight:SetAlpha(0.7)
	self.RaidTargetIcon = getglobal(frameName.."_RaidTargetIcon")
	self.InCombatIcon = getglobal(frameName.."_InCombatIcon")
	self.PVPIcon = getglobal(frameName.."_PVPIcon")
	self.LeaderIcon = getglobal(frameName.."_LeaderIcon")
	self.MasterIcon = getglobal(frameName.."_MasterIcon")
	self.frame:SetScript("OnEnter",function() self:OnEnter() end)
	self.frame:SetScript("OnLeave",function() self:OnLeave() end)
	self.frame:SetScript("OnDragStart",function() self:OnDragStart(arg1) end)
	self.frame:SetScript("OnDragStop",function() self:OnDragStop(arg1) end)
	self.frame:SetScript("OnClick",function() self:OnClick(arg1) end)
	self.frame:SetScript("OnHide",function() this:StopMovingOrSizing() end)
	
	for i =1,20 do
		self["Aura"..i] = getglobal(frameName.."_Aura"..i)
		self["Aura"..i].Icon = getglobal(frameName.."_Aura"..i.."Icon")
		self["Aura"..i].Overlay = getglobal(frameName.."_Aura"..i.."Overlay")
		self["Aura"..i].Count = getglobal(frameName.."_Aura"..i.."Count")
		self["Aura"..i]:SetScript("OnEnter",function() self:AuraOnEnter() end)
		self["Aura"..i]:SetScript("OnLeave",function() GameTooltip:Hide() end)

		aUF.hooks.hookShowHide(self["Aura"..i])
		aUF.hooks.hookSetTexture(self["Aura"..i].Icon)
		
		self["Aura"..i]:Hide()
	end

	if string.find(self.name,"player") then
		self.XPBar_Rest = CreateFrame("StatusBar",frameName.."_XPBar_Rest",self.frame)
		self.XPBar_Rest:SetMinMaxValues(0, 100)
		self.XPBar:SetParent(self.XPBar_Rest)
	end

	if AceOO.inherits(self, aUF.classes.aUFunitCombo) then
		self:CreateCombos()
	end

	self.frame:SetMovable(true)
	self.frame:EnableMouse(true)
	self.frame:RegisterForDrag("LeftButton")
	self.frame:RegisterForClicks("LeftButtonUp","RightButtonUp","MiddleButtonUp","Button4Up","Button5Up")
end

function aUF.classes.aUFunit.prototype:LoadScale()
	self.frame:SetScale(self.database.Scale)
	if self.subgroup then
		aUF.subgroups[self.subgroup]:LoadPosition()
		aUF.subgroups[self.subgroup]:UpdateScale()
	end
end

function aUF.classes.aUFunit.prototype:LoadPosition()
	if self.subgroup then return end
	if(aUF.db.profile.Positions[self.unit]) then
		local x = aUF.db.profile.Positions[self.unit].x
		local y = aUF.db.profile.Positions[self.unit].y
		local scale = self.frame:GetEffectiveScale()
		
		self.frame:SetPoint("TOPLEFT", UIParent,"TOPLEFT", x/scale, y/scale)
	else
		self.frame:SetPoint("CENTER", UIParent, "CENTER")
	end
end

function aUF.classes.aUFunit.prototype:SavePosition()
	local scale = self.frame:GetEffectiveScale()
	local worldscale = UIParent:GetEffectiveScale()
	
	local x,y = self.frame:GetLeft()*scale,self.frame:GetTop()*scale - (UIParent:GetTop())*worldscale
	if not aUF.db.profile.Positions[self.unit] then 
		aUF.db.profile.Positions[self.unit] = {}
	end
	
	aUF.db.profile.Positions[self.unit].x = x
	aUF.db.profile.Positions[self.unit].y = y
end

function aUF.classes.aUFunit.prototype:ApplyTheme()
		local themetable = aUF.Layouts[self.database.FrameStyle]
		if not themetable then return end
		
		local hiddens = {}
		
		local manabarhide = false
		local xpbarhide = false
		local height = 0
		local width = 0
		
		if self.database.HideMana == true then
			manabarhide = true
		end

		if (self.unit ~= "player" and self.unit ~= "pet") or ((self.unit == "pet" or self.unit == "player") and self.database.ShowXP  == false) then
			xpbarhide = true
		end
		
		self.flags.ResizableBar = themetable.ResizableBar
		self.flags.BackgroundBarColor = themetable.BackgroundBarColor
		self.flags.AlphaBar = themetable.AlphaBar
		self.flags.RaidColorName = themetable.RaidColorName
		self.flags.ThemeName = themetable.Name
		self.flags.PetClassName = themetable.PetClassName
		self.flags.HappinessBar = themetable.HappinessBar
		
		if self.unit == "target" then
			if themetable.ComboGFX == true then
				comboGFX = 1
			else
				comboGFX = 0
			end
		end
		
		height = themetable.ThemeData.all.FrameHeight
		width = themetable.ThemeData.all.FrameWidth
		
		if themetable.ThemeData[self.type] then
			if themetable.ThemeData[self.type].FrameHeight then
				height = themetable.ThemeData[self.type].FrameHeight
			end
			if themetable.ThemeData[self.type].FrameWidth then
				width = themetable.ThemeData[self.type].FrameWidth	
			end
		end
		
		if manabarhide == true then
			self.flags.RaidColorName = true
		end
		
		for k,v in themetable.ThemeData.all do
			if self[k] then self[k]:ClearAllPoints() end
		end
		local index = "all"
		for j = 1,2 do
			if j == 2 then
				index = self.type
			end
			if themetable.ThemeData[index] then
				for key, value in pairs(themetable.ThemeData[index]) do
					if self[key] and value.Hidden ~= true and not (key == "ManaBar_BG" and manabarhide == true) and not (key == "XPBar_BG" and xpbarhide == true) and not hiddens[key] then
						
						if value.Hide then
							hiddens[value.Hide] = true
						end
						if value.HeightAdd then
							height = height + value.HeightAdd
						end						
						if value.Width then
							self[key]:SetWidth(value.Width)
						end
						if value.Height then
							self[key]:SetHeight(value.Height)
						end
						if value.Font then
							self[key]:SetFont(value.Font,value.FontSize)
						end
						local RelativeTo
						if value.RelativeTo then
							if themetable.ThemeData[index][value.RelativeTo] and (themetable.ThemeData[index][value.RelativeTo].Hidden == true or (value.RelativeTo == "ManaBar_BG" and manabarhide)) and value.RelativeToSecondary then
								RelativeTo = self.framename.."_"..value.RelativeToSecondary
							else
								RelativeTo = self.framename.."_"..value.RelativeTo
							end
						else
							RelativeTo = self.framename
						end
						if value.x and value.y and value.Point and value.RelativePoint then
							local point
							if themetable.ResizableBar == true and self.database.LongStatusbars == false and (key == "HealthText" or key == "ManaText") then
								if value.Point == "RIGHT" then 
									point = "LEFT"
								elseif value.Point == "LEFT" then 
									point = "RIGHT"
								else
									point = value.Point
								end
							else
								point = value.Point
							end
							self[key]:SetPoint(point, RelativeTo, value.RelativePoint, value.x, value.y)
						end
						if value.Visibility then
							for k, v in pairs(value.Visibility) do
								if self[v] then
									self[v]:Show()
								end
							end
						end
						if value.Justify then
							self[key]:SetJustifyH(value.Justify)
						end
					elseif self[key] and (value.Hidden or (key == "ManaBar_BG" and manabarhide == true) or (key == "XPBar_BG" and xpbarhide == true) ) then
						self[key]:Hide()
						if value.Visibility then
							for k, v in pairs(value.Visibility) do
								if self[v] then
									self[v]:Hide()
								end
							end
						end
					end
				end	
			end
		end
		
		for key,value in pairs(hiddens) do
			self[key]:Hide()
		end
	
	self.frame:SetHeight(height)
	self.frame:SetWidth(100)
	if self.widthAdd then
		self.database.Width = width
	end
	
	if self.flags.ResizableBar == true and self.database.LongStatusbars == false then
		self.HealthBar_BG:SetWidth(self.HealthBar_BG:GetWidth() - self.HealthText:GetWidth())
		self.ManaBar_BG:SetWidth(self.ManaBar_BG:GetWidth() - self.ManaText:GetWidth())
	end
	
	self.widthAdd = 0
	self:SetWidth()
end

function aUF.classes.aUFunit.prototype:BorderBackground()
	local colortable
	local bordercolor = aUF.db.profile.FrameBorderColors
	local borderstyle = aUF.db.profile.BorderStyle
	
	if self.unit == "target" then
		colortable = aUF.db.profile.TargetFrameColors
	else
		colortable = aUF.db.profile.PartyFrameColors
	end
	
	self.frame:SetBackdrop({
				bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16,
				edgeFile = aUF.Borders[borderstyle].texture, edgeSize = aUF.Borders[borderstyle].size,
				insets = {left = aUF.Borders[borderstyle].insets, right = aUF.Borders[borderstyle].insets, top = aUF.Borders[borderstyle].insets, bottom = aUF.Borders[borderstyle].insets},
		})
							
	self.frame:SetBackdropColor(colortable.r,colortable.g,colortable.b,colortable.a)
	self.frame:SetBackdropBorderColor(bordercolor.r,bordercolor.g,bordercolor.b,bordercolor.a)		
end

function aUF.classes.aUFunit.prototype:SetWidth()
	local widthAdd = 100
	if self.database.Width then widthAdd = self.database.Width end
	if not self.widthAdd then self.widthAdd = 0 end
	widthAdd = widthAdd - 100
	
	widthAdd =  widthAdd - self.widthAdd
	self.widthAdd = self.widthAdd + widthAdd
	
	self.frame:SetWidth(self.frame:GetWidth() + widthAdd)
	self.HealthBar_BG:SetWidth(self.HealthBar_BG:GetWidth() + widthAdd)
	self.ManaBar_BG:SetWidth(self.ManaBar_BG:GetWidth() + widthAdd)
	self.XPBar_BG:SetWidth(self.XPBar_BG:GetWidth() + widthAdd)
	
	if self.XPBar_Rest then
		self.XPBar_Rest:ClearAllPoints()
		self.XPBar_Rest:SetPoint("LEFT",self.XPBar_BG,"LEFT")
		self.XPBar_Rest:SetHeight(self.XPBar_BG:GetHeight())
		self.XPBar_Rest:SetWidth(self.XPBar_BG:GetWidth())
	end
	if self.XPBar then
		self.XPBar:ClearAllPoints()
		self.XPBar:SetPoint("LEFT",self.XPBar_BG,"LEFT")	
		self.XPBar:SetHeight(self.XPBar_BG:GetHeight())
		self.XPBar:SetWidth(self.XPBar_BG:GetWidth())
	end
	if self.HealthBar then
		self.HealthBar:ClearAllPoints()
		self.HealthBar:SetPoint("LEFT",self.HealthBar_BG,"LEFT")	
		self.HealthBar:SetHeight(self.HealthBar_BG:GetHeight())
		self.HealthBar:SetWidth(self.HealthBar_BG:GetWidth())				
	end
	if self.ManaBar then
		self.ManaBar:ClearAllPoints()
		self.ManaBar:SetPoint("LEFT",self.ManaBar_BG,"LEFT")		
		self.ManaBar:SetHeight(self.ManaBar_BG:GetHeight())
		self.ManaBar:SetWidth(self.ManaBar_BG:GetWidth())
	end
	self.Highlight:SetHeight(self.frame:GetHeight()-10)
	self.Highlight:SetWidth(self.frame:GetWidth()-10)
	self.DebuffHighlight:SetHeight(self.frame:GetHeight()-10)
	self.DebuffHighlight:SetWidth(self.frame:GetWidth()-10)
		
	if self.subgroup then
		aUF.subgroups[self.subgroup]:UpdateWidth()
	end
	
	self:AuraPosition()
end

function aUF.classes.aUFunit.prototype:BarTexture()
	local barstyle = aUF.db.profile.BarStyle
	
	self.HealthBar:SetStatusBarTexture(aUF.Bars[barstyle])
	self.ManaBar:SetStatusBarTexture(aUF.Bars[barstyle])
	self.XPBar:SetStatusBarTexture(aUF.Bars[barstyle])
	if self.XPBar_Rest then
		self.XPBar_Rest:SetStatusBarTexture(aUF.Bars[barstyle])
	end
	self.HealthBar_BG:SetTexture(aUF.Bars[barstyle])
	self.ManaBar_BG:SetTexture(aUF.Bars[barstyle])
	self.XPBar_BG:SetTexture(aUF.Bars[barstyle])			
end

-- CLASS UPDATES

function aUF.classes.aUFunit.prototype:UpdateHighlight(entered)
	if (UnitExists("target") and UnitName("target") == UnitName(self.unit) and not (string.find(self.unit,"target")) and aUF.db.profile.HighlightSelected == true) or (entered == true and aUF.db.profile.HighlightSelected == true) then
		self.Highlight:Show()
	else
		self.Highlight:Hide()
	end
end

function aUF.classes.aUFunit.prototype:UpdatePetAll()
	if arg1 ~= self.parent then return end
	self:UpdateAll()
end

function aUF.classes.aUFunit.prototype:UpdateAll()
	if self:SetVisibility() then
		self:GroupingUpdate()
		self:StatusBarsColor()
		self:UpdateHealth(true)
		self:UpdatePower(true)
		self:UpdatePvP(true)
		self:UpdateAuras(true)
		self:UpdateRaidTargetIcon(true)
		self:UpdateResting()
		self:UpdateInCombat()
		self:LabelsCheckLeader()
		self:UpdateHighlight()
		self:UpdateTextStrings()
		self:RegisterEvents()
		return true
	else
		self:GroupingUpdate(true)
		self:RegisterEvents(false,true)
		return false
	end
end

function aUF.classes.aUFunit.prototype:GroupingUpdate(hide)
	local oldGroup = self.subgroup
	
	if hide then
		self.subgroup = nil
	elseif string.find(self.type,"raid") then
	
		if aUF.db.profile.RaidGrouping == "byclass" then
			_, _, _, _, _, self.subgroup = GetRaidRosterInfo(self.number)	
		elseif aUF.db.profile.RaidGrouping == "nogroup" then
			self.subgroup = nil
		elseif aUF.db.profile.RaidGrouping == "onebiggroup" then
			self.subgroup = "Raid"
		elseif aUF.db.profile.RaidGrouping == "byrole" then
			local _,eClass = UnitClass(self.unit)
			self.subgroup = "Raid"..(aUF.RaidRole[eClass] or "none")		
		else
			_,_,self.subgroup = GetRaidRosterInfo(self.number)
		end
		
	elseif self.type == "party" or self.type == "partypet" then
	
		if aUF.db.profile.PartyGrouping == "withoutplayer" then
			self.subgroup = "partyParty"
		elseif aUF.db.profile.PartyGrouping == "nogroup" then
			self.subgroup = nil
		else
			self.subgroup = "partyPlayer"
		end
		
	elseif self.type == "pet" then
	
		if aUF.db.profile.PetGrouping == "nogroup" then
			self.subgroup = nil
		else
			self.subgroup = "partyPlayer"
		end
		
	elseif self.type == "player" then
	
		self.subgroup = "partyPlayer"
		
	end
	
	if oldGroup ~= self.subgroup then
		if oldGroup then
			aUF.changedSubgroups[oldGroup] = true
			if aUF.subgroups[oldGroup].group[self.type] and aUF.subgroups[oldGroup].group[self.type][self.name] then
				aUF.subgroups[oldGroup].group[self.type][self.name] = nil
			end
		end
		
		if self.subgroup then
			if not aUF.subgroups[self.subgroup] then
				aUF.subgroups[self.subgroup] = aUF.classes.aUFgroup:new(self.subgroup)
			end
			if not aUF.subgroups[self.subgroup].group[self.type] then
				aUF.subgroups[self.subgroup].group[self.type] = {}
			end
			aUF.subgroups[self.subgroup].group[self.type][self.name] = self
			aUF.changedSubgroups[self.subgroup] = true
		end
		
		self:ScheduleEvent("UpdateGroups", function() aUF:TriggerEvent("agUF_UpdateGroups") end, 0.1, self)
	elseif self.subgroup then
		self:UpdateVisibility()
	end
	if self.subgroup == nil then
		self:LoadPosition()
		self:UpdateVisibility()
	end
end

function aUF.classes.aUFunit.prototype:SetVisibility()
	if aUF:CheckVisibility(self.unit) == true then
		self.visible = true
		return true
	else
		self.visible = false
		return false
	end
end

function aUF.classes.aUFunit.prototype:UpdateVisibility()
	if self.visible == true then
		self.frame:Show()
	else
		self.frame:Hide()
	end
end

function aUF.classes.aUFunit.prototype:LabelsCheckLeader()
	self.LeaderIcon:Hide()
	if not ( self.type == "raid" or self.type == "party" or self.unit == "player") then return end
	if aUF.db.profile.ShowGroupIcons == true then
		if self.type == "raid" then
			local _, rank = GetRaidRosterInfo(self.number)
			if rank == 2 then
				self.LeaderIcon:Show()
			end
		elseif self.type == "party" and tonumber(GetPartyLeaderIndex()) == tonumber(self.number) then
			self.LeaderIcon:Show()
		elseif self.unit == "player" and IsPartyLeader() then
			self.LeaderIcon:Show()
		end
	end
end

function aUF.classes.aUFunit.prototype:LabelsCheckLoot()
	self.MasterIcon:Hide()
	if not ( self.unit == "player" or self.type == "party") then return end
	if aUF.db.profile.ShowGroupIcons == true then
		local _, lootMaster = GetLootMethod()
		if lootMaster then
			if self.unit == "player" and lootMaster == 0 then
				self.MasterIcon:Show()
			elseif self.unit ~= "player" and lootMaster > 0 then
				if lootMaster == self.number and not (string.find(self.unit,"pet")) then
					self.MasterIcon:Show()
				end		
			end
		end
	end
end

function aUF.classes.aUFunit.prototype:UpdateRaidTargetIcon(byevent)
	if type(byevent) == "string" and byevent ~= self.unit then return end

	local index = GetRaidTargetIndex(self.unit)
	if ( index ) and aUF.db.profile[self.type].ShowRaidTargetIcon == true then
		SetRaidTargetIconTexture(self.RaidTargetIcon, index)
		self.RaidTargetIcon:Show()
	else
		self.RaidTargetIcon:Hide()
	end
end

function aUF.classes.aUFunit.prototype:UpdateInCombat()
	if aUF.db.profile[self.type].ShowInCombatIcon == true and UnitAffectingCombat(self.unit) then
		self.combat = true
--		print(self.unit)
	else
		self.combat = false
	end
	self:UpdateStatusIcon()
end

function aUF.classes.aUFunit.prototype:UpdateResting()
	if self.unit ~= "player" then return end
	if IsResting() then
		self.resting = true
	else
		self.resting = false
	end
	self:UpdateStatusIcon()
end

function aUF.classes.aUFunit.prototype:UpdateStatusIcon()
	if self.combat == true then
		self.InCombatIcon:Show()
		self.InCombatIcon:SetTexCoord(0.5,1,0,0.5)
	elseif self.resting == true then
		self.InCombatIcon:Show()
		self.InCombatIcon:SetTexCoord(0,0.5,0,0.421875)
	else
		self.InCombatIcon:Hide()
	end
end

function aUF.classes.aUFunit.prototype:UpdatePvP(byevent)
	if type(byevent) == "string" and byevent ~= self.unit then return end
	if aUF.db.profile.ShowPvPIcon == true then
		if ( UnitIsPVPFreeForAll(self.unit) ) then
			self.PVPIcon:SetTexture("Interface\\TargetingFrame\\UI-PVP-FFA")
			self.PVPIcon:Show()	
		elseif ( UnitFactionGroup(self.unit) and UnitIsPVP(self.unit) ) then
			self.PVPIcon:SetTexture("Interface\\TargetingFrame\\UI-PVP-"..UnitFactionGroup(self.unit))
			self.PVPIcon:Show()
		else
			self.PVPIcon:Hide()
		end
	else
		self.PVPIcon:Hide()
	end
end

function aUF.classes.aUFunit.prototype:UpdateTextStrings()
	if self.visible then
		if aUF.HelperFunctions[self.type] then
			if aUF.HelperFunctions[self.type].HealthText and self.HealthText:IsShown() then
				aUF.HelperFunctions[self.type].HealthText(self.unit,self.HealthText)
			end
			if aUF.HelperFunctions[self.type].ManaText and self.ManaText:IsShown() then
				aUF.HelperFunctions[self.type].ManaText(self.unit,self.ManaText)
			end
			if aUF.HelperFunctions[self.type].NameText and self.NameLabel:IsShown() then
				aUF.HelperFunctions[self.type].NameText(self.unit,self.NameLabel)
			end
			if aUF.HelperFunctions[self.type].ClassText and self.ClassText:IsShown() then
				aUF.HelperFunctions[self.type].ClassText(self.unit,self.ClassText)
			end
		end
	end
end

function aUF.classes.aUFunit.prototype:UpdateHealth(byevent)
	if type(byevent) =="table" and not byevent[self.unit] then return end
	local currValue,maxValue = UnitHealth(self.unit),UnitHealthMax(self.unit)
    local perc = currValue/maxValue * 100
	
	if ( not UnitExists(self.unit) or UnitIsDead(self.unit) or UnitIsGhost(self.unit) or not UnitIsConnected(self.unit) or maxValue == 1) then
		self.HealthBar:SetValue(0)
	else			
		self.HealthBar:SetValue(perc)
	end
	
	self:UpdateTextStrings()
end

function aUF.classes.aUFunit.prototype:UpdatePower(byevent)
	if type(byevent) =="table" and not byevent[self.unit] then return end
	local currValue,maxValue = UnitMana(self.unit),UnitManaMax(self.unit)
    local perc = currValue/maxValue * 100	
	local db = aUF.db.profile
	
	if ( not UnitExists(self.unit) or UnitIsDead(self.unit) or UnitIsGhost(self.unit) or not UnitIsConnected(self.unit) or (currValue == 1 and maxValue == 1) ) then
		self.ManaBar:SetValue(0)
	else
		if maxValue == 0 then
			self.ManaBar:SetValue(0)
		else
			self.ManaBar:SetValue(perc)
		end
	end
	
	local powertype = UnitPowerType(self.unit)
	if (self.powertype ~= powertype) then
		self.powertype = powertype
		
		local info = db.ManaColor[powertype]
		if self.flags.AlphaBar == true then
			self.ManaBar_BG:SetVertexColor(info.r,info.g,info.b,0.25)
		else
			self.ManaBar_BG:SetVertexColor(0,0,0,0.25)
		end	
		self.ManaBar:SetStatusBarColor(info.r,info.g,info.b,0.8)
	end
	self:UpdateTextStrings()
end

function aUF.classes.aUFunit.prototype:AuraPosition()
	local scale = (self.frame:GetWidth()/170)
	local style,position = self.database.AuraStyle,self.database.AuraPos	
	local yadjust = 0

	for i=1,20 do
		self["Aura"..i]:SetScale(scale)
	end
	
	if not (style == "OneLine") and (position == "Right" or position == "Left") then
		yadjust = (self.Aura1:GetHeight()/2)
	end
	
	self.Aura1:ClearAllPoints()
	
	if ( position == "Below" ) then
		self.Aura1:SetPoint("TOPLEFT",self.frame,"BOTTOMLEFT",5, 0)
	elseif ( position == "Above" ) then
		self.Aura1:SetPoint("BOTTOMLEFT",self.frame,"TOPLEFT",5, 0)
	elseif ( position == "Left" ) then
		self.Aura1:SetPoint("RIGHT",self.frame,"LEFT",0, yadjust)
	elseif ( position == "Right" ) then
		self.Aura1:SetPoint("LEFT",self.frame,"RIGHT",0, yadjust)
	end

	if ( position == "Left" ) then
		for i=2,20 do
			self["Aura"..i]:ClearAllPoints()
			if i == 11 then
				self["Aura"..i]:SetPoint("TOP",self.Aura1,"BOTTOM",0,-1)
			else
				self["Aura"..i]:SetPoint("RIGHT",self["Aura"..i-1],"LEFT",1,0)
			end
		end	
	else
		for i=2,20 do
			self["Aura"..i]:ClearAllPoints()
			if i == 11 then
				if position == "Above" then
					self["Aura"..i]:SetPoint("BOTTOM",self.Aura1,"TOP",0,1)
				else
					self["Aura"..i]:SetPoint("TOP",self.Aura1,"BOTTOM",0,-1)
				end
			else
				self["Aura"..i]:SetPoint("LEFT",self["Aura"..i-1],"RIGHT",1,0)
			end
		end	
	end	
end

function aUF.classes.aUFunit.prototype:UpdateAuras(byevent)
	if type(byevent) == "string" and byevent ~= self.unit then return end
	
	if aUF.auraUpdates > 4 then 
		aUF.auraUpdatePool[self.name] = true
--		print(self.name.." add to pool")
		return 
	else
--		print(self.name.." update "..aUF.auraUpdates)
		aUF.auraUpdatePool[self.name] = nil 
		aUF.auraUpdates = aUF.auraUpdates + 1
	end
	
	local filter,style,AuraDebuffC = self.database.AuraFilter,self.database.AuraStyle,self.database.AuraDebuffC
	local dbcount,bcount,lastDebuff = 0,0,0
	local buttons,dFound
	
	self.DebuffHighlight:Hide()
	local hide = style == "Hide"
	
	for i=1,20 do
		if (not self.hidden) then self["Aura"..i]:Hide() end
		local debuff, _, t = aUF:UnitDebuff(self.unit,i,filter)
		if debuff then
			dbcount = dbcount + 1
			lastDebuff = i
			if not dFound then
				if t and AuraDebuffC == true and UnitIsFriend("player",self.unit) then
					self.DebuffHighlight:Show()
					self.DebuffHighlight:SetVertexColor(DebuffTypeColor[t].r, DebuffTypeColor[t].g, DebuffTypeColor[t].b)
					dFound = true
				end
			end
		end
		if UnitBuff(self.unit,i,filter) then
			bcount = bcount + 1
		end		
	end
	
	if hide or bcount + dbcount == 0 then
		self.hidden = true
		return
	end
	self.hidden = false
	
	local position = self.database.AuraPos
	
	if (position == "Above" or position == "Below") and bcount + dbcount <= 10 then
		buttons = 10
	elseif style == "OneLine" then
		if (position == "Right" or position == "Left") and bcount + dbcount <= 10 then
			buttons = bcount + dbcount
		else
			buttons = 10
		end
	else
		buttons = 20
	end
	
	local x,z,a,borderColor
	local b = 1
	
	if (buttons > 10 and dbcount <= 10) then
		x = 11
		z = 1
		a = 10
	else
		x = buttons
		z = -1	
		a = bcount
	end
	
	for i=1,max(lastDebuff,a) do		
		local buff, count, class = aUF:UnitDebuff(self.unit,i,filter)
		local buffFrame = self["Aura"..x]
		if buff and buffFrame then
			buffFrame.Icon:SetTexture(buff)
			buffFrame:Show()
			buffFrame.buffFilter = "HARMFUL"
			buffFrame.id = i
			if count > 1 then
				buffFrame.Count:SetText(count)
			else
				buffFrame.Count:SetText("")
			end
			if class then
				borderColor = DebuffTypeColor[class]
			else
				borderColor = DebuffTypeColor["none"];
			end
			buffFrame.Overlay:SetVertexColor(borderColor.r, borderColor.g, borderColor.b);
			buffFrame.Overlay:Show()
			x = x + z
		end
		buff, count = UnitBuff(self.unit,i,filter)
		buffFrame = self["Aura"..b]
		if buff and b <= a then
			buffFrame.Icon:SetTexture(buff)
			buffFrame:Show()
			buffFrame.buffFilter = "HELPFUL"
			buffFrame.id = i
			if count > 1 then
				buffFrame.Count:SetText(count)
			else
				buffFrame.Count:SetText("")
			end
			buffFrame.Overlay:Hide()
			b = b + 1
		end		
	end
end
	
-- STATUSBAR STUFF

function aUF.classes.aUFunit.prototype:StatusBarsColor()
	local db = aUF.db.profile
	local healthColor
	local _,Eclass = UnitClass(self.unit)
	
	if string.find(self.unit,"target") and not UnitIsFriend(self.unit, "player") and (aUF.db.profile.TargetShowHostile == true ) then
		healthColor = aUF:UtilFactionColors(self.unit)
		self.flags.BarColor = 1
	elseif self.unit == "pet" and self.flags.HappinessBar == true and class ~= "WARLOCK" then
		local happiness = GetPetHappiness()
		if ( happiness == 1 ) then
			healthColor = aUF.ManaColor[1]
		elseif ( happiness == 2 ) then
			healthColor = aUF.ManaColor[3]
		else
			healthColor = db.HealthColor
		end
		self.flags.BarColor = 2
	elseif UnitIsFriend(self.unit, "player") and UnitIsPlayer(self.unit) and self.database.ClassColorBars == true and RAID_CLASS_COLORS[Eclass] then
		healthColor = RAID_CLASS_COLORS[Eclass]
		self.flags.BarColor = 3
	else
		healthColor = db.HealthColor
		self.flags.BarColor = 4
	end
	
	self.HealthBar:SetStatusBarColor(healthColor.r,healthColor.g,healthColor.b, 1)
	if self.flags.BackgroundBarColor == true then
		self.HealthBar_BG:SetVertexColor(healthColor.r,healthColor.g,healthColor.b,0.25)
	else
		self.HealthBar_BG:SetVertexColor(0,0,0,0.25)
	end

	-- mana
	local powertype = UnitPowerType(self.unit)
	local info = db.ManaColor[powertype]
	if self.flags.AlphaBar == true then
		self.ManaBar_BG:SetVertexColor(info.r,info.g,info.b,0.25)
	else
		self.ManaBar_BG:SetVertexColor(0,0,0,0.25)
	end	
	self.ManaBar:SetStatusBarColor(info.r,info.g,info.b,0.8)
end

function aUF.classes.aUFunit.prototype:StatusBarsOnValueChanged(value)
	if ( aUF.db.profile.SmoothHealthBars == true ) then
		if self.flags.BarColor == 1 then
			self:SmoothTargetHealthBarOnValueChanged(value,aUF:UtilFactionColors(self.unit))
		elseif self.flags.BarColor == 4 then
			self:SmoothHealthBarOnValueChanged(value)
		end
	end		
end

function aUF.classes.aUFunit.prototype:SmoothTargetHealthBarOnValueChanged(value,colortable)
	if ( not value ) then
		return
	end
	local r, g, b
	local min, max = this:GetMinMaxValues()
	if ( (value < min) or (value > max) ) then
		return
	end
	if ( (max - min) > 0 ) then
		value = (value - min) / (max - min)
	else
		value = 0
	end
	
	r = colortable.r*(0.35*value+0.65)
	g = colortable.g*(0.35*value+0.65)
	b = colortable.b*(0.35*value+0.65)
	this:SetStatusBarColor(r, g, b)
end
	
function aUF.classes.aUFunit.prototype:SmoothHealthBarOnValueChanged(value)
	if ( not value ) then
		return
	end
	local db = aUF.db.profile
	local r, g, b
	local min, max = this:GetMinMaxValues()
	if ( (value < min) or (value > max) ) then
		return
	end
	if ( (max - min) > 0 ) then
		value = (value - min) / (max - min)
	else
		value = 0
	end
	if(value > 0.5) then
		r = (db.HealthColor.r) + (((1-value) * 2)* (1-(db.HealthColor.r)))
		g = db.HealthColor.g
	else
		r = 1.0
		g = (db.HealthColor.g) - (0.5 - value)* 2 * (db.HealthColor.g)
	end
	b = db.HealthColor.b
	this:SetStatusBarColor(r, g, b)
end

-- MOUSE INTERACTION

function aUF.classes.aUFunit.prototype:OnDragStart(button)
	if self.subgroup then
		aUF.subgroups[self.subgroup]:OnDragStart(button)
		return
	end
	if ( button == "LeftButton" ) and aUF.db.profile.Locked == false then
		self.frame:StartMoving()
	end
end

function aUF.classes.aUFunit.prototype:OnDragStop(button)
	if self.subgroup then
		aUF.subgroups[self.subgroup]:OnDragStop(button)
		return
	end
	self.frame:StopMovingOrSizing()
	self:SavePosition()
end
	
function aUF.classes.aUFunit.prototype:OnClick(button)
	if (IsAltKeyDown() or IsControlKeyDown()) and (button == "LeftButton" or button == "RightButton") then
			aUF.dewdrop:Open(self.frame, 'children', aUF:CreateDewdrop(self.type),'cursorX', true, 'cursorY', true)
		return
	end
	if button == "LeftButton" then
		if SpellIsTargeting() then
			SpellTargetUnit(self.unit)
		elseif CursorHasItem() then
			if UnitIsUnit(self.unit, "player") then
				AutoEquipCursorItem()
			elseif UnitIsFriend(self.unit, "player") and UnitIsPlayer(self.unit) then
				DropItemOnUnit("target")
			end 
		else
			TargetUnit(self.unit)
		end		
	elseif button == "RightButton" then
		self:DropDownUnit(self.unit)
	end
end

function aUF.classes.aUFunit.prototype:OnEnter()
	self.frame.unit = self.unit
	self:UpdateHighlight(true)
	UnitFrame_OnEnter()
end

function aUF.classes.aUFunit.prototype:OnLeave()
	self:UpdateHighlight()
	UnitFrame_OnLeave()
end

function aUF.classes.aUFunit.prototype:DropDownUnit()
    local type = nil
    
    if self.unit == "player" then
        type = PlayerFrameDropDown
    elseif self.unit == "target" then
        type = TargetFrameDropDown
    elseif self.unit == "pet" then
        type = PetFrameDropDown
    elseif self.type == "party" then
        type = getglobal("PartyMemberFrame"..self.number.."DropDown")
    elseif string.find(self.unit, "raid") then
        type = FriendsDropDown
        this.unit = self.unit
        this.name = UnitName(self.unit)
        this.id = this:GetID()
		FriendsDropDown.displayMode = "MENU"
        FriendsDropDown.initialize = RaidFrameDropDown_Initialize
    end
    
    if self.number then this:SetID(self.number) end
    
    if type then
		HideDropDownMenu(1);
        type.unit = self.unit
        type.name = UnitName(self.unit)
        ToggleDropDownMenu(1, nil, type,"cursor")
        return true
    end
end

function aUF.classes.aUFunit.prototype:AuraOnEnter()
	if (not this:IsVisible()) then return end
	GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT")
	if ( this.buffFilter == "HELPFUL") then
		GameTooltip:SetUnitBuff(self.unit, this.id, self.database.AuraFilter)
	elseif ( this.buffFilter == "HARMFUL") then
		GameTooltip:SetUnitDebuff(self.unit, this.id, 0)		
	end
end

function aUF.classes.aUFunit.prototype:UnitCombat(unit)
	if unit ~= self.unit then return end
	if not ( self.database.ShowCombat ) then return end
	self:CombatFeedback_OnCombatEvent(arg1, arg2, arg3, arg4, arg5)
end

function aUF.classes.aUFunit.prototype:UnitSpellmiss(unit)
	if unit ~= self.unit then return end
	if not ( self.database.ShowCombat ) then return end	
	self:CombatFeedback_OnSpellMissEvent(arg1, arg2)
end

function aUF.classes.aUFunit.prototype:CombatFeedback_OnCombatEvent(unit, event, flags, amount, type)
	local fontHeight = 13
	local text = ""
	local r,g,b = 1,1,1
	if( event == "IMMUNE" ) then
		fontHeight = fontHeight * 0.75
		text = CombatFeedbackText[event]
	elseif ( event == "WOUND" ) then
		if ( amount ~= 0 ) then
			if ( flags == "CRITICAL" or flags == "CRUSHING" ) then
				fontHeight = fontHeight * 1.5
			elseif ( flags == "GLANCING" ) then
				fontHeight = fontHeight * 0.75
			end
			if ( type > 0 ) then
				r = 1.0
				g = 1.0
				b = 0.0
			end
			if UnitInParty(self.unit) or UnitInRaid(self.unit) then
				r = 1.0
				g = 0.0
				b = 0.0		
			end			
			text = "-"..amount
		elseif ( flags == "ABSORB" ) then
			fontHeight = fontHeight * 0.75
			text = CombatFeedbackText["ABSORB"]
		elseif ( flags == "BLOCK" ) then
			fontHeight = fontHeight * 0.75
			text = CombatFeedbackText["BLOCK"]
		elseif ( flags == "RESIST" ) then
			fontHeight = fontHeight * 0.75
			text = CombatFeedbackText["RESIST"]
		else
			text = CombatFeedbackText["MISS"]
		end
	elseif ( event == "BLOCK" ) then
		fontHeight = fontHeight * 0.75
		text = CombatFeedbackText[event]
	elseif ( event == "HEAL" ) then
		text = "+"..amount
		r = 0.0
		g = 1.0
		b = 0.0
		if ( flags == "CRITICAL" ) then
			fontHeight = fontHeight * 1.3
		end
	elseif ( event == "ENERGIZE" ) then
		text = amount
		r = 0.41
		g = 0.8
		b = 0.94
		if ( flags == "CRITICAL" ) then
			fontHeight = fontHeight * 1.3
		end
	else
		text = CombatFeedbackText[event]
	end
	
	self.feedbackStartTime = GetTime()
		
	local font = self.HitIndicator:GetFont()
	self.HitIndicator:SetFont(font,fontHeight,"OUTLINE")
	self.HitIndicator:SetText(text)
	self.HitIndicator:SetTextColor(r, g, b)
	self.HitIndicator:SetAlpha(0)
	self.HitIndicator:Show()
	self.HitIndicator:SetPoint("CENTER",self.frame,"CENTER")

	aUF.feedback[self.name] = true
	aUF:ScheduleRepeatingEvent("agUF_CombatSchedule",aUF.FeedbackUpdate, 0.05, aUF)
end

-- UNITXP CLASS

function aUF.classes.aUFunitXP.prototype:init(name,unit)
	aUF.classes.aUFunitXP.super.prototype.init(self,name,unit)
	self:RegisterXPEvents()
	self:UpdateXP()
	self:UpdateRep()
end

function aUF.classes.aUFunitXP.prototype:RegisterXPEvents()
	if self.unit == "player" then
		self:RegisterEvent("PLAYER_XP_UPDATE","UpdateXP")
		self:RegisterEvent("UPDATE_EXHAUSTION","UpdateXP")
		self:RegisterEvent("PLAYER_LEVEL_UP","UpdateXP")
	elseif self.unit == "pet" then
		self:RegisterEvent("UNIT_PET_EXPERIENCE","UpdateXP")
	end
end

function aUF.classes.aUFunitXP.prototype:UpdateRep(newLevel)
	if self.hooks["ReputationWatchBar_Update"] then
		self.hooks["ReputationWatchBar_Update"].orig(tonumber(newLevel))
	else
		self:Hook("ReputationWatchBar_Update", "UpdateRep")
	end
	local repname, repreaction, repmin, repmax, repvalue = GetWatchedFactionInfo()
	if ( repname and UnitLevel("player") == 60) then
		local color = aUF.RepColor[repreaction]
		repmax = repmax - repmin;
		repvalue = repvalue - repmin;
		repmin = 0
	
		if self.XPBar_Rest or repmax == 0 then
			self.XPBar_Rest:Hide()
		end
		
		self.XPBar:SetParent(self.frame)
		self.XPBar:Show()
		if repmax ~= 0 then
			self.XPBar:SetValue((repvalue/repmax)*100)
		else
			self.XPBar:SetValue(0)
		end
		self.XPBar:SetStatusBarColor(color.r, color.g, color.b)
		self.XPBar_BG:SetVertexColor(color.r, color.g, color.b, 0.25)
	end
	self:UpdateXP()
end

function aUF.classes.aUFunitXP.prototype:UpdateXP()
	local _,eClass = UnitClass("player")
	if self.unit == "pet" and eClass == "HUNTER" then
		return
	end
	local repname, repreaction, repmin, repmax, repvalue = GetWatchedFactionInfo();
	if ( self.database.ShowXP == true ) then
		if ((( UnitLevel("player") < MAX_PLAYER_LEVEL ) or not repname) and self.unit == "player") or (self.unit == "pet") then
			local priorXP = self.XPBar:GetValue()
			local restXP 
			local currXP, nextXP
			
			if self.unit == "player" then
				self.XPBar:SetParent(self.XPBar_Rest)
				currXP = UnitXP(self.unit)
				nextXP = UnitXPMax(self.unit)
				restXP = GetXPExhaustion()
			else
				currXP, nextXP = GetPetExperience()
			end
			
			if nextXP ~= 0 then
				self.XPBar:SetValue((currXP/nextXP)*100)
			else
				self.XPBar:SetValue(0)
			end
			
			if self.XPBar_Rest then
				if ( restXP and self.unit == "player" ) then
					self.XPBar_Rest:Show()
					if nextXP ~= 0 then
						self.XPBar_Rest:SetValue(((currXP+restXP)/nextXP)*100)
					else
						self.XPBar_Rest:SetValue(0)
					end
				else
					self.XPBar:SetParent(self.frame)
					self.XPBar:Show()
					self.XPBar_Rest:Hide()
				end
			end
			
			self.XPBar:SetStatusBarColor(0.8, 0, 0.7)
			if self.flags.BackgroundBarColor == true then
				self.XPBar_BG:SetVertexColor(0.8, 0, 0.7, 0.25)
			else
				self.XPBar_BG:SetVertexColor(0, 0, 0, 0.25)
			end
		end
	else
		self.XPBar:Hide()
		self.XPBar_BG:Hide()
		if self.XPBar_Rest then
			self.XPBar_Rest:Hide()
		end
	end
end

function aUF.classes.aUFunitCombo.prototype:init(name,unit)
	aUF.classes.aUFunitCombo.super.prototype.init(self,name,unit)
	self:RegisterComboEvents()
end

function aUF.classes.aUFunitCombo.prototype:RegisterComboEvents()
	self:RegisterEvent("PLAYER_COMBO_POINTS","UpdateComboPoints")
end

function aUF.classes.aUFunitCombo.prototype:CreateCombos()
	for i=1,5 do
		self["Combo"..i] = self.frame:CreateTexture(nil,"OVERLAY")
		self["Combo"..i]:SetTexture(aUF.imagePath.."combo.tga")
		self["Combo"..i]:SetHeight(10)
		self["Combo"..i]:SetWidth(10)
		self["Combo"..i]:Hide()
		if i > 1 then
			self["Combo"..i]:SetPoint("BOTTOMRIGHT",self["Combo"..i-1],"BOTTOMLEFT")
		end
	end
end

function aUF.classes.aUFunitCombo.prototype:UpdateComboPoints()
	local points = GetComboPoints()
	for i=0,4 do
		if points > i then
			self["Combo"..i+1]:Show()
		else
			self["Combo"..i+1]:Hide()
		end	
	end
end

function aUF.classes.aUFunitMetro.prototype:init(name,unit)
	aUF.classes.aUFunitMetro.super.prototype.init(self,name,unit)
end

function aUF.classes.aUFunitMetro.prototype:UpdateMetro()
	if self:SetVisibility() then
		self:UpdateHealth(true)
		self:UpdatePower(true)
		self:UpdateAuras(true)
		self:UpdateRaidTargetIcon(true)
		self:StatusBarsColor()
		self:UpdateTextStrings()
	end
	self:UpdateVisibility()
end
		
function aUF.classes.aUFunitMetro.prototype:Start()
	if not self.database.HideFrame == true then
		self:UpdateMetro()
		if not self.schedule then 
			self.schedule = self:ScheduleRepeatingEvent(self.UpdateMetro, 0.8, self)
		end
	end
end

function aUF.classes.aUFunitMetro.prototype:Stop()
	if self.schedule and self:IsEventScheduled(self.schedule) then
		self:CancelScheduledEvent(self.schedule)
		self.schedule = nil
	end
	self:UpdateMetro()
end

-- UNITRAID CLASS

function aUF.classes.aUFunitRaid.prototype:init(name,unit)
	aUF.classes.aUFunitRaid.super.prototype.init(self,name,unit)
	self:RegisterEvent("RAID_ROSTER_UPDATE","RosterUpdate")
	self:RosterUpdate()
end

function aUF.classes.aUFunitRaid.prototype:RosterUpdate()
	if aUF:CheckVisibility(self.unit) then
		self.inRaid = true
	end
	if self.inRaid == true then
		if self:UpdateAll() == true then
			self.inRaid = true
		else
			self.inRaid = false
		end
	end
end


-- Group class

aUF.classes.aUFgroup = AceOO.Class("AceEvent-2.0","AceHook-2.0")

function aUF.classes.aUFgroup.prototype:init(objectName)
	aUF.classes.aUFgroup.super.prototype.init(self)
	
	self.name = objectName
	self.variableName = self.name.."_aUFgroup"
	self.index = {}
	self.group = {}
	self.raid = true
	
	self:CreateFrame()
	self:BorderBackground()
	self:UpdateTitle()
end

function aUF.classes.aUFgroup.prototype:CreateFrame()
	local frameName = "aUFgroup"..self.name
	self.anchor = CreateFrame("Button",frameName,UIParent,"AGraidAnchorTemplate")
	self.anchor:SetScript("OnDragStart",function() self:OnDragStart(arg1) end)
	self.anchor:SetScript("OnDragStop",function() self:OnDragStop(arg1) end)
	self.anchor:SetScript("OnClick",function() self:OnClick(arg1) end)
	self.anchor:SetMovable(true)
	self.anchor:EnableMouse(true)
	self.anchor:RegisterForDrag("LeftButton")
	self.anchor:RegisterForClicks("LeftButtonUp","RightButtonUp","MiddleButtonUp","Button4Up","Button5Up")
	
	self.title = getglobal("aUFgroup"..self.name.."Title")
end

function aUF.classes.aUFgroup.prototype:Reset()
	self:UpdateTitle()
	self:LoadPosition()
end

function aUF.classes.aUFgroup.prototype:UpdateTitle(player)
	if self.raid then
		if player == true then
			self.title:SetText("Group "..self.name.." *")
		else
			self.title:SetText("Group "..self.name)
		end
	else
		self.title:SetText("Group "..self.name)
	end
end

--[[
function aUF.classes.aUFgroup.prototype.groupSortClosure()
	local unitIdIndex = {
		["player"]    = 1,
		["playerpet"] = 2,
		["party1"]    = 3,
		["party1pet"] = 4,
		["party2"]    = 5,
		["party2pet"] = 6,
		["party3"]    = 7,
		["party3pet"] = 8,
		["party4"]    = 9,
		["party4pet"] = 10,
	}

	return function (a, b)
		return (unitIdIndex[a.unit] or 99) < (unitIdIndex[b.unit] or 99)
	end
end

function aUF.classes.aUFgroup.prototype:EachMember(group)
	local i = 0
	local sortedGroup = {}

	for _,member in pairs(group) do
		table.insert(sortedGroup, member)
	end

	if not self.groupSort then
		self.groupSort = self.groupSortClosure()
	end

	if self.groupSort then
		table.sort(sortedGroup, self.groupSort)
	end

	return function ()
		i = i + 1
		return sortedGroup[i]
	end
end ]]

function aUF.classes.aUFgroup.prototype:Update()
	if self.lastFrame then
		self.lastFrame:StopMovingOrSizing()
	end
	self.lastFrame = nil
		
	local grow = "down"
	local relation1, relation2,x,y
	local space = 5
	local player = false
	
	if grow == "up" then
		relation1 = "BOTTOMLEFT"
		relation2 = "TOPLEFT"
		x = 0
		y = -(space)
	elseif grow == "down" then
		relation1 = "TOPLEFT"
		relation2 = "BOTTOMLEFT"
		x = 0
		y = space		
	elseif grow == "left" then
		relation1 = "TOPRIGHT"
		relation2 = "TOPLEFT"
		x = space
		y = 0		
	elseif grow == "right" then
		relation1 = "TOPLEFT"
		relation2 = "TOPRIGHT"
		x = -(space)
		y = 0		
	end
	
	self.index = {}
	
	if self.group.player and self.group.player.player then
		table.insert(self.index, self.group.player.player)
	end
	if self.group.pet and self.group.pet.pet then
		table.insert(self.index, self.group.pet.pet)
	end
	
	if self.group.party then
		for _,unitObject in self.group.party do
			table.insert(self.index, unitObject)
			if self.group.partypet then
				for _, unitPetObject in self.group.partypet do
					if unitPetObject.parent and unitPetObject.parent == unitObject.unit then
						table.insert(self.index, unitPetObject)
					end
				end
			end
		end
	end
	if self.group.raid then
		for _,unitObject in self.group.raid do
			table.insert(self.index, unitObject)
			if UnitName(unitObject.unit) == UnitName("player") then
				player = true
			end
			if self.group.raidpet then
				for _, unitPetObject in self.group.raidpet do
					if unitPetObject.parent and unitPetObject.parent == unitObject.unit then
						table.insert(self.index, unitPetObject)
					end
				end
			end
		end
	end
	
--	print("---"..self.name)
	local empty = true
	for k,v in ipairs(self.index) do
--		print(UnitName(v.unit))
		v.frame:ClearAllPoints()
		if self.index[k-1] then
			v.frame:SetPoint(relation1, self.index[k-1].frame,relation2,x,y)
		else
			empty = false
			self.lastFrame = v.frame
			self:LoadPosition()
			if self.raid then
				self.anchor:ClearAllPoints()
				self.anchor:SetPoint(relation2, self.lastFrame,relation1,-x,-y)
				self.anchor:Show()
			end
		end
	end
	if self.lastFrame then
		self.anchor:SetHeight(20)
		self:UpdateWidth()
		self:UpdateScale()
		self:UpdateTitle(player)
	end
	if empty == true or not self.lastFrame then
		self.anchor:Hide()
	end
end

function aUF.classes.aUFgroup.prototype:UpdateWidth()
	local width = 0
	local scale = 0
	if self.index then
		for _,unitObject in ipairs(self.index) do
			local lwidth = unitObject.frame:GetWidth()
			local swidth = unitObject.frame:GetWidth()*unitObject.frame:GetWidth()
			if lwidth > width then
				width = lwidth
				scale = unitObject.frame:GetScale()
			end
		end
	end
	self.anchor:SetWidth(width)
	if scale > 0 then
		self.anchor:SetScale(scale)
	end
end

function aUF.classes.aUFgroup.prototype:UpdateScale()
	self:UpdateWidth()
end

function aUF.classes.aUFgroup.prototype:BorderBackground()
	local colortable
	local borderstyle = aUF.db.profile.BorderStyle
	
	colortable = aUF.db.profile.PartyFrameColors
	
	self.anchor:SetBackdrop({
				bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16,
				edgeFile = aUF.Borders[borderstyle].texture, edgeSize = aUF.Borders[borderstyle].size,
				insets = {left = aUF.Borders[borderstyle].insets, right = aUF.Borders[borderstyle].insets, top = aUF.Borders[borderstyle].insets, bottom = aUF.Borders[borderstyle].insets},
		})
							
	self.anchor:SetBackdropColor(colortable.r,colortable.g,colortable.b,colortable.a)
	self.anchor:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r,TOOLTIP_DEFAULT_COLOR.g,TOOLTIP_DEFAULT_COLOR.b,colortable.a)								
end

function aUF.classes.aUFgroup.prototype:OnClick(button)
	for k,v in self.index do
--		print(v.name)
	end
end

function aUF.classes.aUFgroup.prototype:OnDragStart(button)
	if ( button == "LeftButton" ) and aUF.db.profile.Locked == false then
		self.lastFrame:StartMoving()
	end
end

function aUF.classes.aUFgroup.prototype:OnDragStop(button)
	if self.lastFrame then
		self.lastFrame:StopMovingOrSizing()
		self:SavePosition()
	end
end

function aUF.classes.aUFgroup.prototype:LoadPosition()
	if self.lastFrame then
		if (aUF.db.profile.Positions[self.variableName]) then
			local x = aUF.db.profile.Positions[self.variableName].x
			local y = aUF.db.profile.Positions[self.variableName].y
			local scale = self.lastFrame:GetEffectiveScale()
			
			self.lastFrame:SetPoint("TOPLEFT", UIParent,"TOPLEFT", x/scale, y/scale)
		else
			self.lastFrame:SetPoint("CENTER", UIParent, "CENTER")
		end
	end
end

function aUF.classes.aUFgroup.prototype:SavePosition()
	local scale = self.lastFrame:GetEffectiveScale()
	local worldscale = UIParent:GetEffectiveScale()
	
	local x,y = self.lastFrame:GetLeft()*scale,self.lastFrame:GetTop()*scale - (UIParent:GetTop())*worldscale

	if not aUF.db.profile.Positions[self.variableName] then 
		aUF.db.profile.Positions[self.variableName] = {}
	end
	
	aUF.db.profile.Positions[self.variableName].x = x
	aUF.db.profile.Positions[self.variableName].y = y
end
