-- Functions to save and load props

CAKE.PropList = {};

-- simple and clean removing of prop from table
local function propRemoving( ent )

	if( string.match( ent:GetClass(), "prop_physics" ) and ent:GetNWString("CreatorName") != "" ) then
--Msg("removing prop.\n");
		CAKE.PropList[ent:EntIndex()] = nil;
		
		-- toss out any items that might be stored in the item.
		if( ent.inventory != nil ) then
	
			for k,v in pairs( ent.inventory ) do

				local itemtable = ItemData[ v ];

				/*
				umsg.Start( "addsearchitem", ply )
				umsg.String( ItemTable.Model )
				umsg.Bool( true )
				umsg.String( ItemTable.Class )
				umsg.Entity( entity )
				umsg.String( ItemTable.Name )
				umsg.String( ItemTable.Description )
				umsg.End( );
				*/
	
				local item = ents.Create("item_prop");
	
				item:SetModel( itemtable.Model );
				item:SetAngles( ent:GetAngles() );
				item:SetPos( ent:GetPos() );
	
				for k, v in pairs(itemtable) do
					item[k] = v;
					if(type(v) == "string") then
						item:SetNWString(k, v);
					end
				end
	
				item:Spawn();
				item:Activate();
				
				-- have to influence the physobj to move an ent
				local entphys = item:GetPhysicsObject();
				entphys:SetVelocity( Angle( math.random(-1000,1000), math.random(-1000,1000), math.random(20,1000) ) );

			end
			
		end
		
	end

end

local function getNewPlayerPropCount( ply )

	--local count = 0;
	local ownerSteam = ply:SteamID();
	
	for k, v in pairs( CAKE.PropList ) do
	
		if( string.match( v.steam, ownerSteam ) ) then
			--count = count + 1;
			
			
			undo.Create("Prop");
 				undo.SetPlayer(ply);
 				undo.AddEntity( ents.GetByIndex(k) );
 			undo.Finish( "Prop ("..tostring(v.model)..")" );
 			
 			
 			ply:AddCount("props", ents.GetByIndex(k) );
		end
	
	end

	--ply:SetNWInt( "props", count );

end
hook.Add( "PlayerInitialSpawn", "setPropCount", getNewPlayerPropCount );

-- loads and spawns all props from the saved list.
-- due to how the system is setup it won't remember a prop spawned by the map
-- cannot be called in GM:Init because its too soon to spawn props, causing it to "work" but no props to show up (and insanely low ent indexes)
function CAKE.LoadProps()

	hook.Remove( "Think", "PropLoadingSingle" );

	if( file.Exists( "CakeScript/MapData/" .. game.GetMap() ..  "/Props.txt" ) )then
	
		local Data_Raw = file.Read( "CakeScript/MapData/" .. game.GetMap() ..  "/Props.txt" );
		
		-- Convert the data into a table
		local tempData = util.KeyValuesToTable( Data_Raw );
		
		for u, v in pairs( tempData ) do
		
			local oldProp = ents.Create("prop_physics");
	
			oldProp:SetModel( v.model );
			oldProp:SetAngles( Angle( v.pitch, v.yaw, v.roll ) );
			oldProp:SetPos( Vector( v.x, v.y, v.z ) );
			oldProp:SetNWString("CreatorName", v.creator );
			oldProp:SetNWString("CreatorSteam", v.steam );
		
			oldProp:Spawn();
			oldProp:Activate();
			oldProp:GetPhysicsObject():EnableMotion( false ); -- yay freezing
			
			-- indexes may change
			CAKE.PropList[ oldProp:EntIndex() ] = v;
			
			oldProp:CallOnRemove( "dataRemoval", propRemoving, oldProp );
			
		end	
	
	end
	
	-- timer creation for saving props is here so we don't overwrite the save before its loaded
	timer.Create("propsave", 180, 0, CAKE.SaveProps);

end
-- only using think because its called after all server loading is done, we remove from the think hook on the first call so kind of a hack
hook.Add("Think", "PropLoadingSingle", CAKE.LoadProps );

-- Called when a player spawns a prop, ent indexes are unique per lifetime of the server
function CAKE.AddPropSave( ply, entity )

	local newProp = {};
	newProp.model = entity:GetModel();
	local angle = entity:GetAngles();
	newProp.pitch = angle.p;
	newProp.yaw = angle.y;
	newProp.roll = angle.r;
	local pos = entity:GetPos();
	newProp.x = pos.x;
	newProp.y = pos.y;
	newProp.z = pos.z;
	newProp.creator = entity:GetNWString("CreatorName");
	newProp.steam = entity:GetNWString("CreatorSteam");

	CAKE.PropList[ entity:EntIndex() ] = newProp;
	
	entity:CallOnRemove( "dataRemoval", propRemoving, entity );
	
	ply:AddCount("props", entity );
	
end

-- updates position and orientation, called after physgun is released from the prop (no we don't detect grav gunning)
local function CAKEUpdateProp( ply, ent )

	if( CAKE.PropList[ ent:EntIndex() ] != nil ) then
	
--Msg("Updating prop.\n");
	
		local angle = ent:GetAngles();
		CAKE.PropList[ ent:EntIndex() ].pitch = angle.p;
		CAKE.PropList[ ent:EntIndex() ].yaw = angle.y;
		CAKE.PropList[ ent:EntIndex() ].roll = angle.r;
		local pos = ent:GetPos();
		CAKE.PropList[ ent:EntIndex() ].x = pos.x;
		CAKE.PropList[ ent:EntIndex() ].y = pos.y;
		CAKE.PropList[ ent:EntIndex() ].z = pos.z;
	
	end

end
hook.Add("PhysgunDrop", "PropUpdate", CAKEUpdateProp);  

local function CAKEUpdatePropWrapper( weaponEnt, physobj, ent, ply)

	CAKEUpdateProp( ply, ent );

end
hook.Add("OnPhysgunFreeze", "PropUpdate", CAKEUpdatePropWrapper); 



-- called every 180 seconds after the props are loaded
function CAKE.SaveProps()

--Msg("saving props.\n");

	local keys = util.TableToKeyValues( CAKE.PropList );
	file.Write( "CakeScript/MapData/" .. game.GetMap() ..  "/Props.txt" , keys);

end