/////////////////////////////////////////////////////////////////////////////////////////
//
//	FILE:			Tools_Shapes.h
//
//	AUTHOR:			Richard M. Smith (5 September 2002)
//
/////////////////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __TOOLS_SHAPES_H__
#define __TOOLS_SHAPES_H__


//////////////
// INCLUDES //
//////////////
#include "Core/Asura_Hash.h"
#include "Shapes/Asura_Shapes.h"
#include "Misc/Tools_Modal_Overlay.h"
#include "Load&Save/LevelExport/Tools_Level_Export.h"

#include <string.h>
#include <stdlib.h>

// File Tools for PS2 Export
//#include "PS2ExportShape.h"



/////////////
// DEFINES //
/////////////
#define	ASURA_SHAPE_HASH_TABLE_FILE_EXT		".STB"




/////////////
// CLASSES //
/////////////
class Asura_String;
class Asura_Overlay;
class Tools_ShapeTableElement;

class Tools_ShapeTable
{
	friend class Tools_ShapeTableElement;
	friend class Tools_ShapeTable_Overlay;

public:
	Tools_ShapeTable(){s_pxThis = this;}
	virtual ~Tools_ShapeTable(){s_pxThis = 0;}
	
	static void Initialise( void );
	static void Shutdown( void );
	//static bool LoadTable( void );
	//static bool SaveTable( void );

	static void BuildShapeTable();


	static Asura_Hash_ID SelectShape( Asura_Hash_ID uInitiallySelectedHashID = ASURA_HASH_ID_UNSET );
	
	static void AddShapeByRequester( void );
	static Asura_Hash_ID AddShapeByFilename( const char* szFilename,bool bShowOverlays = true );

	static void RemoveShape( void );

	static const char* LookupObjectMeshName( Asura_Hash_ID uShapeID );
	static const char* LookupObjectFileName( Asura_Hash_ID uShapeID );

	static unsigned int GetNumElements( void )
	{
		return (unsigned int)s_iNumElementsInTable;
	}

	static unsigned int GetNumExportShapes( void )
	{
		return (unsigned int)s_iNumExportShapes;
	}

	static Asura_Mesh* GetMeshByIndex(unsigned int uIndex, bool bCommonShapes = false );
	static const char* GetMeshNameByIndex(unsigned int uIndex, bool bCommonShapes = false );
	static Asura_Mesh* GetMeshByHashID(Asura_Hash_ID uShapeID);

	static Asura_Hash_ID GetHashIDByIndex(u_int uIndex,bool bCommonShapes = false);

	
	static bool ExportShape( Tools_Level_Export::EXPORT_TYPE eExportType, unsigned int uIndex, HANDLE pSaveHandle, const char*& szShapeFilename, bool bCommonShapes = false );
	//Exports multiple shapes in an asura file , assigning Hash ID based on mesh name
	static bool ExportShapeFile(Tools_Level_Export::EXPORT_TYPE eExportType,const char* pszFilename,HANDLE pSaveHandle);
		
	//Loads shapes listed in [SHAPES] section of specified file.
	//Any shapes listed in this file will also be flagged for inclusion in exports.
	//Returns false if failed to load text file.
	static bool LoadExportShapesFromFile(const char* pszTextFilename);

	//Loads the common export and level specific export text files using LoadExportShapesFromFile
	static void LoadExportShapes( void );

	//Flags all shapes listed in [SHAPES] section of file for inclusion in level export.
	//This needs to be done before Tools_SaveAsura::SaveAll() in the export process.
	//Returns false if failed to load text file.
	//If bEnableEntityShapesAsWell is set , then the shapes in the main entity shape table
	//will be enabled for export.(Only relevent if they have previously been disabled by the function below)
	static bool EnableShapesForExport(const char* pszTextFilename,bool bEnableEntityShapesAsWell = false);

	//Flags all shapes listed in [SHAPES] section of file for exclusion from level export.
	//This won't prevent shapes from being exported should they also appear from being used
	//by static objects or cutscenes... Unless bDisableEntityShapesAsWell is used
	//Returns false if failed to load text file.
	static bool DisableShapesForExport(const char* pszTextFilename,bool bDisableEntityShapesAsWell = false);

	//Loads a single shape , and flags it for inclusion in exports
	//(must provide appropriate relative filename)
	//Returns false if failed to add
	static bool LoadExportShape(const char* pszFilename);

	//Flags a single shape for inclusion in export.
	//Returns false if shape not in shape table
	static bool EnableShapeForExportByFilename(const char* pszFilename,bool bEnableEntityShapesAsWell = false);
	static bool EnableShapeForExportByHashID(Asura_Hash_ID uShapeHash,bool bEnableEntityShapesAsWell = false);


	//Flags a single shape for exclusion from export.
	//This won't prevent shapes from being exported should they also appear from being used
	//by static objects or cutscenes.
	//Returns false if shape not in shape table
	static bool DisableShapeForExportByFilename(const char* pszFilename,bool bDisableEntityShapesAsWell = false);
	static bool DisableShapeForExportByHashID(Asura_Hash_ID uShapeHash,bool bDisableEntityShapesAsWell = false);
	

#ifdef ASURA_USING_ALL_LEVEL_EXPORT
	static void ExcludeCommonShapesFromLevelExport(void);
	static void ExcludeNonCommonShapesFromCommonExport(void);
#endif //ASURA_USING_ALL_LEVEL_EXPORT

// RICHARDS		static void UnloadExportShapes( void );
	
	
	static bool IsInShapeTable(Asura_Hash_ID uShapeHashID){ return IsInMainShapeTable(uShapeHashID) || IsCommonExportShape(uShapeHashID);}
	//Indicates whether the shape is flagged for export
	static bool ShouldExportShape(Asura_Hash_ID uShapeHashID);
	//Similarly but using index into shape list instead of hash ID
	//(Note that if a shape appears in both lists , a different result may occur for each)
	static bool ShouldExportShapeByIndex(u_int uIndex,bool bCommonShapes = false);


	static bool IsInMainShapeTable( Asura_Hash_ID uShapeHashID );
	static bool IsCommonExportShape( Asura_Hash_ID uShapeHashID );


	static Tools_ShapeTable* GetThis(){return s_pxThis;}

	static void RepairShapeTable();

	static void RemoveZeroReferenceCountElements( void );

	//get value based on modified time of shape , to detect changes
	static u_int GetChecksumForShape(Asura_Hash_ID uShapeHashID);

		//checks an asura file to see if it is a shape file , and it contains a shape with an appropriate name
	static bool IsValidShapeFile(const char* pszFilename,bool bShowErrorMessages);
	//Similar , but will fill in pxErrorMessage if it returns false
	static bool IsValidShapeFile(const char* pszFilename,Asura_String* pxErrorMessage);


protected :
	//Adds extra project specific stuff after exporting a shape
	virtual void ExportProjectShapeData(Tools_Level_Export::EXPORT_TYPE eExportType,const Tools_ShapeTableElement* pxElement,HANDLE pSaveHandle){}

private:
	static Asura_Hash_ID AddShapeByFilenameInternal( const char* szFilename,Tools_ShapeTableElement*& pxList,int& iListLength,bool bShowOverlays);

	static void GetShapesFromTextFile( FILE* pFile );
	static bool CheckFileNameFromTextFile( char* szFilename, int iStringLen );

	//get list of filenames in [SHAPES] section of text file
	static bool ListShapesInTextFile(const char* pszFilename,List<Asura_String>& xOutputFilenameList);

	//export shape table element for Pc
	static bool ExportShapeTableEntryMain( Tools_Level_Export::EXPORT_TYPE eExportType,const Tools_ShapeTableElement* pxElement, HANDLE pSaveHandle );

	//Common export function for shape table elements/fragment files for PC
	static bool ExportShapeFileMain(Tools_Level_Export::EXPORT_TYPE eExportType,const char* szFilename,const char* szMeshName,HANDLE pSaveHandle);


// RICHARDS		static void AddElement( Tools_ShapeTableElement* pxNewElement );
	static void AddElement( Tools_ShapeTableElement* pxNewElement, Tools_ShapeTableElement*& pxList, int& iListLen );

	static void RemoveElement( Tools_ShapeTableElement* pxElementToRemove, Tools_ShapeTableElement*& pxList = s_pxTable, int& iListLen = s_iNumElementsInTable);
	static void UpdateReferenceCounts( void );
	static void ClearReferenceCount( void );
	static void IncrementReference( const Asura_Hash_ID uShapeHashID,bool bIncludeInExport = true);
	static Tools_ShapeTableElement* FindElementByHashID( const Asura_Hash_ID uShapeHashID, Tools_ShapeTableElement* pxList = s_pxTable );
	static Tools_ShapeTableElement* FindElementByFilename( const char* szName, Tools_ShapeTableElement* pxList = s_pxTable );
	static void ListBoxCallBack( void );
	static void OkaySelected( void );
	static void CancelSelected( void );
	static Tools_ShapeTableElement* GetElementByIndex( int iIndex, Tools_ShapeTableElement* pxList = s_pxTable, int iListLen = s_iNumElementsInTable );
	// RICHARDS		static void RemoveNonCommonShapes( void );


	static bool IsSafeToDeleteMesh(const Asura_Mesh* pxMesh);

	//Builds a list of shapes used in the level. Will contain duplicate entries
	//for shapes that are used more than once
	static void BuildListOfUsedShapes(List<Asura_Hash_ID>& xExportShapeList,List<Asura_Hash_ID>& xNonExportShapeList);


// Data
	static Tools_ShapeTableElement*			s_pxTable;			// Normal shapes added by the user
	static int								s_iNumElementsInTable;
	static Tools_ShapeTableElement*			s_pxExportShapes;	// Shapes added by the ***_Export.txt files
	static int								s_iNumExportShapes;
	static Asura_Hash_ID					s_uDefaultShapeID;
	
	static bool								s_bCloseShapeTable;
	static class Tools_ShapeTable_Overlay*	s_pxOverlay;
	static Tools_ShapeTableElement*			s_pxShapeTableSelection;

	static Tools_ShapeTable*				s_pxThis;
};

class Tools_ShapeTableElement
{
public:

	Tools_ShapeTableElement(){m_bIncludeInExport = true;m_bUsedInGame=true;}
	Tools_ShapeTableElement( const char* szShapeFile, Tools_ShapeTableElement*& pxList = Tools_ShapeTable::s_pxTable, int& iListLen = Tools_ShapeTable::s_iNumElementsInTable );

	~Tools_ShapeTableElement();
	
// Data
	Asura_Hash_ID					m_uHashID;
	char							m_szShapeName[ _MAX_PATH ];	// For display in the shape table
	char							m_szMeshName[ _MAX_PATH ];	// For use with GetMesh
	char							m_szFile[ _MAX_PATH ];
	unsigned int					m_uReferenceCount;
	class Tools_ShapeTableElement*	m_pxNext;
	//UsedInGame is used for marking those shapes in the main entity shape table that
	//are only used as 'Merge with environment'. Any such shapes will be marked as false 
	//and so won't get exported.
	//Shapes in the 'common' table always get marked as UsedInGame , and are controlled
	//just by m_bIncludeInExport
	bool							m_bUsedInGame;
	//IncludeInExport is set to true by default for all shapes , but can be disabled by
	//project export code to prevent the shape from being exported.
	//Shapes only get exported if both marked as UsedInGame and IncludeInExport.
	bool							m_bIncludeInExport;

	//used to determine if a shape file has changed... derived from the modified time of the file
	u_int							m_uChecksum;

};

class Tools_ShapeTable_Overlay : public Tools_Modal_Overlay
{
	friend class Tools_ShapeTable;
	
public:

	Tools_ShapeTable_Overlay( void );
	~Tools_ShapeTable_Overlay( void );

// RICHARDS		void AddItem( const char* szString, int iData = 0 );
	void DoModal( void );

// RICHARDS		const char* GetSelectionString();
// RICHARDS		int GetSelectionData();
// RICHARDS	
// RICHARDS		int GetNumItems(){return Items.size();}
	static int*						s_aiMappings;

private:
	virtual void InitialiseOverlay( class Asura_Overlay* Overlay );

// RICHARDS		List<ListSelectionItem*> Items;
// RICHARDS		char** Strings;
// RICHARDS	
// RICHARDS		int ListSelection;
// RICHARDS		int ListOffset;
// RICHARDS	
// RICHARDS		static void OkaySelected(){ReturnValue = true;}
// RICHARDS		static void CancelSelected(){ReturnValue = false;}
// RICHARDS	
// RICHARDS		static bool ReturnValue;

	static char**					s_pszListBoxStrings;
	static char**					s_pszAlphabetisedList;
	static int						s_iNumberOfEntriesInList;
	static int						s_iListBoxOffset;
	static int						s_iListBoxSelection;

};

class Tools_ShapeTable_WarningDlg : public Tools_Modal_Overlay
{
	public :
		Tools_ShapeTable_WarningDlg( const char* szWarningMsg );
		~Tools_ShapeTable_WarningDlg( void );
		
		void DoModal();

	private :
		virtual void InitialiseOverlay( class Asura_Overlay* Overlay );

// RICHARDS			//unfortunately this lot has to be static... but we should never end up
// RICHARDS			//with more than 1 copy of the overlay in action at a time
// RICHARDS			static void YesSelected(){ReturnValue = true;}
// RICHARDS			static void NoSelected(){ReturnValue = false;}

// RICHARDS			static bool ReturnValue;
		const char*	s_szWarning;
};





#endif __TOOLS_SHAPES_H__



////////////////////////////////////// End of file //////////////////////////////////////
