
local table 			= table
local pairs 			= pairs
local concommand 		= concommand
local SERVER 			= SERVER
local saverestore 		= saverestore
local tostring			= tostring

module("undo")



// undo.Create("Wheel")
// undo.AddEntity( axis )
// undo.AddEntity( constraint )
// undo.SetPlayer( self.Owner )
// undo.Finish()


if (!SERVER) then return end

local PlayerUndo = {}
// PlayerUndo
//	- Player UniqueID
//		- Undo Table
//			- Name
//			- Entities (table of ents)
//			- Owner (player)

local Current_Undo = nil


local function Save( save )

	saverestore.WriteTable( PlayerUndo, save )

end

local function Restore( restore )

	PlayerUndo = saverestore.ReadTable( restore )

end

saverestore.AddSaveHook( "UndoTable", Save )
saverestore.AddRestoreHook( "UndoTable", Restore )

// Starts an undo
function Create( text )

	Current_Undo = {}
	Current_Undo.Name 			= text
	Current_Undo.Entities 		= {}
	Current_Undo.Owner 			= nil
	
end

// Add entity to undo
function AddEntity( ent )

	if ( Current_Undo == nil ) then return end
	if ( !ent ) then return end
	if ( !ent:IsValid() ) then return end
	
	table.insert( Current_Undo.Entities, ent )
	
end

// Set the player owner od the undo
function SetPlayer( player )

	if (Current_Undo == nil) then return end	
	if ( !player || !player:IsValid() ) then return end
	
	Current_Undo.Owner = player
	
end

// Finish Undo and add it to the player's list
function Finish()

	if (Current_Undo == nil) then return end
	if (Current_Undo.Owner == nil) then return end
	if (!Current_Undo.Owner:IsValid()) then return end
	
	local index = Current_Undo.Owner:UniqueID()
	PlayerUndo[ index ] = PlayerUndo[ index ] or {}
	
	local id = table.insert( PlayerUndo[ index ], Current_Undo )
	
	// id can now be used somehow!
			
	Current_Undo = nil
	
end


local function Do_Undo( undo )

	if ( !undo ) then return false end
	
	local count = 0
	
	// Remove each entity in this undo
	for index, entity in pairs( undo.Entities ) do
	
		if ( entity:IsValid() ) then
			entity:Remove()
			count = count + 1
		end
		
	end
	
	if (count > 0) then
		// Sends tooltip to client
		undo.Owner:SendLua( "GAMEMODE:OnUndo( '"..undo.Name.."' )" )
	end
	
	return count;
	
end

local function CC_UndoLast( pl, command, args )

	local index = pl:UniqueID()
	PlayerUndo[ index ] = PlayerUndo[ index ] or {}
	
	local last = nil
	local lastk = nil
	
	for k, v in pairs( PlayerUndo[ index ] ) do
	
		lastk = k
		last = v
	
	end
	
	// No undos
	if (!last) then	return end
	
	local count = Do_Undo( last )
	
	PlayerUndo[ index ][ lastk ] = nil
	
	// If our last undo object is already deleted then compact
	// the undos until we hit one that does something
	if ( count == 0 ) then
		CC_UndoLast( pl )
	end

end

concommand.Add("undo",					CC_UndoLast		)
concommand.Add("gmod_undo",				CC_UndoLast		)

	
