#include"CStorageCore.h"
#include"../../Auxiliary/Debug/CAssert.h"
#include"../../Auxiliary/Debug/CTrace.h"

//	ゲーム側で呼ばれる関数

namespace Maid
{

CStorageCore*	GlobalPointer<CStorageCore>::s_pPointer;

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! コンストラクタ
/*!	
 */
CStorageCore::CStorageCore()
{
	GlobalPointer<CStorageCore>::Set();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! デストラクタ
/*!	
 */
CStorageCore::~CStorageCore()
{
	Finalize();
	GlobalPointer<CStorageCore>::Clear();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 実行する関数の登録
/*!	
	実行する関数の書式は
@code
	SPRETURNPARAM STORAGEFUNCTION( const mstring& FileName, const SPSTORAGEFUNCTION_FUNCTIONPARAM& pParam )
\n	{
\n		return SPRETURNPARAM();
\n	}
@endcode
\n	となります

	@param	FuncNo	[i ]	登録する番号
	@param	func	[i ]	実行させる関数
 */
void CStorageCore::RegistFunction( int FuncNo, const STORAGEFUNCTION& func )
{
	CThreadMutexLocker Lock(m_FunctionMutex);	//	わざわざとる必要なさそうだけど一応

	MAID_ASSERT( m_FunctionMap.find(FuncNo)!=m_FunctionMap.end(), "関数が存在しています" );

	m_FunctionMap[FuncNo] = func;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! このクラスの初期化
/*!	
	ほかのメンバを呼ぶ前にこの関数を呼んでおくこと
 */
void CStorageCore::Initialize()
{
	m_ReturnCode.resize(1000);	//	こんだけあれば十分？
	for( int i=0; i<(int)m_ReturnCode.size(); ++i )
	{
		m_ReturnCode[i].State = RETURNCODE::STATE_NONE;
	}

	m_Thread.SetFunc( MakeThreadObject(&CStorageCore::ThreadFunction,this) );
	m_Thread.Execute();
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! このクラスの解放
/*!	
	この関数を呼んだら、ほかの関数を呼ぶことを禁止します。
 */
void CStorageCore::Finalize()
{
	m_Thread.Close();
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 指定したファイル名の読み込み
/*!	
	@param	FuncNo	 [i ]	実行させる関数番号
	@param	FileName [i ]	読み込むファイル名
	@param	pParam	 [i ]	ファイル名以外の引数

	@return	読み込み状態を調べるためのハンドル
 */
int CStorageCore::Execute( int FuncNo, const mstring& FileName, const SPSTORAGEFUNCTION_FUNCTIONPARAM& pParam )
{
	CThreadMutexLocker Lock(m_MessageMutex);

	const int ret = CreateReturnCode();

	POSTMESSAGE mess;

	mess.FunctionNo   = FuncNo;
	mess.ReturnCodeID = ret;
	mess.FileName = FileName;
	mess.pParam = pParam;

	m_MessageQue.push_back(mess);

	return ret;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 実行中の読み込み処理を中断する
/*!	
	@param	no	 [i ]	中断させる番号(Execute()の戻り値)
 */
void CStorageCore::Cancel( int no )
{
	CThreadMutexLocker Lock(m_MessageMutex);

	POSTMESSAGE mess;

	mess.FunctionNo = POSTMESSAGE::CANCEL;
	mess.ReturnCodeID = no;

	m_MessageQue.push_back(mess);
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 現在読み込み中か問い合わせる
/*!	
	@param	no	 [i ]	問い合わせ番号(Execute()の戻り値)

 	@return	no	 [i ]	読み込み中なら true
*/
bool CStorageCore::IsNowLoading( int no )
{
	//	CThreadMutexLocker Lock(m_MessageMutex);
	//	ここはなくても問題ない
	return m_ReturnCode[no].State==RETURNCODE::STATE_LOADING;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 読み込みの終わった戻り値を取得する
/*!	
	同じ番号を連続で呼んだ場合、２回目以降はなにも戻りません。

	@param	no	 [i ]	問い合わせ番号(Execute()の戻り値)

 	@return	読み込み結果
*/


SPSTORAGEFUNCTION_RETURNPARAM CStorageCore::GetReturnParam( int no )
{
	//	CThreadMutexLocker Lock(m_MessageMutex);
	//	ここはなくても問題ない
	RETURNCODE& code = m_ReturnCode[no];

	SPSTORAGEFUNCTION_RETURNPARAM pRet;

	code.pMess.swap( pRet );				//	この２行の順番は守ること！
	code.State = RETURNCODE::STATE_NONE;	//

	return pRet;
}

int CStorageCore::CreateReturnCode()
{
	//	空いている終了コードを探す&作成する
	for( int i=0; i<(int)m_ReturnCode.size(); ++i )
	{
		RETURNCODE& code = m_ReturnCode[i];
		if( code.State == RETURNCODE::STATE_NONE )
		{
			code.State = RETURNCODE::STATE_LOADING;
			return i;
		}
	}

	MAID_ASSERT( true, "領域が足りません" );

	return -1;
}













}

