//********************************************************************************************
/**
 * @file		SongDataConvert.cpp
 * @brief		歌詞大データコンバータ
 *
 *	このファイルの詳細説明
 *
 * @date		2013/07/03	abesh	新規作成.
 */
//********************************************************************************************

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


//********************************************************************************************
/**
 * @class		SONGDATACONVERT
 * @brief		歌詞大データコンバータスクリプトコマンドクラス.
 */
//********************************************************************************************
class SONGDATACONVERT
{
	BOOL		m_bInitialized;
	BOOL		m_bImplemented;
	BOOL		m_bFullInit;
	
	void		Initialize();
	
public:
	virtual int		Func( LPCTSTR _sParamString );
	virtual void	Quit( BOOL _bExit );
	
	SONGDATACONVERT();
	virtual ~SONGDATACONVERT();
	
};

//********************************************************************************************
/**
 * @brief		歌詞大データコンバータコンストラクタ.
 */
//********************************************************************************************
SONGDATACONVERT::SONGDATACONVERT()
	: m_bFullInit( FALSE )
	, m_bInitialized( FALSE )
	, m_bImplemented( FALSE )
{
	
}

//********************************************************************************************
/**
 * @brief		歌詞大データコンバータデストラクタ.
 */
//********************************************************************************************
SONGDATACONVERT::~SONGDATACONVERT()
{
	
}


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

//********************************************************************************************
/**
 * @brief		歌詞大データコンバータスクリプトコマンドの初期化.
 *				(特に必要ないなら変更の必要なし)
 *
 * @return		なし (none)
 */
//********************************************************************************************
void	SONGDATACONVERT::Initialize()
{
	if( m_bInitialized == TRUE )	return;
	m_bInitialized = TRUE;	//	初期済みフラグ
	
	if( m_bFullInit == FALSE )
	{
		m_bFullInit = TRUE;
		//	全体を通して一度しか行わない初期化
		
		//Message_printf( TEXT("全体の初期化") );
		
	}
	
	//	初期化処理
	//	１つのバッチに同じスクリプトが２度指定されていたならここには２度来る
	//Message_printf( TEXT("初期化") );
	
}

//********************************************************************************************
/**
 * @brief		歌詞大データコンバータスクリプトコマンドの終了.
 *				(特に必要ないなら変更の必要なし)
 *
 * @param[in]	BOOL	_bExit	.
 *
 * @return		なし (none)
 */
//********************************************************************************************
void	SONGDATACONVERT::Quit(BOOL _bExit)
{
	//	ここにはスクリプトを使っていなくても来るので注意
	
	if( m_bImplemented == FALSE )	return;		///<変換処理が実行されていないなら帰還.
	m_bImplemented = FALSE;
	m_bInitialized = FALSE;
	
	///	終了処理.
	//Message_printf( TEXT("終了") );
	
	if( _bExit == TRUE )
	{
		//	次のスクリプトは存在しない、完全な終了
		//	１つのバッチに同じスクリプトに別パラメータを渡しての処理で
		//	逐一結果を出さず、全体で統合して結果を出したい場合などはここで
		
		//Message_printf( TEXT("全体の終了") );
	}
	
}

//自作定数.
#define	TEXTURE_MAX					4   ///変更に使うtextureの最大数
#define	TEXTURE_NAME_SIZE			256  ///textureの名前のサイズ

//********************************************************************************************
/**
 * @brief		CSVシートから指定セルの文字列を取得.
 *
 * @param[in]	LPCTSTR		_pBuff			CSVを格納したバッファ.
 * @param[in]	const Int32	_iSize			CSVサイズ.
 * @param[in]	const Int32	_iR				列(1〜).
 * @param[in]	const Int32	_iC				行(1〜).
 * @param[out]	LPTSTR		_pReceiptBuff	受け取りバッファ.
 * @param[in]	const Int32	_iReceiptSize	受け取りサイズ.
 *
 * @return		Int32	取得した文字数.
 */
//********************************************************************************************
Int32	My_CSV_GetCell( LPCTSTR _pBuff, const Int32 _iSize, const Int32 _iR, const Int32 _iC, LPTSTR _pReceiptBuff, const Int32 _iReceiptSize )
{
	int i = 0;
	int column = 1, record = 1;

	//指定された行までiを進める.
	while(i < _iSize){
		if(record == _iR) break;
		
		//改行されたらrecord++
		if(*(_pBuff+i) == '\r') {
			record++;
			if (*(_pBuff+i+1) == '\n')i++;
		}else if(*(_pBuff+i) == '\n') {
			record++;
		}
		
		//改行の次で外に出たいのでiの更新はこの位置
		i++;										
	}
	
	while(i < _iSize){
		if(column == _iC) break;
		
		//列を数える
		if(*(_pBuff+i) == ',') column++;
		//行が変わったら不成功.
		else if(*(_pBuff+i) == '\r' || *(_pBuff+i) == '\n') return 0;
		
		i++;
	}

	int j = 0;
	while(i < _iSize){
		if((*(_pBuff+i+j) == '\r' )||(*(_pBuff+i+j) == '\n' )||(*(_pBuff+i+j) == ','))return STRING_len(_pReceiptBuff);
		*(_pReceiptBuff+j) =  *(_pBuff+i+j); 
		j++;
	}
	
	return 0;
}

//********************************************************************************************
/**
 * @brief		指定した文字列を数える.
 *
 * @param[in]	LPCTSTR		_pBuff			文字列を格納したバッファ.
 * @param[in]	LPCTSTR		_pCharList		数える文字列.
 *
 * @return		Int32	ファイル内にある指定した文字列の数.
 */
//********************************************************************************************
Int32	My_STRING_Count( LPCTSTR _pBuff, LPCTSTR _pCharList = NULL)
{
	int count=0;
	LPTSTR _pWork = (LPTSTR)_pBuff;
	

	while(_pWork = STRING_str(_pWork, _pCharList)) {
		count++;
		_pWork++;	//ずらして再検索.
	}
	return count;
}

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

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

//********************************************************************************************
/**
 * @brief	歌詞大データコンバータ変換フィルターサンプル　機能:無変換
 *			テキストデータを取り扱うサンプル.
 *			関数内は patol.lib を使用したサンプルになっているが、中身は完全に別物に変えても問題ありません.
 *
 *			
 *
 * @param[in]	LPCTSTR	_sParamString	引数文字列  ターゲットファイル名 + スクリプトで指定する引数.
 *
 * @return		int	TRUE:成 / FALSE:否(デフォルト)
 */
//********************************************************************************************
int		SONGDATACONVERT::Func( LPCTSTR _sParamString )
{
	CSwbParam	cParam( _sParamString );							///< パラメータ処理.
	
	TCHAR	*pMem = NULL;			//読み込み,csvファイル.
	TCHAR	*pOut = NULL;			//出力.
	TCHAR	*pBase1 = NULL;			//変えるテクスチャーが1つのときに使うd2aファイルのデータ.
	TCHAR	*pBase2 = NULL;			//変えるテクスチャーが２つのときに使うd2aファイルのデータ.
	TCHAR	*pBase3 = NULL;			//変えるテクスチャーが３つのときに使うd2aファイルのデータ.
	TCHAR	*pBase4 = NULL;			//変えるテクスチャーが４つのときに使うd2aファイルのデータ.
	TCHAR	*pBase5 = NULL;			//変えるテクスチャーが5つのときに使うd2aファイルのデータ.
	TCHAR	*pBase6 = NULL;			//変えるテクスチャーが6つのときに使うd2aファイルのデータ.
	TCHAR	*pTargetBase = NULL;	//d2aファイルのデータを受け取るポインタ.
	LPCTSTR	szFileName, szOutName;	//入出力ファイルの名前.
	LPCTSTR baseD2a_1_name = TEXT("baseD2a\\wrd_001.d2a");	//変えるテクスチャーが２つのときに使うd2aファイルの名前.
	LPCTSTR baseD2a_2_name = TEXT("baseD2a\\wrd_002.d2a");	//変えるテクスチャーが２つのときに使うd2aファイルの名前.
	LPCTSTR baseD2a_3_name = TEXT("baseD2a\\wrd_003.d2a");	//変えるテクスチャーが３つのときに使うd2aファイルの名前.
	LPCTSTR baseD2a_4_name = TEXT("baseD2a\\wrd_004.d2a");	//変えるテクスチャーが４つのときに使うd2aファイルの名前.
	LPCTSTR baseD2a_5_name = TEXT("baseD2a\\wrd_005.d2a");	//変えるテクスチャーが４つのときに使うd2aファイルの名前.
	LPCTSTR baseD2a_6_name = TEXT("baseD2a\\wrd_006.d2a");	//変えるテクスチャーが４つのときに使うd2aファイルの名前.
	int		ii, jj, iSourceLength;
	int		baseLength;	//d2aファイルの文字数.
	int		word_num = 0;							//変更歌詞テクスチャー用の数.
	int		texture_id = 0;							//変更テクスチャー用.
	int		max_record = 0;							//行の最大数.
	
	TCHAR	texture_name[TEXTURE_MAX+1][TEXTURE_NAME_SIZE] ={};

	/// 引数の取り出し.
	/**
	 * ターゲットファイル (GetString(0)としても同じ).
	 * swb ファイルでは指定しない、システムで付加される引数.
	 */
	szFileName = cParam.GetPath();
	
	/**
	 * 出力パスを取得. GetString(1)以降の最初に見つかったオプションでない文字列を得る.
	 * %0等の特殊記号は変換される. 引数が1つしかないなら GetFilePath(1) としても同じ.
	 * swb で引数として指定する文字列. 指定がなければGetPath()と同じ物が入る.
	 */
	szOutName  = cParam.GetOutPath();
	
//	if( cParam.IsParam( 2 ) )	iVal = cParam.GetInt( 2 );		///< 第2引数が存在するなら数値として取得.	
	
	/// 機能の初期化.
	Initialize();
	
	/// 元データ読み込み(関数内部でpMemに領域を確保している).
	iSourceLength = MEM_TextRead( &pMem, szFileName );					///< UNICODEの場合 UTF16に変換されて読まれます.
	MEM_TextRead( &pBase1, baseD2a_1_name );							///< UNICODEの場合 UTF16に変換されて読まれます.
	MEM_TextRead( &pBase2, baseD2a_2_name );							///< UNICODEの場合 UTF16に変換されて読まれます.
	MEM_TextRead( &pBase3, baseD2a_3_name );							///< UNICODEの場合 UTF16に変換されて読まれます.
	MEM_TextRead( &pBase4, baseD2a_4_name );							///< UNICODEの場合 UTF16に変換されて読まれます.
	MEM_TextRead( &pBase5, baseD2a_5_name );							///< UNICODEの場合 UTF16に変換されて読まれます.
	baseLength = MEM_TextRead( &pBase6, baseD2a_6_name );				///< 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()が実行されない.
	
	//一番大きいファイルのサイズ.
	mem_alloc( TCHAR, pOut,	baseLength );
	
	//行の最大数を取得.
	max_record = My_STRING_Count(pMem, TEXT("\n") );
	if (max_record < My_STRING_Count(pMem, TEXT("\r")) )
	{
		max_record = My_STRING_Count(pMem, TEXT("\r"));
	}

	/// 変換処理部分.
	ii = 0;
	jj = 0;
	while( ii < max_record )
	{		
		//while文の中で必要な初期化.
		word_num = 0;
		texture_id = 0;
		for(int id = 0; id < TEXTURE_MAX  ;id++){
			ZeroMemory(texture_name[id], TEXTURE_NAME_SIZE);
		}
	
		//最初のセルは(1,1)なので注意.
		for (int j = 0; j < TEXTURE_MAX ; j++)
		{
			int count = My_CSV_GetCell( pMem, iSourceLength, ii+1, j+1, texture_name[j], iSourceLength );
			if(count)
				word_num++;
		}
	

		//変えるテクスチャーの数からd2aの情報を
		switch(word_num){
		case 1:
			pTargetBase = pBase1;
			break;
		case 2:
			pTargetBase = pBase2;
			break;
		case 3:
			pTargetBase = pBase3;
			break;
		case 4:
			pTargetBase = pBase4;
			break;
		case 5:
			pTargetBase = pBase5;
			break;
		case 6:
			pTargetBase = pBase6;
			break;
		default:
			ii++;
			continue;
		}
		
		int pos_out = 0;	//ポインタを進める
		int pos_in = 0;	//ポインタを進める
		for( pos_out = 0; *(pTargetBase+pos_out) ;pos_out++){
			//コピー
			if(pos_out < STRING_len(pTargetBase)){
				*(pOut+pos_out) = *(pTargetBase+pos_in);
			}else{
				/** エラーメッセージの表示　処理はMessage_printfと同じ、Message_errorを使用すると自動終了しなくなります */
				Message_error( TEXT("size over") );
				return FALSE;						///< ファイルがない.
			}
					
			//検索.
			if( STRING_buffcmp(pTargetBase+pos_in, TEXT("wrd01_000.tga"), TEXT("\"") )){
				int kk = 0;
				for( kk = 0; kk < STRING_len(texture_name[texture_id]); kk++ )
				{
					*(pOut+pos_out+kk) = texture_name[texture_id][kk]; 
				}
				texture_id++;
				pos_out += kk-1;								///<代入した文字分pos_outを進める（更新されるので1減らしておく).
				pos_in  += STRING_len(TEXT("wrd01_000.tga")) - 1; ///<代入した文字分pos_inを進める（更新されるので減らしておく).
			}

			pos_in++;
		}
		//最後にヌル文字入力.
		*(pOut+pos_out-1) ='\0';

		///※コピーしているだけなのでここでは書き込み先のバッファオーバーはみていません.
		
		/// 変換された pOut を出力　　出力ファイル名はバッチで指定、特に指定されていなければ元と同じファイル名.
		{
			TCHAR	cDrive[_MAX_DRIVE], cDir[_MAX_DIR], cName[_MAX_FNAME], cExt[_MAX_EXT], szTemp[_MAX_PATH];

			FILE_split( szOutName, cDrive, cDir, cName, cExt );
#if	0
			FILE_merge( szTemp, cDrive, cDir, cName, cExt );	///<ここでは分解した物をそのまま連結、拡張子等を変えたい時はここで.
#else
			TCHAR line_wstr[_MAX_FNAME]={};

			STRING_printf(line_wstr, _MAX_FNAME, TEXT("_%03d") ,ii+1);
			STRING_cat(cName , line_wstr);
			FILE_merge( szTemp, cDrive, cDir, cName, TEXT(".d2a") );	///<拡張子を".txt"に変えるサンプルを".d2a"に変更
#endif
			/// Infoメッセージ出力(改行コードは\r\n).
			Message_printf( TEXT("file:%s"), szTemp );
			/// ファイル出力(同名が存在する時はバックアップが作成される).
			file_textwrite( szTemp, pOut );						///< UNICODEの場合 S-JISに戻して書き込み.
		}
	
		ii++;	//次の行へ.
		CHECK_LOOPOVER(32000);	///< 無限ループ安全処理	引数で指定した回数 ii が更新されないとbreakして処理停止.
	}

	
	/// メモリを開放.
	del_alloc( pMem );
	del_alloc( pOut );
	//baseメモリ解放
	del_alloc( pBase1 );
	del_alloc( pBase2 );
	del_alloc( pBase3 );
	del_alloc( pBase4 );
	del_alloc( pBase5 );
	del_alloc( pBase6 );
	return TRUE;
}


SONGDATACONVERT	*pC_SongDataConvert = NULL;

#endif	// SW_MODULE_SONGDATACONVERT
