//////////////////////////////////////////////////////////////////////////////
//
// Asura_Hash.h
//
// Created by Morgan Parry.
//
// Copyright (c) 2002 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef ___ASURA_HASH_H___
#define ___ASURA_HASH_H___ 1



// M A C R O S ///////////////////////////////////////////////////////////////

#ifdef ASURA_TOOLS
#define ASURA_ENABLE_HASH_TO_FILENAME_LOOKUPS 1
#endif

// (MH - 16.05.2007) moved these into Asura.h
//typedef unsigned Asura_Hash_ID;
//static const Asura_Hash_ID ASURA_HASH_ID_UNSET = 0;

// P R O T O T Y P E S   A N D   I N L I N E   F U N C T I O N S /////////////

Asura_Hash_ID Asura_ConcatenateHashID( const Asura_Hash_ID uInitialHash, const char* szString );

Asura_Hash_ID Asura_GetHashID( const char* szString );

Asura_Hash_ID Asura_GetHashID_IgnoreExtension( const char* szString );

// NB: Asura_GetHashID(szStr) != Asura_GetHashID_Binary(szStr, strlen(szStr)).
Asura_Hash_ID Asura_GetHashID_Binary( const void* pvData, u_int uNumBytes );
// C L A S S E S /////////////////////////////////////////////////////////////
#ifdef ASURA_ENABLE_HASH_TO_FILENAME_LOOKUPS

template <class T> class Asura_TemplateHashTree;
class Asura_StrippedHashedFilename;

class Asura_HashedFilename_System
{

public:

    static void Initialise();
    static void Shutdown();

    //Finds the full or stripped filename based on a hash id
	static const char* GetFilename(Asura_Hash_ID uHashID,bool bAssertOnFail = true);

	//As above, but if a stripped filename is found , searches through the full filenames
	//for the full path for that file.
	static const char* GetFullFilename(Asura_Hash_ID uHashID,bool bAssertOnFail = true);

	//Checks to see if the stripped filename corresponding to the hash ID has any platform specific versions
	static bool DoesStrippedFilenameHavePlatformVersions(Asura_Hash_ID uHashID);

	//Checks to see if the stripped filename for the hash ID has an entry for the specified platform
	static bool DoesStrippedFilenameHaveVersionForPlatform(Asura_Hash_ID uHashID,int iPlatform);

	//Forces hashed filename data to be recalculated if currently using saved data
	static void RebuildTreeIfUsingSavedData();

private:

    static void AddFile(const char* szFilename);
    
    static void Platform_BuildHashToFilenameLookupTree();
    static void Platform_AddFilesRecursive(const char* szDirectory, const char* szStripPathFromName = NULL);

	static bool Platform_LoadHashedFilenames();
	static void Platform_SaveHashedFilenames();

    // static class data
    static bool s_bInitialised;

    static class Asura_HashTree* s_pxFullFilenameHashTree;
    static class Asura_NameList* s_pxFullFilenameList;
	static Asura_TemplateHashTree<Asura_StrippedHashedFilename>* s_pxStrippedFilenameTree;
	
    static class Asura_NameList* s_pxBackupFullFilenameList;
	static Asura_TemplateHashTree<Asura_StrippedHashedFilename>* s_pxBackupStrippedFilenameTree;

    static int s_iNumDuplicateStrippedNames;
	static bool s_bUsingSavedHashedFilenames;

	//null terminated list of directories to search for asura files
	static char* s_apszProjectDirectoryList[];
	static u_int s_uNumProjectDirectories;
};



#else // not ASURA_ENABLE_HASH_TO_FILENAME_LOOKUPS

class Asura_HashedFilename_System
{
public:

    static void Initialise( void ) { }
    static void Shutdown( void ) { }

    static const char* GetFilename( Asura_Hash_ID uHashID, bool bAssertOnFail = true ) { return NULL; }

};

#endif // else not ASURA_ENABLE_HASH_TO_FILENAME_LOOKUPS

#if defined(ASURA_UNIVERSAL_HASH_LOOKUP)
// ARC - 12 September 2006 12:58:28 - Universal hash lookup
template <class T> class Asura_TemplateHashTree;

class Asura_Universal_HashLookup
{
public:
	static void Initialise();
	static void Shutdown();

	static const char* GetName(Asura_Hash_ID uHashID, bool bAssertOnFail = true);
	static void AddName(const char* szString, Asura_Hash_ID uHashID);

protected:
	static void DeleteStrings(Asura_Hash_ID uHash, const char** pxData);
	static Asura_TemplateHashTree<const char*>* s_pxHashTree;
	static bool s_bInitialised;
	static bool s_bHasShutDown;

private:
};

#else // NOT ASURA_UNIVERSAL_HASH_LOOKUP

class Asura_Universal_HashLookup
{
public:
	static void Initialise() {};
	static void Shutdown() {};

	static const char* GetName(Asura_Hash_ID uHashID, bool bAssertOnFail = true) {return NULL;};
	static void AddName(const char* szString, Asura_Hash_ID uHashID) {};

protected:
private:
};

#endif // ASURA_UNIVERSAL_HASH_LOOKUP
// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

#endif // #ifndef ___ASURA_HASH_H___
