#include <wchar.h>
#include <stdlib.h>
#include <vector>
#include <widec.h>
#include "spf.h"

using namespace std;

#define UPPER_CHAR L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define LOWER_CHAR L"abcdefghijklmnopqrstuvwxyz"

static int Search( const wchar_t *pStr, wchar_t c )
{
	const wchar_t *p = pStr;
	while ( (*p) ) {
		if ( (*p) == c ) return p - pStr;
		++p;
	}
	return -1;
}

// 一行だけ変換する
static void TranseLine( CSyuhituPlugin spf, const wchar_t *pSrc, const wchar_t *pDest, bool EnableRev, unsigned long LP, unsigned long SCP, unsigned long ECP )
{
	wstring str;
	wstring str2;
	unsigned long i;
	int idx;
	bool flg = false;

	if ( SCP == ECP ) return ;

	// 指定された範囲の文字列を取得
	str = spf.GetString( LP, SCP, LP, ECP );

	for ( i = SCP; i < ECP; i++ ) {
		// 順方向の検索
		idx = Search( pSrc, str[ i - SCP ] );
		if ( idx >= 0 ) {
			str2 += pDest[ idx ];
			flg = true;
		}
		else {
			if ( EnableRev ) {
				// 逆方向の検索
				idx = Search( pDest, str[ i - SCP ] );
				if ( idx >= 0 ) {
					str2 += pSrc[ idx ];
					flg = true;
				}
				else
					str2 += str[ i - SCP ];
			}
			else
				str2 += str[ i - SCP ];
		}
	}

	if ( flg ) {
		spf.Replace( LP, SCP, LP, ECP, str2.c_str() );
	}
}

static void Transe( CSyuhituPlugin spf, const wchar_t *pSrc, const wchar_t *pDest, bool EnableRev )
{
	unsigned long SLP, SCP, ELP, ECP;
	unsigned long CLP;
	unsigned long len;

	// 選択範囲を取得
	spf.GetSelectionRange( &SLP, &SCP, &ELP, &ECP );

	// 範囲選択されていない
	if ( SLP == ELP && SCP == ECP ) return ;

	if ( SLP == ELP ) {
		// 選択された範囲を変換
		TranseLine( spf, pSrc, pDest, EnableRev, SLP, SCP, ECP );
	}
	else {
		unsigned long LineCnt = spf.GetLineCount();

		// 最初の行を変換
		len = spf.GetCharCount( SLP );
		if ( SLP != LineCnt - 1 ) len--;
		TranseLine( spf, pSrc, pDest, EnableRev, SLP, SCP, len );

		// 中間の行を変換
		for ( CLP = SLP + 1; CLP < ELP; CLP++ ) {
			len = spf.GetCharCount( CLP );
			if ( CLP != LineCnt - 1 ) len--;
			TranseLine( spf, pSrc, pDest, EnableRev, CLP, 0, len );
		}

		// 最後の行を変換
		TranseLine( spf, pSrc, pDest, EnableRev, ELP, 0, ECP );
	}
}

extern "C" void ToLowerCase( PFT_GetAPIFunction GetAPIFunction )
{
	CSyuhituPlugin spf( GetAPIFunction );

	try {
		Transe( spf, UPPER_CHAR, LOWER_CHAR, false );
	}
	catch ( CSP_Err e ) {
		printf( "ERROR\n" );
	};
}

extern "C" void ToUpperCase( PFT_GetAPIFunction GetAPIFunction )
{
	CSyuhituPlugin spf( GetAPIFunction );

	try {
		Transe( spf, LOWER_CHAR, UPPER_CHAR, false );
	}
	catch ( CSP_Err e ) {
		printf( "ERROR\n" );
	};
}

extern "C" void ReverseCase( PFT_GetAPIFunction GetAPIFunction )
{
	CSyuhituPlugin spf( GetAPIFunction );

	try {
		Transe( spf, UPPER_CHAR, LOWER_CHAR, true );
	}
	catch ( CSP_Err e ) {
		printf( "ERROR\n" );
	};
}

