//-----------------------------------------------------------------------------------------------
// StringTable.hpp
//
#pragma once
#ifndef include_StringTable
#define include_StringTable

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


//-----------------------------------------------------------------------------------------------
typedef unsigned int HashValue;
HashValue Hash( const char* stringToHash );
HashValue Hash( const std::string& stringToHash );


//-----------------------------------------------------------------------------------------------
inline HashValue Hash( const char* stringToHash )
{
	HashValue hashValue = 0;
	const char* scan = stringToHash;
	while( *scan != '\0' )
	{
		hashValue &= 0x07ffffff;
		hashValue *= 31;
		hashValue += *scan;
		++scan;
	}

	return hashValue;
}


//-----------------------------------------------------------------------------------------------
inline HashValue Hash( const std::string& stringToHash )
{
	HashValue hashValue = 0;
	size_t stringLength = stringToHash.size();
	for( unsigned int i = 0; i < stringLength; ++ i )
	{
		hashValue &= 0x07ffffff;
		hashValue *= 31;
		hashValue += stringToHash[i];
	}

	return hashValue;
}



/////////////////////////////////////////////////////////////////////////////////////////////////
struct StringTableEntry
{
	const char*						m_stringText;
	int								m_stringTextLength;
	CaseSensitiveStringHashValue	m_caseSensitiveHash;
//	CaseInsensitiveStringHashValue	m_caseInsensitiveHash;

	StringTableEntry()
		: m_stringText( nullptr )
		, m_stringTextLength( -1 ) // -1 means "dirty" (not yet calculated)
		, m_caseSensitiveHash( 0 )
	{}
};


/////////////////////////////////////////////////////////////////////////////////////////////////
// StoredString - A lightweight, non-heap-allocated flyweight representation of a stored ASCII
//	string constant, usually used for internally-visible symbol/event/property names.
// 
// Goals:
//	- Can be constructed in place from any flavor of string (cString, std::string, Hashed), as:
//			StoredString helloString( "Hello" );
//	- Can be asked for its source string, with case intact (or also in upper-case form).
//	- Can do very fast comparisons (==, !=, <, others) against other StoredStrings; comparisons are?  are not?  case sensitive... ?
//	- Reasonably compact in size (4-8 bytes)
//	- Super fast copy construction
//	- Super fast sorting/comparison (for map keys, etc.)
//	- Fast construction from cString, std::string, or HCIS
//	- Reasonably fast string recall
//	- No heap allocations in all cases, except for newly-unseen string insertions into table
//
class StoredString
{
public:
	StoredString();
	StoredString( const StoredString& copy );
	StoredString( const char* cString );
	StoredString( const std::string& stdString );
//	StoredString( const HashedCaseInsensitiveString& hashedString );

	void Set( const char* cString );
	void Set( const std::string& stdString );

	const char* GetCString() const;

	void operator = ( const StoredString& copy );
	bool operator == ( const StoredString& rhsCompare ) const;
	bool operator != ( const StoredString& rhsCompare ) const;
	bool operator < ( const StoredString& rhsCompare ) const;
	bool operator > ( const StoredString& rhsCompare ) const;

private:
	CaseSensitiveStringHashValue m_caseSensitiveHash;
//	unsigned int m_caseInsensitiveHash;
//	unsigned int m_caseSensitiveStringTableID;
//	unsigned int m_caseInsensitiveStringTableID;

private:
	static std::map< CaseSensitiveStringHashValue, StringTableEntry >	s_caseSensitiveStringTable;
//	static std::map< CaseInsensitiveStringHashValue, StringTableEntry >	s_caseInsensitiveStringTable;
};


//-----------------------------------------------------------------------------------------------
inline StoredString::StoredString()
{
	m_caseSensitiveHash = 0;
	StringTableEntry& entry = s_caseSensitiveStringTable[ m_caseSensitiveHash ]; // Find or create this entry in the string table
	if( entry.m_stringText == nullptr )
	{
		entry.m_caseSensitiveHash = 0;
		entry.m_stringText = "";
	}
}


//-----------------------------------------------------------------------------------------------
inline StoredString::StoredString( const StoredString& copy )
	: m_caseSensitiveHash( copy.m_caseSensitiveHash )
{
}


//-----------------------------------------------------------------------------------------------
inline StoredString::StoredString( const char* cString )
{
	m_caseSensitiveHash = ComputeCaseSensitiveHashForString( cString );
	StringTableEntry& entry = s_caseSensitiveStringTable[ m_caseSensitiveHash ]; // Find or create this entry in the string table
	if( entry.m_stringText == nullptr )
	{
		entry.m_caseSensitiveHash = m_caseSensitiveHash;
		entry.m_stringText = _strdup( cString );
	}
}


//-----------------------------------------------------------------------------------------------
inline void StoredString::operator = ( const StoredString& copy )
{
	m_caseSensitiveHash = copy.m_caseSensitiveHash;
}


//-----------------------------------------------------------------------------------------------
inline bool StoredString::operator == ( const StoredString& rhsCompare ) const
{
	return m_caseSensitiveHash == rhsCompare.m_caseSensitiveHash;
}


//-----------------------------------------------------------------------------------------------
inline bool StoredString::operator != ( const StoredString& rhsCompare ) const
{
	return m_caseSensitiveHash != rhsCompare.m_caseSensitiveHash;
}


//-----------------------------------------------------------------------------------------------
inline bool StoredString::operator < ( const StoredString& rhsCompare ) const
{
	return m_caseSensitiveHash < rhsCompare.m_caseSensitiveHash;
}


//-----------------------------------------------------------------------------------------------
inline bool StoredString::operator > ( const StoredString& rhsCompare ) const
{
	return m_caseSensitiveHash > rhsCompare.m_caseSensitiveHash;
}


/////////////////////////////////////////////////////////////////////////////////////////////////
/*

std::map< HashedCaseInsensitiveString, StoredString >	g_stringTable;


//-----------------------------------------------------------------------------------------------
StoredString GetIDForString( const char* cString )
{
	HashedCaseInsensitiveString hashedString( cString );
	StoredString stringID = g_stringTable[ hashedString ];
	if( stringID )


	std::pair< HashedCaseInsensitiveString, StoredString >& found = g_stringTable[ hashedString ];
	if( found->second)

	std::map< HashedCaseInsensitiveString, StoredString >::iterator found = g_stringTable.find( hashedString );
	if( found != g_stringTable.end() )
	{
		return found->second;
	}
	else
	{

	}
}
*/


#endif // include_StringTable
