//********************************************************************************************
/**
 * @file		smpl_d2arc.cpp
 * @brief		D2アーカイバ
 *
 *	このファイルの詳細説明
 *
 * @date		2013/01/09	takedan	新規作成.
 */
//********************************************************************************************

//#define	SW_MODULE_SMPL_D2ARC						///< この機能を切り離したい時はコメントアウト.
#if 0//def	SW_MODULE_SMPL_D2ARC

#ifdef _UNICODE

//********************************************************************************************
/**
 * @class		SMPL_D2ARC
 * @brief		D2アーカイバスクリプトコマンドクラス.
 */
//********************************************************************************************
class SMPL_D2ARC
{
	Bool		m_bInitialized;
	Bool		m_bImplemented;
	Bool		m_bFullInit;
	
	void		Initialize();
	
	Char		*m_pOut;
	Int32		m_iLength;
	TCHAR		m_sOutName[ T_MAXPATH ];
	
	enum{	enBuffSize = 1024*1024	};
	
	struct StFIleInfo
	{
		UInt32	m_uCrcName;
		UInt32	m_uOffset;
		UInt32	m_uSize;
	};
	struct StHeader
	{
		Char		m_sId[ 4 ];
		Int16		m_iEntry;
		Int16		m_iRefEntry;
		
		StFIleInfo	m_stFiles[ 256 ];	//!< 最大値. 256個のデータ長があるわけではない.
	};
	
	StHeader	m_stHeader;
	
public:
	virtual int		Func( LPCTSTR _sParamString );
	virtual void	Quit( Bool _bExit );
	
	SMPL_D2ARC();
	virtual ~SMPL_D2ARC();
	
};

//********************************************************************************************
/**
 * @brief		D2アーカイバコンストラクタ.
 */
//********************************************************************************************
SMPL_D2ARC::SMPL_D2ARC()
	: m_bFullInit( FALSE )
	, m_pOut( NULL )
	, m_sOutName()
	, m_bInitialized( FALSE )
	, m_bImplemented( FALSE )
{
	
}

//********************************************************************************************
/**
 * @brief		D2アーカイバデストラクタ.
 */
//********************************************************************************************
SMPL_D2ARC::~SMPL_D2ARC()
{
	
}


//==============================================================================================================================================
/**
	初期化と開放.
		1ファイルに1つの処理でコンプリートするような場合は修正する必要ありません
		注釈となっている Message_printf を有効にして sample.swb を実行すると動きがよく分かると思います。
*/
//==============================================================================================================================================

//********************************************************************************************
/**
 * @brief		D2アーカイバスクリプトコマンドの初期化.
 *				(特に必要ないなら変更の必要なし)
 *
 * @return		なし (none)
 */
//********************************************************************************************
void	SMPL_D2ARC::Initialize()
{
	if( m_bInitialized == TRUE )	return;
	m_bInitialized = TRUE;	//	初期済みフラグ
	
	if( m_bFullInit == FALSE )
	{
		m_bFullInit = TRUE;
		//	全体を通して一度しか行わない初期化
		
		//Message_printf( TEXT("全体の初期化") );
		
		/// 変換後のデータバッファを確保
		mem_alloc( Char, m_pOut, enBuffSize );
		m_iLength = 0;
		
		memcpy( m_stHeader.m_sId, "D2C", 4 );
		m_stHeader.m_iEntry = 0;
		m_stHeader.m_iRefEntry = 0;
		
	}
	
	//	初期化処理
	//	１つのバッチに同じスクリプトが２度指定されていたならここには２度来る
	//Message_printf( TEXT("初期化") );
	
}

//********************************************************************************************
/**
 * @brief		D2アーカイバスクリプトコマンドの終了.
 *				(特に必要ないなら変更の必要なし)
 *
 * @param[in]	Bool	_bExit	.
 *
 * @return		なし (none)
 */
//********************************************************************************************
void	SMPL_D2ARC::Quit(Bool _bExit)
{
	//	ここにはスクリプトを使っていなくても来るので注意
	
	if( m_bImplemented == FALSE )	return;		///<変換処理が実行されていないなら帰還.
	m_bImplemented = FALSE;
	m_bInitialized = FALSE;
	
	///	終了処理.
	//Message_printf( TEXT("終了") );
	
	if( _bExit == TRUE )
	{
		//	次のスクリプトは存在しない、完全な終了
		//	１つのバッチに同じスクリプトに別パラメータを渡しての処理で
		//	逐一結果を出さず、全体で統合して結果を出したい場合などはここで
		#define	HEADER_SIZE		(8)
		
	//	Message_printf( TEXT("全体の終了") );
		
		Char	cRefStr[1024] = "";
		Int32	iRefLength = 0;
		{
			TCHAR	cWork[T_MAXPATH], cDrive[_MAX_DRIVE], cDir[_MAX_DIR], cName[_MAX_PATH];
			FILE_split( m_sOutName, cDrive, cDir, cName, NULL );
			FILE_merge( cWork, cDrive, cDir, cName, TEXT(".d2a") );
			
			TCHAR	*pMem = NULL;
			Int32	iLen = MEM_TextRead( &pMem, cWork );
			
			TCHAR	*pp = pMem;
			while( 1 )
			{
				pp = STRING_str( pp, TEXT("<Reference") );
				if( !pp )	break;
				pp = STRING_str( pp, TEXT("<data name=\"") );
				if( !pp )	break;
				pp += STRING_len( TEXT("<data name=\"") );
				Int32	ii=0;
				while( *pp != '"' )	cWork[ ii++ ] = *pp++;
				cWork[ ii ] = '\0';
				
				if( STRING_cmp( cWork, TEXT("n_all") ) == 0 )	continue;
				
				if( cWork[ 0 ] != '@' )	continue;
				TCHAR	*pPtr = &cWork[ 1 ];
				
				CTOSJIS	cJis(pPtr);
				BUF_copy( &cRefStr[ iRefLength ], cJis.Get(), STRING_len(pPtr) );
				iRefLength += STRING_len( pPtr ) + 1;
				m_stHeader.m_iRefEntry++;
			}
			
			del_alloc( pMem );
		}
		if(0<iRefLength)	iRefLength += 4 - (iRefLength % 4);
		
		//! 各オフセットにヘッダー分を加算.
		for( Int32 ii=0 ; ii<m_stHeader.m_iEntry ; ii++ )
		{
			m_stHeader.m_stFiles[ ii ].m_uOffset += (HEADER_SIZE + sizeof(StFIleInfo)*m_stHeader.m_iEntry) + iRefLength;
		}
		
		//! データ出力.
		FILE_TargetWrite( m_sOutName, &m_stHeader, HEADER_SIZE + sizeof(StFIleInfo)*m_stHeader.m_iEntry );
		if(0<iRefLength)	FILE_TargetWriteMerge( m_sOutName, cRefStr, iRefLength );
		FILE_TargetWriteMerge( m_sOutName, m_pOut, m_iLength );
		
		del_alloc( m_pOut );
		#undef	HEADER_SIZE
	}
	
}







//==============================================================================================================================================
//	変換処理部分
//==============================================================================================================================================

#define	SMPL_D2ARC_OUTAREA		2	///< 変換後の容量は仮に元の倍取っている　内容によって変更して下さい.
#define	SMPL_D2ARC_RANGE				///< このdefineを有効にすると範囲限定機能が有効になる.


//********************************************************************************************
/**
 * @brief	D2アーカイバ変換フィルターサンプル　機能:無変換
 *			テキストデータを取り扱うサンプル.
 *			関数内は patol.lib を使用したサンプルになっているが、中身は完全に別物に変えても問題ありません.
 *
 *			
 *
 * @param[in]	LPCTSTR	_sParamString	引数文字列  ターゲットファイル名 + スクリプトで指定する引数.
 *
 * @return		int	TRUE:成 / FALSE:否(デフォルト)
 */
//********************************************************************************************
int		SMPL_D2ARC::Func( LPCTSTR _sParamString )
{
	CSwbParam	cParam( _sParamString );							///< パラメータ処理.
	
	Char		*pMem = NULL;
	int			iSourceLength;
	LPCTSTR		szFileName;
	Char		cCrcName[ _MAX_FNAME ];
	
	/// 引数の取り出し.
	/**
	 * ターゲットファイル (GetString(0)としても同じ).
	 * swb ファイルでは指定しない、システムで付加される引数.
	 */
	szFileName = cParam.GetPath();
	
	
	/// 機能の初期化.
	Initialize();
	
	{
		TCHAR	cDrive[_MAX_DRIVE], cDir[_MAX_DIR], cName[_MAX_PATH], cExt[_MAX_EXT];
		FILE_split( szFileName, cDrive, cDir, cName, cExt );
		
		if( STRING_cmp( cExt, TEXT(".d2a") ) == 0 || STRING_cmp( cExt, TEXT(".d2b") ) == 0 )
		{
			FILE_merge( m_sOutName, cDrive, cDir, cName, TEXT(".d2c") );
			STRING_cpy( cName, TEXT("D2DATA") );
		}else{
			STRING_cat( cName, TEXT(".tga") );
		}
		
		CTOSJIS	cJis(cName);
		memcpy( cCrcName, cJis.Get(), strlen(cJis.Get())+1 );
	}
	
	
	
	/// 元データ読み込み(関数内部でpMemに領域を確保している).
	iSourceLength = MEM_TargetRead( &pMem, szFileName );							///< UNICODEの場合 UTF16に変換されて読まれます.
	if( iSourceLength == 0 )
	{
		/** エラーメッセージの表示　処理はMessage_printfと同じ、Message_errorを使用すると自動終了しなくなります */
		Message_error( TEXT("file not found:%s"), szFileName );
		return FALSE;						///< ファイルがない.
	}
	
	m_bImplemented = TRUE;					///< 実行済みフラグon. これをonにしないとQuit()が実行されない.
	
	T_ASSERT( m_iLength+iSourceLength < enBuffSize );
	if( m_iLength+iSourceLength >= enBuffSize )
	{
		Message_error( TEXT("buff over:%s"), szFileName );
		return FALSE;
	}
	BUF_copy( m_pOut + m_iLength, pMem, iSourceLength );
	
	CTOUTF16	cUtf(cCrcName);
	m_stHeader.m_stFiles[ m_stHeader.m_iEntry ].m_uCrcName = STRING_crc32( cUtf.Get() );
	m_stHeader.m_stFiles[ m_stHeader.m_iEntry ].m_uOffset = m_iLength;
	m_stHeader.m_stFiles[ m_stHeader.m_iEntry ].m_uSize = iSourceLength;
	Message_printf( TEXT("%-24s 0x%08X,0x%08X,0x%08X"), cUtf.Get(), m_stHeader.m_stFiles[ m_stHeader.m_iEntry ].m_uCrcName, m_stHeader.m_stFiles[ m_stHeader.m_iEntry ].m_uOffset, m_stHeader.m_stFiles[ m_stHeader.m_iEntry ].m_uSize );
	m_stHeader.m_iEntry++;
	
	
	m_iLength += ((iSourceLength+3)/4)*4;
	
	/// メモリを開放.
	del_alloc( pMem );
	
	return TRUE;
}
#else
class SMPL_D2ARC
{
public:
	virtual int		Func( LPCTSTR _sParamString ){return 0;}
	virtual void	Quit( BOOL _bExit ){}
	
	SMPL_D2ARC(){}
	virtual ~SMPL_D2ARC(){}
};
#endif	// _UNICODE


SMPL_D2ARC	*pC_smpl_d2arc = NULL;

#endif	// SW_MODULE_SMPL_D2ARC
