-- ------------------------------------------------------------------------------ --
--                                TradeSkillMaster                                --
--                http://www.curse.com/addons/wow/tradeskill-master               --
--                                                                                --
--             A TradeSkillMaster Addon (http://tradeskillmaster.com)             --
--    All Rights Reserved* - Detailed license information included with addon.    --
-- ------------------------------------------------------------------------------ --

local _, TSM = ...
local Container = TSMAPI_FOUR.Class.DefineClass("Container", TSM.UI.Element, "ABSTRACT")
TSM.UI.Container = Container
local private = {}



-- ============================================================================
-- Container - Public Class Methods
-- ============================================================================

function Container.__init(self, frame)
	self.__super:__init(frame)

	self._children = {}
	self._layoutChildren = {}
	self._noLayoutChildren = {}
end

function Container.Release(self)
	self:ReleaseAllChildren()
	self.__super:Release()
end

function Container.ReleaseAllChildren(self)
	for _, child in ipairs(self._children) do
		child:Release()
	end
	wipe(self._children)
	wipe(self._layoutChildren)
	wipe(self._noLayoutChildren)
end


function Container.AddChild(self, child)
	self:_AddChildHelper(child, true)
	return self
end

function Container.AddChildBeforeById(self, beforeId, child)
	self:_AddChildHelper(child, true, beforeId)
	return self
end

function Container.AddChildrenWithFunction(self, func, ...)
	func(self, ...)
	return self
end

function Container.AddChildNoLayout(self, child)
	self:_AddChildHelper(child, false)
	return self
end

function Container.RemoveChild(self, child)
	assert(child:__isa(TSM.UI.Element) and child:_GetBaseFrame():GetParent())
	child:_GetBaseFrame():SetParent(nil)
	TSMAPI_FOUR.Util.TableRemoveByValue(self._children, child)
	TSMAPI_FOUR.Util.TableRemoveByValue(self._layoutChildren, child)
	TSMAPI_FOUR.Util.TableRemoveByValue(self._noLayoutChildren, child)
	child:_SetParentElement(nil)
end

function Container.GetNumLayoutChildren(self)
	local count = 0
	for _ in self:LayoutChildrenIterator() do
		count = count + 1
	end
	return count
end

function Container.LayoutChildrenIterator(self)
	local children = TSMAPI_FOUR.Util.AcquireTempTable()
	for _, child in ipairs(self._layoutChildren) do
		if child:IsVisible() then
			tinsert(children, child)
		end
	end
	return TSMAPI_FOUR.Util.TempTableIterator(children)
end



-- ============================================================================
-- Container - Public Class Methods
-- ============================================================================

function Container._AddChildHelper(self, child, layout, beforeId)
	assert(child:__isa(TSM.UI.Element) and not child:_GetBaseFrame():GetParent())
	child:_GetBaseFrame():SetParent(self:_GetBaseFrame())
	tinsert(self._children, private.GetElementInsertIndex(self._children, beforeId), child)
	if layout then
		tinsert(self._layoutChildren, private.GetElementInsertIndex(self._layoutChildren, beforeId), child)
	else
		tinsert(self._noLayoutChildren, private.GetElementInsertIndex(self._noLayoutChildren, beforeId), child)
	end
	child:_SetParentElement(self)
	child:Show()
end

function Container.Draw(self)
	self.__super:Draw()
	for _, child in ipairs(self._children) do
		child:Draw()
	end
end



-- ============================================================================
-- Private Helper Functions
-- ============================================================================

function private.GetElementInsertIndex(tbl, beforeId)
	if not beforeId then
		return #tbl + 1
	end
	for i, element in ipairs(tbl) do
		if element._id == beforeId then
			return i
		end
	end
	error("Invalid beforeId: "..tostring(beforeId))
end
