//
// Tools_Animation_Files.h
//
// Created by Richard Rice - 15/08/2002
// 
// Copyright (C) 2002 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __TOOLS_ANIMATION_FILES_H__
#define __TOOLS_ANIMATION_FILES_H__

#include "Misc/list_tem.hpp"
#include "Core/Asura_String.h"
#include "Core/Asura_Hash.h"

struct ToolsAnimationDirectory;
struct ToolsSkinFile;
struct ToolsSkinCategory;
struct ToolsAnimCategory;

class Asura_Hierarchy_Skin;
class Asura_Hierarchy_Anim;
class Asura_AnimTable;



//options for ReloadAnims()/ReloadSkins()
enum Tools_Animation_Files_ReloadOptions
{
	TOOLS_ANIMATION_RELOAD_ALL, //reload all skins/anims
	TOOLS_ANIMATION_RELOAD_FILEMODIFIED, //reload skin/anims whose modified time has changed since being loaded
	TOOLS_ANIMATION_RELOAD_PLATFORMSPECIFIC, //reload any skins/anims that have platform specific versions
};

class Tools_Animation_Files
{
public :
	Tools_Animation_Files();
	virtual ~Tools_Animation_Files();

	static const List<ToolsAnimationDirectory*>* GetDirectoryList();
	static const List<ToolsSkinFile*>* GetSkinList();
	static void ListAnimations(const char* pszDir,List<Asura_String>* pxOutputAnimNameList,List<Asura_String>* pxOutputFilenameList,bool bRecurse = true);
	static const char* GetDefaultAnimDirForSkin(const char* pszSkin);

	static bool ChooseSkin(const Asura_Hierarchy_Skin** ppxOutputSkin);
	static bool ChooseSkin_AllowNone(const Asura_Hierarchy_Skin** ppxOutputSkin);
	//If bOutputIsAlsoDefault , then ppxOutputAnim points at a valid default anim when the function is called
	static bool ChooseAnimation(const Asura_Hierarchy_Skin* pxSkin,const Asura_Hierarchy_Anim** ppxOutputAnim,bool bOutputIsAlsoDefault = false);

	//Picks a skin outputing the name and filename.
	//Pass null pointers for information that isn't needed
	static Asura_Hierarchy_Skin* ChooseSkin(Asura_String* pxSkinName,Asura_String* pxSkinFilename);
	//Pick an animation for a named skin.
	//pxDir is optional input/output for the current dir to look in
	//pxAnimName is the output animation name (pass null if this isn't needed)
	//pxAnimFilename is the output animation filename (pass null if this isn't needed)
	//pxDefaultAnim is the anim that will be selected in the lists by default (if its there)
	//bAllowNone will cause a no-anim option to be added
	//pbWasCancelled is optional output for indicating whether the user cancelled the selection process
	static Asura_Hierarchy_Anim* ChooseAnimation(const char* pszSkinName,Asura_String* pxDir,Asura_String* pxAnimName,Asura_String* pxAnimFilename,const Asura_Hierarchy_Anim* pxDefaultAnim = 0,bool bAllowNone=false, bool* pbWasCancelled = 0);

	//locate a skin or animation in the characters dir
	static bool FindFile(const char* pszName,Asura_String* pOutputFilename);

	//set an extra directory containing anims/skins specific to a cutscene
	static void SetCutsceneDirectory(const char* pszDir);

	static bool IsSkinMeshLoaded(const Asura_Hierarchy_Skin* pxSkin);

	//Attempts to load the Asura_Mesh for a skin from the original file , if it isn't currently loaded
	static bool LoadMeshForSkin(Asura_Hierarchy_Skin* pxSkin);
	static void LoadMeshesForAllSkins();

	//Loads the 'keyframe' sounds associated with the skins
	static void LoadSoundsForSkin(const Asura_Hierarchy_Skin* pxSkin);
	//and for anims
	static void LoadSoundsForAnim(const Asura_Hierarchy_Anim* pxAnim);
	//and for everything
	static void LoadSoundsForAllSkinsAndAnims();

	//Attempts to load the original uncompressed animation file (if the current animation came from
	//and exported character file)
	static void LoadUncompressedAnimation(Asura_Hierarchy_Anim* pxAnim,const char* pszFilename = NULL);

	//Attempts to reload all the animations from the original files.
	static void ReloadAllAnimations() {ReloadAnimations(TOOLS_ANIMATION_RELOAD_FILEMODIFIED);}
	static void ReloadAnimations(Tools_Animation_Files_ReloadOptions eReloadType);
	#ifdef ASURA_SUPPORT_COMMAND_CONSOLE
	static bool ConsoleCmd_ReloadAllAnimations(bool bHelp);
	#endif

	//and for skins
	static void ReloadAllSkins() {ReloadSkins(TOOLS_ANIMATION_RELOAD_FILEMODIFIED);}
	static void ReloadSkins(Tools_Animation_Files_ReloadOptions eReloadType);
	#ifdef ASURA_SUPPORT_COMMAND_CONSOLE
	static bool ConsoleCmd_ReloadAllSkins(bool bHelp);
	#endif


	//Gets the list of animations that would appear in the ChooseAnim overlay
	static void GetChooseAnimListFromDirectory(const char* pszDir,List<Asura_String>* pxOutputAnimNameList,List<Asura_String>* pxOutputFilenameList);

	//Gets skin/anim from hash ID ,loading them if needed
	static Asura_Hierarchy_Skin* GetSkinFromID(Asura_Hash_ID uSkinID,Asura_Hash_ID uFileID = ASURA_HASH_ID_UNSET,bool bShowMessages = true);
	static Asura_Hierarchy_Anim* GetAnimFromID(Asura_Hash_ID uAnimID,Asura_Hash_ID uFileID = ASURA_HASH_ID_UNSET,bool bShowMessages = true);

	#ifndef ASURA_DISABLE_ANIM_TABLE_CODE
	//Attempts to get/load an anim table from a hash id or name
	//It will be only able to load the animtable by hash ID if there is a matching asura file
	//that can be found by the hashed filename system (such as a skin).
	static Asura_AnimTable* GetAnimTable(Asura_Hash_ID uHash);
	static Asura_AnimTable* GetAnimTable(const char* szName);
	static Asura_AnimTable* GetAnimTable(Asura_Hash_ID uHashID,const char* szName);
	#endif


	static void GetStandardRestAnim(Asura_String& xStandardRestAnimFile, Asura_String& xStandardRestAnimPath);

	static bool BrowseForAsuraFile(const char* pszTitle,Asura_String& xFilename,bool bAnim,const char* szDefaultPath = 0);

protected :
	
	virtual void GetStandardRestAnimMain(Asura_String& xStandardRestAnimFile, Asura_String& xStandardRestAnimPath);

	virtual void UpdateDirectoryList();
	void AddDirectory(const char* pszDir,const char* pszName);

	virtual void UpdateSkinList();
	void AddToSkinList(const char* pszFilename);

	virtual const List<ToolsAnimationDirectory*>* GetDirectoryListMain();
	virtual const List<ToolsSkinFile*>* GetSkinListMain();

	virtual void ListAnimationsMain(const char* pszDir,List<Asura_String>* pxOutputAnimNameList,List<Asura_String>* pxOutputFilenameList, bool bRecurse);

	void ListAnimationsInTextFile(const char* pszTextFile,List<Asura_String>* pxOutputAnimNameList,List<Asura_String>* pxOutputFilenameList);
	void ListAnimationsInCategory(const char* pszCategory,List<Asura_String>* pxOutputAnimNameList,List<Asura_String>* pxOutputFilenameList);

	void LoadAnimationIniFile();

	const char* GetDefaultAnimDirForSkinMain(const char* pszSkin);


	bool ChooseSkinMain(const Asura_Hierarchy_Skin** ppxSkin, Asura_String* pxSkinName,Asura_String* pxSkinFilename, bool bAllowNone);
	void ChooseSkinCategory();
	void ChooseSkinFromCategory(Asura_String* pxSkinName,Asura_String* pxSkinFilename);
	void ChooseSkinDisplayAll(Asura_String* pxSkinName,Asura_String* pxSkinFilename,const Asura_String* pxInitialSkin, bool bAllowNone);
	void ChooseSkinCutsceneSpecific(Asura_String* pxSkinName,Asura_String* pxSkinFilename, bool bAllowNone);
	void ChooseSkinBrowseDisk(Asura_String* pxSkinName,Asura_String* pxSkinFilename, const Asura_String* pxInitialName,const Asura_String* pxInitialFile);
	void UpdateSkinSelectionState(const char* pszOption);

	
	const Asura_Hierarchy_Anim* ChooseAnimationMain(const char* pszSkinName,Asura_String* pDir,Asura_String* pAnimName,Asura_String* pAnimFilename,const Asura_Hierarchy_Anim* pxDefaultAnim,bool bAllowNone,bool* pbWasCancelled);
	bool ChooseAnimCategory(const char* pszSkin,Asura_String* pxDir);
	bool ChooseAnimDirectory(const char* pszSkin,Asura_String* pxDir,bool bAllowNone);
	bool ChooseAnimFromCategory(Asura_String* pxDir,Asura_String* pxAnimName,Asura_String* pxAnimFilename,const Asura_Hierarchy_Anim* pxDefaultAnim,bool bAllowNone);
	bool ChooseAnimFromDirectory(Asura_String* pxDir,Asura_String* pxAnimName,Asura_String* pxAnimFilename,const Asura_Hierarchy_Anim* pxDefaultAnim,bool bAllowNone);
	bool ChooseAnimFromCutsceneDirectory(Asura_String* pxDir,Asura_String* pxAnimName,Asura_String* pxAnimFilename,const Asura_Hierarchy_Anim* pxDefaultAnim);
	bool ChooseAnimBrowseDisk(Asura_String* pxAnimName,Asura_String* pxAnimFilename, const Asura_Hierarchy_Anim* pxInitialAnim);

	void ListAnimCategoriesForSkin(const char* pszSkinName,List<const char*>& xCatList);

	virtual bool FindFileMain(const char* pszName,Asura_String* pOutputFilename);

	virtual int GetNumberOfRootDirectories();
	virtual const char* GetDirectory(int iIndex);

	//Gets the strings that need to be tacked onto the end of the animation table names to
	//generated the filenames.
	//The postfix doesn't need to include the initial underscore.
	virtual int GetNumberOfAnimTableFilePostFixes() {return 0;}
	virtual const char* GetAnimTableFilePostFix(int iIndex) {return 0;}


	List<ToolsAnimationDirectory*> m_xDirectoryList;
	List<ToolsSkinFile*> m_xSkinList;

	bool m_bIniFileLoaded;
	List<ToolsSkinCategory*> m_xSkinCatList;
	List<ToolsAnimCategory*> m_xAnimCatList;


	enum SkinSelectionState
	{
		SSS_CANCEL,
		SSS_OKAY,
		SSS_SELECT_CATEGORY,
		SSS_SELECT_FROM_CATEGORY,
		SSS_DISPLAY_ALL,
		SSS_CUTSCENE_SPECIFIC,
		SSS_BROWSE_DISK,
	} m_eSkinSelectionState;

	ToolsSkinCategory* m_pxCurrentSkinCat;

	Asura_String m_xCutsceneDirectory;


public :
	static Tools_Animation_Files* s_xThis;
};

struct ToolsAnimationDirectory
{
	Asura_String m_xDirectory;
	Asura_String m_xName;
};

struct ToolsSkinFile
{
	Asura_String m_xFilename;
	Asura_String m_xName;
	Asura_String m_xDefaultAnimDir;
};


struct ToolsSkinCategory
{
	Asura_String m_xName;
	List<Asura_String> m_xSkinList;
	List<ToolsAnimCategory*> m_xAnimCatList;
};

struct ToolsAnimCategory
{
	Asura_String m_xName;
	List<Asura_String> m_xAnimList;
};


#endif //__TOOLS_ANIMATION_FILES_H__
