#pragma once

#include <map>
#include <list>

#include "Mix/CriticalSection.h"
#include "Mix/Private/IO/Manager.h"

namespace Mix{ namespace IO{

	class Controller;
	class Archive;
	class Loader;

	class NarrowManager : public Mix::IO::Manager
	{
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::IO::NarrowManager
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	private:
		//各種値
		enum VALUE
		{
			ARCHIVE_MAGICNUMBER = 0x5F46414D,
			ARCHIVE_VERSION = 0x01000000,

			TYPE_LOAD = 0,
			TYPE_EXIT = 1,

			MAX_LOADQUEUE = 1024,
		};

		//アーカイブヘッダ構造体
		struct ARCHIVE_HEADER
		{
			UInt32 magicNumber;
			UInt32 version;
			UInt32 alignment;
			UInt32 fileCount;
			UInt32 stringSize;
			UInt32 reserve;
			UInt64 fileStart;
			UInt64 stringStart;
		};

		//アーカイブファイル構造体
		struct ARCHIVE_FILE
		{
			UInt32 namePos;
			UInt32 dataPos;
			UInt32 dataSize;
			UInt32 reserve;
		};

		//ファイルマップ
		typedef std::map<Mix::StringW, Mix::IO::Controller*> FileMap;

	public:
		static NarrowManager* CreateInstance( void );

	private:
		Mix::CriticalSection m_MySync;
		FileMap m_FileMap;

	private:
		NarrowManager( void );
		virtual ~NarrowManager( void );

	private:
		Boolean GetFileReader( const wchar_t* pFailedMsg, const wchar_t* pFilePath, Mix::IO::IReader** ppReader );

		Mix::IO::Controller* FindController( const wchar_t* pFilePath, Boolean bWrite, const wchar_t* pFailedMsg );
		Mix::Memory::IBuffer* CreateBufferFromFile( const wchar_t* pFilePath, const wchar_t* pFailedMsg );
//		Mix::IO::Controller* InsertController( const wchar_t* pFilePath, const wchar_t* pFailedMsg );

		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::IO::IManager
		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public:
		virtual Boolean MountArchive( const wchar_t* pFilePath );
		virtual Boolean MountDirectory( const wchar_t* pDirectoryPath );
		virtual Boolean MountFile( const wchar_t* pFilePath );

		virtual Boolean ExistsFile( const wchar_t* pFilePath );

		virtual Boolean CreateBufferFromFile( const wchar_t* pFilePath, Mix::Memory::IBuffer** ppBuffer );

		virtual Boolean CreateFileReader( const wchar_t* pFilePath, Mix::IO::IReader** ppReader );
		virtual Boolean CreateBufferedReader( const wchar_t* pFilePath, Mix::IO::IReader** ppReader );
		virtual Boolean CreateBufferedReader( const wchar_t* pName, Mix::Memory::IBuffer* pBuffer, Mix::IO::IReader** ppReader );

		virtual Boolean CreateFileWriter( const wchar_t* pFilePath, Mix::IO::IWriter** ppWriter );

	private:
		static const wchar_t* FAILED_MOUNTARCHIVE;
		static const wchar_t* FAILED_MOUNTDIRECTORY;
		static const wchar_t* FAILED_MOUNTFILE;
	};

}}
