--[[   _                                
	( )                               
   _| |   __   _ __   ___ ___     _ _ 
 /'_` | /'__`\( '__)/' _ ` _ `\ /'_` )
( (_| |(  ___/| |   | ( ) ( ) |( (_| |
`\__,_)`\____)(_)   (_) (_) (_)`\__,_) 


--]]

local PANEL = {}

AccessorFunc( PANEL, "m_iSpaceX", 				"SpaceX" )
AccessorFunc( PANEL, "m_iSpaceY", 				"SpaceY" )
AccessorFunc( PANEL, "m_iBorder", 				"Border" )
AccessorFunc( PANEL, "m_iBaseSize", 			"BaseSize" )
AccessorFunc( PANEL, "m_iMinHeight", 			"MinHeight" )

--[[---------------------------------------------------------
   Name: Init
-----------------------------------------------------------]]
function PANEL:Init()

	self:SetDropPos( "46" )
	self:SetMinHeight( 1 )
	
	self:SetSpaceX( 0 )
	self:SetSpaceY( 0 )
	self:SetBorder( 0 )
	self:SetBaseSize( 64 )
	
	self.LastW = 0;
	self.LastH = 0;
	
	self.Tiles = {}
	

end

function PANEL:Layout()

	self.LastW = 0;
	self.LastH = 0;
	self:InvalidateLayout()

end

function PANEL:FitsInTile( x, y, w, h )

	for a=x, x+(w-1) do
		for b=y, y+(h-1) do
		
			if ( self:GetTile( a, b ) == 1 ) then
				return false 
			end
				
		end
	end
	
	return true

end

function PANEL:FindFreeTile( x, y, w, h )

	x = x or 1
	y = y or 1

	local span = math.floor( self:GetWide() / self.m_iBaseSize )
	if ( span < 1 ) then span = 1 end
	
	for i=1, span do
	
		-- Too long to fit on this line
		if ( (i + (w-1)) > span ) then 

			-- If we're on the first part
			-- and the line is empty
			-- add it. It might be too long to fit on anyway		
			if ( i == 1 ) then
			
				if ( self:FitsInTile( i, y, w, h ) ) then 
					return i, y
				end	
				
			end
		
			break 
		end
	
		if ( self:FitsInTile( i, y, w, h ) ) then 
			return i, y
		end
	
	end
	
	return self:FindFreeTile( 1, y + 1, w, h )

end

function PANEL:ClearTiles()

	self.Tiles = {}

end

function PANEL:GetTile( x, y )

	if ( !self.Tiles[y] ) then 
		return nil
	end
	
	return self.Tiles[y][x]

end

function PANEL:SetTile( x, y, val )

	if ( !self.Tiles[y] ) then 
		self.Tiles[y] = {}
	end
	
	self.Tiles[y][x] = val

end

function PANEL:ConsumeTiles( x, y, w, h )

	for a=x, x+(w-1) do
		for b=y, y+(h-1) do
			self:SetTile( a, b, 1 )
		end
	end

end

function PANEL:LayoutTiles()

	local StartLine = 1;
	local LastX		= 1;
	local tilesize	= self.m_iBaseSize;
	local MaxWidth	= math.ceil( self:GetWide() / tilesize );
	
	self:ClearTiles()
	
	local chld = self:GetChildren()
	for k, v in pairs( chld ) do
	
		if ( !v:IsVisible() ) then continue end
		
		local w = math.ceil( v:GetWide() / tilesize )
		local h = math.ceil( v:GetTall() / tilesize )
		
		if ( v.OwnLine ) then
			w = MaxWidth
		end
		
		local x, y = self:FindFreeTile( 1, StartLine, w, h )
		
		v:SetPos( (x-1) * tilesize, (y-1) * tilesize )
		
		self:ConsumeTiles( x, y, w, h )
		
		if ( v.OwnLine ) then
			StartLine = y + 1
		end
		
		LastX = x
		

	end
	
end

function PANEL:PerformLayout()

	local ShouldLayout = false;
	
	if ( self.LastW != self:GetWide() )		then ShouldLayout = true end
	if ( self.LastH != self:GetTall() )		then ShouldLayout = true end
	
	self.LastW = self:GetWide()
	self.LastH = self:GetTall()

	if ( ShouldLayout ) then
		self:LayoutTiles()
	end
	
	local w, h = self:ChildrenSize();
	h = math.max( h, self:GetMinHeight() )

	self:SetHeight( h )

end

function PANEL:OnModified()

	-- Override me

end

function PANEL:OnChildRemoved()

	self:Layout()
	
end

function PANEL:OnChildAdded( child )
	
	local dn = self:GetDnD()
	if ( dn ) then
		child:Droppable( self:GetDnD() );			
	end
	
	if ( self:IsSelectionCanvas() ) then
		child:SetSelectable( true )
	end
	
	self:Layout()
	
end

function PANEL:Copy()

	local copy = vgui.Create( "DTileLayout", self:GetParent() )
	copy:CopyBase( self )
	copy:SetSortable( self:GetSortable() )
	copy:SetDnD( self:GetDnD() )
	copy:SetSpaceX( self:GetSpaceX() )
	copy:SetSpaceX( self:GetSpaceX() )
	copy:SetSpaceY( self:GetSpaceY() )
	copy:SetBorder( self:GetBorder() )
	copy:SetSelectionCanvas( self:GetSelectionCanvas() )
	copy.OnModified = self.OnModified
	
	copy:CopyContents( self )
	
	return copy

end

function PANEL:CopyContents( from )

	for k, v in pairs( from:GetChildren() ) do
	
		v:Copy():SetParent( self )
	
	end

end

--[[---------------------------------------------------------
   Name: GenerateExample
-----------------------------------------------------------]]
function PANEL:GenerateExample( ClassName, PropertySheet, Width, Height )

	local pnl = vgui.Create( ClassName )
	pnl:MakeDroppable( "ExampleDraggable", false )
	pnl:SetSize( 200, 200 )
	pnl:SetUseLiveDrag( true )
	pnl:SetSelectionCanvas( true )
	pnl:SetSpaceX( 4 )
	pnl:SetSpaceY( 4 )
	
	for i=1, 32 do
		
		local btn = pnl:Add( "DButton" )
		btn:SetSize( 32, 32 )
		btn:SetText( i )
		
	end
		
	PropertySheet:AddSheet( ClassName, pnl, nil, true, true )

end

derma.DefineControl( "DTileLayout", "", PANEL, "DDragBase" )

