local AceOO = AceLibrary("AceOO-2.0")
local L = AceLibrary("AceLocale-2.2"):new("ag_UnitFrames")
local print = function(msg) if msg then DEFAULT_CHAT_FRAME:AddMessage(msg) end end

-- Group class

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

local function ClassOnEvent(frame, event)
	if event == "PARTY_MEMBERS_CHANGED" and frame:IsVisible() then
		frame.object:UpdateTitle()
	end
end

function aUF.classes.aUFgroup.prototype:init(name,type,class,groupdb,unitdb,reset)
	aUF.classes.aUFgroup.super.prototype.init(self)

	self.name = name
	self.type = type
	self.class = class
	self.unitdb = unitdb

	self:CreateFrame()
	local self = self
	self.header.initialConfigFunction = function(child) self:SetInitial(child) end
	self.header:HookScript("OnEvent", ClassOnEvent)
	
	self.header:SetAttribute("template","AGUnitTemplate")
	self:SetDefaults(groupdb,reset)	
	self:UpdateAll()
end

function aUF.classes.aUFgroup.prototype:UpdateAll()
	self:BorderBackground()
	self:UpdateWidth()
	self:UpdateScale()
	self:LoadPosition()
	self:UpdateGrowth()
	self:UpdateGroupFilter()
	self:SetVisibility()	
	self:UpdateTitle()	
end

function aUF.classes.aUFgroup.prototype:SetDefaults(groupdb,reset)
	if not groupdb then
		groupdb = aUF.db.profile.subgroups[self.name]
	end
	if reset then
		local defaults = aUF_DEFAULT_OPTIONS.subgroups["**"]
		local nDefaults = aUF_DEFAULT_OPTIONS.subgroups[self.name]
		for k in pairs(groupdb) do
			groupdb[k] = nil
		end
		for k in pairs(defaults) do
			groupdb[k] = defaults[k]
		end
		if nDefaults then
			for k in pairs(nDefaults) do
				groupdb[k] = nDefaults[k]
			end
		end
		groupdb.Exists = true	
	end
	self.database = groupdb
end

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

function aUF.classes.aUFgroup.prototype:CreateFrame()
	local frameName = "aUF"..self.name.."Anchor"
	local frameNameHeader = "aUF"..self.name

	if self.type == "raid" then
		self.header = CreateFrame("Button",frameNameHeader,UIParent,"SecureRaidGroupHeaderTemplate")
	else
		self.header = CreateFrame("Button",frameNameHeader,UIParent,"SecurePartyHeaderTemplate")
	end

	self.header.object = self
	self.header:Hide()
	self.header:EnableMouse(false)

	self.anchor = CreateFrame("Button",frameName,UIParent,"AGraidAnchorTemplate")
	self.title = getglobal(frameName.."Title")

	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:EnableMouse(true)
	self.anchor:RegisterForDrag("LeftButton")
	self.anchor:RegisterForClicks("LeftButtonUp","RightButtonUp","MiddleButtonUp","Button4Up","Button5Up")

	self.base = CreateFrame("Button",frameName,UIParent)
	self.base:SetHeight(self.anchor:GetHeight())
	self.base:SetMovable(true)
	self.base:EnableMouse(false)
	self.anchor:SetPoint("CENTER",self.base)
end

function aUF.classes.aUFgroup.prototype:SetVisibility()
	self:UpdateRaidSet()
	if self.database.Hidden == true
	or self.database.Exists == false
	or (not (self.raidSetVisible) and self.type == "raid")
	or (self.type == "raid" and aUF.db.profile.units.raid.HideFrame == true)
	or (self.type == "party" and (aUF.db.profile.units.party.HideFrame == true or
								 (aUF.db.profile.RaidHideParty and UnitInRaid("player")) ))
	or (self.type == "partypet" and (aUF.db.profile.units.partypet.HideFrame == true or
								 (aUF.db.profile.RaidHideParty and UnitInRaid("player")) ))	 then
		self.header:Hide()
		self.anchor:Hide()
	else
		self.header:Show()
	end
end

function aUF.classes.aUFgroup.prototype:UpdateGroupFilter()
	if self.type == "raid" then
		local tempHide
		if self.header:IsVisible() then
			self.header:Hide()
			tempHide = true
		end
		local groupFilter = self.database.groupFilter
		local nameList = self.database.nameList
		local groupBy = self.database.groupBy
		if nameList and nameList ~= "" then
			self.header:SetAttribute("nameList",nameList)
			self.header:SetAttribute("groupFilter",nil)
			self.header:SetAttribute("groupBy","CLASS")
			self.header:SetAttribute("sortMethod","NAME")
			self.header:SetAttribute("groupingOrder",nil)
		else
			self.header:SetAttribute("groupFilter",groupFilter)
			self.header:SetAttribute("nameList",nil)
			if groupBy and groupBy == "NAME" then
				self.header:SetAttribute("sortMethod","NAME")
				self.header:SetAttribute("groupBy",nil)
			elseif groupBy and groupBy == "INDEX" then
				self.header:SetAttribute("sortMethod","INDEX")
				self.header:SetAttribute("groupBy",nil)
			 elseif groupBy and groupBy == "CLASS" then
				self.header:SetAttribute("sortMethod","INDEX")
				self.header:SetAttribute("groupBy","CLASS")
				self.header:SetAttribute("groupingOrder","DRUID,HUNTER,MAGE,PRIEST,PALADIN,ROUGE,SHAMAN,WARLOCK,WARRIOR")
			else
				self.header:SetAttribute("sortMethod","INDEX")
				self.header:SetAttribute("groupBy","GROUP")
				self.header:SetAttribute("groupingOrder","1,2,3,4,5,6,7,8")
			end
		end
		if tempHide then
			self.header:Show()
		end
	end
end

function aUF.classes.aUFgroup.prototype:UpdateTitle()
	local i = 1
	local child = self.header:GetAttribute("child"..i)
	while child do
		if child:IsShown() then
			i = 0
			break
		end
		i = i + 1
		child = self.header:GetAttribute("child"..i)
	end

	if self.database.ShowAnchor == true and i == 0 and self.header:IsVisible() then
		self.title:SetText(self.database.Name or self.name)
		self.anchor:Show()
	else
		self.anchor:Hide()
	end
	self.base:StopMovingOrSizing()
end

function aUF.classes.aUFgroup.prototype:UpdateRaidSet()
	local var = aUF.db.profile.CurrentRaidSet
	if (self.database.RaidSets and self.database.RaidSets[var])
		or (not (self.database.RaidSets))
		or (self.database.RaidSets and self.database.RaidSets[var] == nil) then
		self.raidSetVisible = true
	else
		self.raidSetVisible = nil
	end
end

function aUF.classes.aUFgroup.prototype:UpdateGrowth()
	local point, relativePoint = self.database.Grow
	local padding = (self.database.Padding or 2) - 6
	local AnchorOffset = (self.database.AnchorOffset or 2) - 6

	if point == "TOP" then
		relativePoint = "BOTTOM"
		self.header:SetAttribute("xOffset",0)
		self.header:SetAttribute("yOffset",-(padding))
		self.header:ClearAllPoints()
		self.header:SetPoint(point,self.base,relativePoint,0,-(AnchorOffset))
	elseif point == "BOTTOM" then
		relativePoint = "TOP"
		self.header:SetAttribute("xOffset",0)
		self.header:SetAttribute("yOffset",padding)
		self.header:ClearAllPoints()
		self.header:SetPoint(point,self.base,relativePoint,0,AnchorOffset)
	elseif point == "LEFT" then
		relativePoint = "RIGHT"
		self.header:SetAttribute("xOffset",padding)
		self.header:SetAttribute("yOffset",0)
		self.header:ClearAllPoints()
		self.header:SetPoint(point,self.base,relativePoint,AnchorOffset,0)
	elseif point == "RIGHT" then
		relativePoint = "LEFT"
		self.header:SetAttribute("xOffset",-(padding))
		self.header:SetAttribute("yOffset",0)
		self.header:ClearAllPoints()
		self.header:SetPoint(point,self.base,relativePoint,-(AnchorOffset),0)
	end

	self.header:SetAttribute("point",point)
end

function aUF.classes.aUFgroup.prototype:UpdateWidth()
	local unitdb = self.unitdb or aUF.db.profile.units[self.type]
	self.anchor:SetWidth(unitdb.Width)
	self.base:SetWidth(unitdb.Width)
end

function aUF.classes.aUFgroup.prototype:UpdateScale()
	local unitdb = self.unitdb or aUF.db.profile.units[self.type]
	self.anchor:SetScale(unitdb.Scale)
	self.base:SetScale(unitdb.Scale)
end

function aUF.classes.aUFgroup.prototype:SetInitial(child)
	if child then
		local name = child:GetName()
		child.headerType = self.type
		child.header = self

		local unitdb = self.unitdb or aUF.db.profile.units[self.type]
		child.initialWidth = unitdb.Width
		child:SetAttribute("initial-width",unitdb.Width)
		child:SetAttribute("initial-scale",unitdb.Scale or 1)
		child:SetAttribute("initial-unitWatch",true)
		if self.database.suffix then
			child:SetAttribute("unitsuffix",self.database.suffix)
		end		
		
		if not aUF.units[name] then
			aUF.units[name] = aUF.classes["aUFunit"..((self.class == "Metro" and "Metro") or "")]:new(child)
		else
			child.object = aUF.units[name]
		end
		child:SetAttribute("initial-height",self.height)

		if not child.attributesSet then
			child.object:SetAttributes()
			child.attributesSet = true
		end

	end
end

function aUF.classes.aUFgroup.prototype:BorderBackground()
	local colortable = aUF.db.profile.PartyFrameColors
	local bordercolor = aUF.db.profile.FrameBorderColors
	local borderstyle = aUF.db.profile.BorderStyle
	self.anchor:SetBackdrop({
				bgFile = "Interface\\ChatFrame\\ChatFrameBackground", 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(bordercolor.r,bordercolor.g,bordercolor.b,bordercolor.a)
end

local dewdrop
function aUF.classes.aUFgroup.prototype:OnClick(button)
	if not InCombatLockdown() then
		if (IsAltKeyDown() or IsControlKeyDown()) and (button == "LeftButton" or button == "RightButton") then
			if not dewdrop then dewdrop = AceLibrary("Dewdrop-2.0") end
			dewdrop:Open(self.anchor, 'children', aUF:GroupCreateMenu(self.name,true),'cursorX', true, 'cursorY', true)
		end
	else
		aUF:Print(L["lockdown"])
	end
end

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

function aUF.classes.aUFgroup.prototype:OnDragStop(button)
	self.base:StopMovingOrSizing()
	self.base:SetUserPlaced(false)
	self:SavePosition()
end

function aUF.classes.aUFgroup.prototype:LoadPosition()
	if type(aUF.db.profile.Positions[self.name]) == "string" then
		local x, y = strsplit(" ", aUF.db.profile.Positions[self.name])
		local scale = self.base:GetScale()*UIParent:GetEffectiveScale()

		self.base:SetPoint("TOPLEFT", UIParent,"TOPLEFT", x/scale, y/scale)
	else
		self.base:SetPoint("CENTER", UIParent, "CENTER")
	end
end

function aUF.classes.aUFgroup.prototype:SavePosition()
	local scale = self.base:GetEffectiveScale()
	local worldscale = UIParent:GetEffectiveScale()

	local x,y = self.base:GetLeft()*scale , self.base:GetTop()*scale - (UIParent:GetTop())*worldscale

	if not aUF.db.profile.Positions[self.name] then
		aUF.db.profile.Positions[self.name] = {}
	end

	aUF.db.profile.Positions[self.name] = strjoin(" ", x, y)
end

function aUF.classes.aUFgroup.prototype:Delete()
	self.database.Exists = false
	self.header:Hide()
	self.anchor:Hide()
end
