/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A.  All Rights Reserved.                         *
*                                                                          *
***************************************************************************/

#pragma once

#include "glmCrowdIOAPI.h"
#include "glmFbx.h"
#include <glmString.h>
#include <glmArray.h>
#include <glmList.h>
#include <glmMap.h>

namespace glm
{
	class Log;

	namespace crowdio
	{
		class CrowdFBXCharacter;

		/**
		* \brief Stores the information needed to (re)load a character
		*/
		struct CharacterLoadInfo
		{
			glm::GlmString filePath;
			glm::GlmString skeletonRootName;
			bool triangulate;
            bool generateTangents;
		};

		// Loads and stores the FBX characters that will be exported
		class GLM_CROWDIO_API CrowdFBXStorage
		{
		public:
			//************************************************************
			/*! @name Constructor & Destructor
			*/ //*********************************************************
			//@{
			/**
			* \brief Constructor
			* \param log Golaem Log in which to report status messages. If NULL, no log is used
			*/
			CrowdFBXStorage();

			/**
			* \brief Destructor
			*/
			virtual ~CrowdFBXStorage();
			//@}

			//************************************************************
			/*! @name Accessors
			*/ //*********************************************************
			//@{

			/** 
			* \brief Returns the FBXSDK manager
			*/
			const FbxManager* getFbxSdkManager() const;

			/** 
			* \brief Returns the FBXSDK manager
			*/
			FbxManager* touchFbxSdkManager();

			/**
			* \brief Loads and returns the FBX Character associated to the given filePath (or NULL if the character associated to the file path was never preloaded)
			* \param filePath File path of the character to search for
			* \warning The character must be preloaded (using preLoadCharacter) before calling this function
			*/
			CrowdFBXCharacter* getCharacter(const glm::GlmString& filePath, const glm::Array<glm::GlmString>& dirmap, bool& newCharacter);

			/**
			* \brief Returns the file names of the characters that have been preloaded
			*/
			void getUsedCharacterFiles(glm::Array<glm::GlmString>& characterFiles) const;

			/**
			* \brief Returns the maximum number of loaded characters
			*/
			unsigned int getMaxLoadedCharactersCount() const;

			/**
			* \brief Sets the maximum number of loaded characters
			*/
			void setMaxLoadedCharactersCount(unsigned int count);

			/**
			* \brief Returns the loaded characters
			*/
			const glm::GlmList<CrowdFBXCharacter*>& getLoadedCharacters() const;
			//@}

			/**
			* \brief Preloads a FBX character. Does nothing if the character already exists.
			* \param filePath The file path of the FBX file containing the character
			* \param skeletonRootName The name of the characters' skeleton root in the FBX file
			* \param[in] triangulate If true, all the meshes are triangulated
			* \param[in] generateTangents Generate tangent data
			*/
			void preLoadCharacter(
				const glm::GlmString& filePath, 
				const glm::GlmString& skeletonRootName, 
				bool triangulate = false,
				bool generateTangents = false);

			/**
			* \brief Unloads a character to save memory space
			* The character must first be preloaded
			* Calling getCharacter automatically reloads it
			*/
			void unloadCharacter(CrowdFBXCharacter* character);

			/**
			* \brief Unloads the character associated to the file and removes the file (the character is no longer preloaded)
			*/
			void removeFile(const glm::GlmString& filePath);

			/**
			* \brief Unloads all characters -> never called ?
			*/
			void clear();

		protected:
			//************************************************************
			/*! @name Data Members
			*/ //*********************************************************
			//@{

			/// The FBXSDK manager
			FbxManager* _fbxSdkManager;

			/// The imported characters
			glm::GlmMap<glm::GlmString, CrowdFBXCharacter*> _importedCharacters;

			/// The loaded characters
			glm::GlmList<CrowdFBXCharacter*> _loadedCharacters;

			/// The maximum number of loaded characters
			unsigned int _maxLoadedCharactersCount;

			/// The character reload infos, indexed by character id
			glm::GlmMap<glm::GlmString, CharacterLoadInfo> _importedCharactersLoadInfos;
			//@}
		};
	}
}
