//==============================================================================================================================
//	変換ルーチンベースプログラム
//==============================================================================================================================

#define	MAX_LIST		32768
#define	MAX_STRING		(4*1024)

typedef list<xstring> ListSort;

//		
class LIST_SORT
{
	BOOL		m_bInitialized;
	BOOL		m_bImplemented;
	
public:
	void		Initialize();
	int			Func( LPCTSTR _sParamString );
	void		Quit( BOOL _bExit );
	
	LIST_SORT();
	~LIST_SORT();
	
private:
	ListSort	lList;
	char		list[ MAX_LIST ][ MAX_STRING ];
//	int			entry;
	
};


LIST_SORT::LIST_SORT()
	: m_bInitialized( FALSE )
	, m_bImplemented( FALSE )
//	, entry( 0 )
{
	
	lList.clear();
	
}
LIST_SORT::~LIST_SORT()
{
	
}


void	LIST_SORT::Initialize()
{
	if( m_bInitialized == TRUE )	return;
	m_bInitialized = TRUE;	//	初期済みフラグ
	
}

//		
void	LIST_SORT::Quit( BOOL _bExit )
{
	if( m_bImplemented == FALSE)	return;
	m_bImplemented = FALSE;
	m_bInitialized = FALSE;
	//	終了処理は変換処理が実行された場合のみ行う
	
}


//		
int		LIST_SORT::Func( LPCTSTR _sParamString )
{
	CSwbParam	cParam( _sParamString );							///< パラメータ処理.
	
	xstring				sPath;
	xstring				sWork;
	int					iType = 0;
	BOOL				bRepeatDel = FALSE;
	TCHAR				*pMem = NULL;
	int					i,j,iSIdx,iLen;
	xstring				sSeachStr;
	xstring				sGrepStr;
	ListSort::iterator	it;
	
	
	sPath		= cParam.GetPath();		///< ターゲットファイル (GetFilePath(0)としても同じ).
	
	iSIdx		= cParam.SearchOption( 'o' );
	if( iSIdx >= 0 )
	{
		
		if( cParam.CheckOption( iSIdx, 'l', TRUE ) )	//大文字小文字を区別しない
		{	///レングスモード.
			iType++;
		}
		if( cParam.CheckOption( iSIdx, 'r', TRUE ) )	//大文字小文字を区別しない
		{	///リバース.
			iType += 2;
		}
		
		if( cParam.CheckOption( iSIdx, 'p', TRUE ) )
		{///同じ物を削除.
			bRepeatDel = TRUE;
		}
	}
	
	LPCTSTR	pPtr = NULL;
	pPtr = cParam.GetStringOption( 's' );
	if(pPtr)	sSeachStr = pPtr;
	pPtr = cParam.GetStringOption( 'c' );
	if(pPtr)	sGrepStr = pPtr;
	
	Initialize();
/*	
	iLen = FILE_GetFileSize( sPath.c_str() );
	mem_alloc(char,pMem,iLen*2);		//	元のファイルが同じ長さになる場合 \n改行を考慮して2倍とる
	FILE_TargetRead( sPath.c_str(), pMem );
*/		
	iLen = MEM_TextRead2( &pMem, sPath.c_str(), 2 );	///< 元のファイルが同じ長さになる場合 \n改行を考慮して2倍とる
	if(iLen == 0)	return FALSE;
	m_bImplemented = TRUE;	//	実行済みフラグ
	
	
//		entry = 0;
	
	//★★改行コードを調べて元と同じにするように
	
	if(iType == 0){
		Message_win( TEXT("文字コードで昇順ソートします.") );
	}else if(iType == 1){
		Message_win( TEXT("長さで昇順ソートします.") );
	}else if(iType == 2){
		Message_win( TEXT("文字コードで降順ソートします.") );
	}else if(iType == 3){
		Message_win( TEXT("長さで降順ソートします.") );
	}
	
	if( bRepeatDel )
		Message_win( TEXT("同じ項目は除外されます.") );
	
	if( !sSeachStr.empty() )
		Message_printf( TEXT(" \"%s\" 以降の文字を対象にソートします."), sSeachStr.c_str() );
	if( !sGrepStr.empty() )
		Message_printf( TEXT("行頭から \"%s\" までは削除されます."), sGrepStr.c_str() );
	
	
	lList.clear();
	i = 0;
	while(i < iLen){
		
		sWork.clear();
		while( (*(pMem+i) != '\r' && *(pMem+i) != '\n') && i < iLen ){
			sWork.append( 1, *(pMem+i++) );
		}
		
		if( !sGrepStr.empty() )
		{
			//	Grep検索結果のパス、行番号部分を除外する
			j = sWork.find( sGrepStr );
			if( j != xstring::npos )
			{
				xstring	cTmp;
				cTmp = sWork;
				sWork = cTmp.c_str() + j + sGrepStr.size();
			}
		}
		
		
		while((*(pMem+i) == '\r' || *(pMem+i) == '\n'/* || *(pMem+i) == '\t' || *(pMem+i) == ' '*/) && i < iLen)	i++;
		
		if( bRepeatDel )
		{
			//	同じ物は登録しない
			for( it = lList.begin() ; it != lList.end() ; it++ )
			{
				if( it->compare( sWork ) == 0)	break;
			}
			if( it != lList.end() )	continue;
		}
		
		
		
		for( it = lList.begin() ; it != lList.end() ; it++ )
		{
			xstring	ss,ds;
			int		ii;
			
			
			if( sSeachStr.empty() )
			{
				ss = *it;
				ds = sWork;
			}else{
				ii = it->find( sSeachStr );
				if( ii == xstring::npos )
				{
					ss = *it;
				}else{
					ss = it->c_str() + ii;
				}
				
				ii = sWork.find( sSeachStr );
				if( ii == xstring::npos )
				{
					ds = sWork;
				}else{
					ds = sWork.c_str() + ii;
				}
			}
			
			
			//ソート(タイプ別)
			if(iType == 0)
			{	///	文字コードソート(昇順).
				if( ss.compare( ds ) > 0 )	//昇順
				{
					lList.insert( it, sWork );
					break;
				}
			}
			else if(iType == 1)
			{	///	レングスソート(昇順).
				
				if( ss.size() > ds.size() )
				{
					lList.insert( it, sWork );
					break;
				}
				
			}
			else if(iType == 3)
			{	///	文字コードソート(降順).
				if( ss.compare( ds ) < 0 )	//降順
				{
					lList.insert( it, sWork );
					break;
				}
			}
			else if(iType == 4)
			{	///	レングスソート(降順).
				
				if( ss.size() < ds.size() )
				{
					lList.insert( it, sWork );
					break;
				}
				
			}
			
		}
		if( it == lList.end() )
		{
			lList.push_back( sWork );
		}
		
	//	if( (lList.size() % 1000) == 0 )
	//		Message_printf( TEXT(" %d lines sorting."), lList.size() );
		
		
	}
	
	
	//テキスト変換
	*pMem = 0;
	
	for( it = lList.begin() ; it != lList.end() ; it++ )
	{
		STRING_cat( pMem, it->c_str() );
		STRING_cat( pMem, TEXT("\r\n") );
	}
	iLen = STRING_len(pMem);
	
	
	file_textwrite( sPath.c_str() ,pMem );		//	出力パスが指定されていない時、元のパス
	
	mem_del(pMem);
	
	return TRUE;
}


LIST_SORT	*pC_listsort = NULL;

