//-----------------------------------------------------------------------------------------------
// EngineUtilities.hpp
//
#pragma once
#ifndef INCLUDED_ENGINEUTILITIES
#define INCLUDED_ENGINEUTILITIES

//-----------------------------------------------------------------------------------------------
#include "Engine/Core/EngineBase.hpp"


//-----------------------------------------------------------------------------------------------
class Rgba;


//-----------------------------------------------------------------------------------------------
typedef unsigned int CaseInsensitiveStringHashValue;
typedef unsigned int CaseSensitiveStringHashValue;
typedef unsigned int GenericHashValue;


//-----------------------------------------------------------------------------------------------
// String utilities
//
int Stricmp( const std::string& first, const std::string& second );
int Stricmp( const char* first, const std::string& second );
int Stricmp( const std::string& first, const char* second );
int Stricmp( const char* first, const char* second );
void Sprintf( std::string& destination, const char* format, ... );
void Sprintf( const int maxLength, std::string& destination, const char* format, ... );
const std::string Stringf( const char* format, ... );
const std::string Stringf( const int maxLength, const char* format, ... );
std::string GetAsLowerCase( const std::string& mixedCaseString );
void GetAsLowerCase( const std::string& mixedCaseString, std::string& out_lowerCaseString );
bool DoesShorterStringMatch( const std::string& firstString, const std::string& secondString );
bool DoesShorterStringMatchCaseInsensitive( const std::string& firstString, const std::string& secondString );
bool IsFirstStringCaseInsensitiveSubsetOfSecond( const std::string& firstString, const std::string& secondString );
void SkipWhitespace( const char*& scanPosition );
void SkipInlineWhitespace( const char*& scan );
void SkipWhitespaceAndCountLineNumbers( const char*& scanPosition, int& lineNumber );
void SkipNonWhitespace( const char*& scanPosition );
void SkipQuotedString( const char*& scan );
void SkipQuotedStringAndCountLineNumbers( const char*& scan, int& lineNumber );
std::string ParseContiguousStringAndAdvance( const char*& scan );
std::string ParseContiguousOrQuotedStringAndAdvance( const char*& scan );
void ParseCommandsAndArgs( const std::string& rawCommandString, std::string& out_commandName, std::string& out_commandArgs, std::vector< std::string >& out_commandArgList );
std::string GetLineFromTextBuffer( const std::string& textBuffer, int lineNumber );
CaseInsensitiveStringHashValue ComputeCaseInsensitiveHashForString( const char* stringWhoseCaseWillBeIgnoredForHashGeneration );
CaseInsensitiveStringHashValue ComputeCaseInsensitiveHashForString( const char* stringWhoseCaseWillBeIgnoredForHashGeneration, unsigned int stringLength );
CaseInsensitiveStringHashValue ComputeCaseInsensitiveHashForString( const std::string& stringWhoseCaseWillBeIgnoredForHashGeneration );
CaseSensitiveStringHashValue ComputeCaseSensitiveHashForString( const char* stringWhoseCaseWillBeUsedForHashGeneration );
CaseSensitiveStringHashValue ComputeCaseSensitiveHashForString( const char* stringWhoseCaseWillBeUsedForHashGeneration, unsigned int stringLength );
CaseSensitiveStringHashValue ComputeCaseSensitiveHashForString( const std::string& stringWhoseCaseWillBeUsedForHashGeneration );
GenericHashValue ComputeHashForBuffer( const unsigned char* buffer, size_t bufferSizeInBytes );


//-----------------------------------------------------------------------------------------------
// File I/O utilities
//
char* LoadTextFileToNewBuffer( const char* textFilePath );


//-----------------------------------------------------------------------------------------------
// Console utilities
//
void ConsolePrintf( const char* messageFormat, ... );
void ConsolePrintf( const Rgba& color, const char* messageFormat, ... );



/////////////////////////////////////////////////////////////////////////////////////////////////
struct CommandLineCommand
{
	std::string						m_commandName;
	std::vector< std::string >		m_args;
};


/////////////////////////////////////////////////////////////////////////////////////////////////
struct CommandLineCommands
{
	CommandLineCommands( const std::string& rawCommandLineString );
	void ParseCommandAndArgs( const char*& scan );
	bool IsCommandPresent( const std::string& commandName ) const;
	const std::vector< std::string >& GetCommandArgs( const std::string& commandName ) const;

	std::string							m_rawCommandLineString;
	std::vector< CommandLineCommand >	m_commandsWithArgs;
};


/////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------------------------
template< typename T_MapValueTypePointedTo >
T_MapValueTypePointedTo* FindMapItemByName( const char* mapItemKeyName, std::map< std::string, T_MapValueTypePointedTo* >& mapToSearch )
{
	std::map< std::string, T_MapValueTypePointedTo* >::iterator found = mapToSearch.find( mapItemKeyName );
	if( found != mapToSearch.end() )
	{
		return found->second;
	}
	else
	{
		return nullptr;
	}
}


//-----------------------------------------------------------------------------------------------
inline int Stricmp( const std::string& first, const std::string& second )
{
	return _stricmp( first.c_str(), second.c_str() );
}


//-----------------------------------------------------------------------------------------------
inline int Stricmp( const char* first, const std::string& second )
{
	return _stricmp( first, second.c_str() );
}


//-----------------------------------------------------------------------------------------------
inline int Stricmp( const std::string& first, const char* second )
{
	return _stricmp( first.c_str(), second );
}


//-----------------------------------------------------------------------------------------------
inline int Stricmp( const char* first, const char* second )
{
	return _stricmp( first, second );
}



#endif // INCLUDED_ENGINEUTILITIES
