-------------------------------
-- SSTRP
-- Author: MNWRP
--
-- player_data.lua
-- Handles player data and such.
-------------------------------

-- Define the table of player information.
PlayerData = {  };

-- This is to be used only by the main player table.
PlayerDataFields = {  };

-- This is to be used only by the characters table.
CharacterDataFields = {  };

local meta = FindMetaTable( "Player" );

function FormatCharString( ply )
	
	return ply:SteamID( ) .. "-" .. ply:GetNWString( "uid" );
	
end

-- This formats a player's SteamID for things such as data file names
-- For example, STEAM_0:1:5947214 would turn into 015947214
function FormatSteamID( SteamID )

	local SteamID = NilFix(SteamID, "STEAM_0:0:0");

	s = string.gsub( SteamID,"STEAM","" );
	s = string.gsub( s,":","" );
	s = string.gsub( s,"_","" );
	
	return s;
	
end

-- When fieldtype is 1, it adds it to the player table.
-- When it is 2, it adds it to the character table.
function AddDataField( fieldtype, fieldname, default )

	if( fieldtype == 1 ) then
	
		DayLog( "script.txt", "Adding player data field " .. fieldname .. " with default value of " .. tostring( default ) );
		PlayerDataFields[ fieldname ] = ReferenceFix(default);
	
	elseif( fieldtype == 2 ) then
	
		DayLog( "script.txt", "Adding character data field " .. fieldname .. " with default value of " .. tostring( default ) );
		CharacterDataFields[ fieldname ] = ReferenceFix(default);
		
	end
	
end

-- Load a player's data
function LoadPlayerDataFile( ply )

	local SteamID = FormatSteamID( ply:SteamID( ) );
	
	PlayerData[ SteamID ]  = {  };
	
	if( file.Exists( "SSTRP/PlayerData/" .. ConVars[ "Schema" ] .. "/" .. FormatSteamID( ply:SteamID() ) .. ".txt" ) ) then
	
		CallHook( "LoadPlayerDataFile", ply );
		
		DayLog( "script.txt", "Loading player data file for " .. ply:SteamID( ) );
		
		-- Read the data from their data file
		local Data_Raw = file.Read( "SSTRP/PlayerData/" .. ConVars[ "Schema" ] .. "/" .. FormatSteamID( ply:SteamID() ) .. ".txt" );
		
		-- Convert the data into a table
		local Data_Table = NilFix(util.KeyValuesToTable( Data_Raw ), { });
		
		-- Insert the table into the data table
		PlayerData[ SteamID ] = Data_Table;
		
		-- Retrieve the data table for easier access
		local PlayerTable = PlayerData[ SteamID ];
		local CharTable = PlayerData[ SteamID ][ "characters" ];

		-- If any values were loaded and they aren't in the DataFields table, delete them from the player.
		for _, v in pairs( PlayerTable ) do
			
			if( PlayerDataFields[ _ ] == nil ) then
			
				DayLog( "script.txt", "Invalid player data field '" .. tostring( _ ) .. "' in " .. ply:SteamID( ) .. ", removing." );
				PlayerData[ SteamID ][ _ ] = nil;
				
			end
			
		end
		
		-- If any fields were not loaded and they are in the DataFields table, add them.
		for fieldname, default in pairs( PlayerDataFields ) do
			
			if( PlayerTable[ fieldname ] == nil ) then
			
				DayLog( "script.txt", "Missing player data field '" .. tostring( fieldname ) .. "' in " .. ply:SteamID( ) .. ", inserting with default value of '" .. tostring(default) .. "'" );
				PlayerData[ SteamID ][ fieldname ] = ReferenceFix(default);
				
			end
			
		end
		
		-- If any values were loaded and they aren't in the DataFields table, delete them from the character.
		for _, char in pairs( CharTable ) do
		
			for k, v in pairs( char ) do
			
				if( CharacterDataFields[ k ] == nil ) then
				
					DayLog( "script.txt", "Invalid character data field '" .. tostring( _ ) .. "' in character " .. ply:SteamID( ) .. "-" .. _ .. ", removing." );
					PlayerData[ SteamID ][ "characters" ][ _ ][ k ] = nil;
					
				end
				
			end
			
		end
		
		-- If any fields were not loaded and they are in the DataFields table, add them.
		for _, char in pairs( CharTable ) do
			
			for fieldname, default in pairs( CharacterDataFields ) do
			
				if( char[ fieldname ] == nil ) then
				
					DayLog( "script.txt", "Missing character data field '" .. tostring( fieldname ) .. "' in character " .. ply:SteamID( ) .. "-" .. _ .. ", inserting with default value of '" .. tostring(default) .. "'" );
					PlayerData[ SteamID ][ "characters" ][ _ ][ fieldname ] = ReferenceFix(default);
					
				end
				
			end
			
		end
		
		SavePlayerData(ply);
		
		CallHook( "LoadedPlayerDataFile", ply, Data_Table );
		
	else
		
		-- Seems they don't have a player table. Let's create a default one for them.
		
		DayLog( "script.txt", "Creating new data file for " .. ply:SteamID( ) );
		
		PlayerData[ SteamID ] = {  };
		
		-- Let's get the default fields and add them to the table.
		for fieldname, default in pairs( PlayerDataFields ) do
			
			if( PlayerData[ fieldname ] == nil ) then
			
				PlayerData[ SteamID ][ fieldname ] = ReferenceFix(default);
				
			end
			
		end
		
		-- We won't make a character, obviously. That is done later.
		
		SavePlayerData(ply);
		
		-- Technically, we didn't load it, but the data is now there.
		CallHook( "LoadedPlayerDataFile", ply, Data_Table );
		
	end
	
end

function ResendCharData( ply ) -- Network all of the player's character data

	local SteamID = FormatSteamID( ply:SteamID() );
	
	if( PlayerData[ SteamID ][ "characters" ][ ply:GetNWString( "uid" ) ] == nil ) then
		return;
	end
	
	for fieldname, data in pairs( PlayerData[ SteamID ][ "characters" ][ ply:GetNWString( "uid" ) ] ) do
		
		if( type( data ) != "table" ) then
			
			ply:SetNWString( fieldname, tostring( data ) );
			
		end

	end
	
end

function SetPlayerField( ply, fieldname, data )

	local SteamID = FormatSteamID( ply:SteamID() );
	
	-- Check to see if this is a valid field
	if( PlayerDataFields[ fieldname ] ) then
	
		
		PlayerData[ SteamID ][ fieldname ] = data;
		SavePlayerData(ply);
		
	else
	
		return "";
		
	end
	
end
	
function GetPlayerField( ply, fieldname )

	local SteamID = FormatSteamID( ply:SteamID() );

	-- Check to see if this is a valid field
	if( PlayerDataFields[ fieldname ] ) then
		
		return NilFix(PlayerData[ SteamID ][ fieldname ], "");
		
	else
	
		return "";
		
	end
	
end

function SetCharField( ply, fieldname, data )

	local SteamID = FormatSteamID( ply:SteamID() );
	
	-- Check to see if this is a valid field
	if( CharacterDataFields[ fieldname ] ) then
	
		PlayerData[ SteamID ][ "characters" ][ ply:GetNWString( "uid" ) ][ fieldname ] = data;
		SavePlayerData(ply);
		
	else
	
		return "";
		
	end
	
end
	
function GetCharField( ply, fieldname )

	local SteamID = FormatSteamID( ply:SteamID() );
	
	-- Check to see if this is a valid field
	if( CharacterDataFields[ fieldname ] ) then
	
		return NilFix(PlayerData[ SteamID ][ "characters" ][ ply:GetNWString( "uid" ) ][ fieldname ], "");
		 
	else
	
		return "";
		
	end
	
end

function SavePlayerData( ply )

	local keys = util.TableToKeyValues(PlayerData[FormatSteamID( ply:SteamID() )]);
	file.Write( "SSTRP/PlayerData/" .. ConVars[ "Schema" ] .. "/" .. FormatSteamID( ply:SteamID() ) .. ".txt" , keys);
	
end
