#ifndef __MyuCharCnv_H__
#define __MyuCharCnv_H__

#include "MyuDynamicDll.h"

//int CALLBACK CLASS_DECLSPEC SetNkfOption(LPCSTR optStr);
//void CALLBACK CLASS_DECLSPEC NkfConvert(LPSTR outStr, LPCSTR inStr);
//BOOL WINAPI CLASS_DECLSPEC NkfConvertSafe(LPSTR outStr,DWORD nOutBufferLength /*in Bytes*/,LPDWORD lpBytesReturned /*in Bytes*/, LPCSTR inStr,DWORD nInBufferLength /*in Bytes*/);
//void CALLBACK NkfFileConvert1(LPCSTR fName);
//void CALLBACK NkfFileConvert2(LPCSTR fInName,LPCSTR fOutName);

#define DLLCHK(R)	{ \
	if ( m_bDllLoaded != TRUE ) \
		if ( Load() != TRUE ) \
			return R; }
#define DLLCHK_NR()	{ \
	if ( m_bDllLoaded != TRUE ) \
		if ( Load() != TRUE ) \
			return; }

#define DEFAULT_RESULT_ENCODING		"Shift_JIS"

//	クラス宣言
class CMyuCharCnv : public CMyuDynamicDll
{
private:
	typedef int (CALLBACK* FUNC_NKF_SET_OPTION)(LPCSTR);
	typedef void (CALLBACK* FUNC_NKF_CONVERT)(LPSTR,LPCSTR);
	typedef BOOL (CALLBACK* FUNC_NKF_CONVERT_SAFE)(LPSTR,DWORD,LPDWORD,LPCSTR,DWORD);
	typedef void (CALLBACK* FUNC_NKF_FILE_CONVERT1)(LPCSTR);
	typedef void (CALLBACK* FUNC_NKF_FILE_CONVERT2)(LPCSTR,LPCSTR);

	FUNC_NKF_SET_OPTION		m_funcSetOption;
	FUNC_NKF_CONVERT		m_funcConvert;
	FUNC_NKF_CONVERT_SAFE	m_funcConvertSafe;
	FUNC_NKF_FILE_CONVERT1	m_funcFileConvert1;
	FUNC_NKF_FILE_CONVERT2	m_funcFileConvert2;

	BOOL m_bDllLoaded;

	//char m_szConvertStaticBuffer[1024*
	char* m_szpConvertStaticBuffer;
	int m_szpConvertStaticBufferSize;

	void BufferRelease(){
		SAFE_DELETE_ARY(m_szpConvertStaticBuffer);
		m_szpConvertStaticBufferSize = -1;
	}
	void BufferAlloc( int size ){
		//	今より大きい時のみあろっく
		if ( size > m_szpConvertStaticBufferSize )
		{
			//SAFE_DELETE_ARY(m_szpConvertStaticBuffer);
			BufferRelease();
			m_szpConvertStaticBuffer = new char[size];
			m_szpConvertStaticBufferSize = size;
		}
		ZeroMemory( m_szpConvertStaticBuffer, m_szpConvertStaticBufferSize );
	}

public:
	//	コンストラクタ・デストラクタ
	CMyuCharCnv();
	virtual ~CMyuCharCnv();

	//	DLLのロード（明示的に呼び出すのであれば）
	//BOOL Load();
	bool Load();
	//	Release()はCMyuDynamicDll()のが呼ばれる
	//	→ m_bDllLoaded が戻らない等あるけどとりあえずいいや…（何

	//	SetNkfOption
	bool SetNkfOption( LPCSTR optStr ){
		DLLCHK(false);
		if ( m_funcSetOption(optStr) != 0 )
			return false;
		else
			return true;
	}
	bool SetResultEncoding( LPCSTR szEncoding ){
		DLLCHK(false);
		const char* szNkfOptStr = "";

		if ( STRICMP(szEncoding,"Shift_JIS") == 0 )
			szNkfOptStr = "-s";

		return SetNkfOption(szNkfOptStr);
	}

	//	EzConvert
	//void EzCnv( LPCSTR szInputStr, LPSTR szOutputStr ){ EzConvert(szInputStr,szOutputStr); }
	//void Convert( LPCSTR szInputStr, LPSTR szOutputStr ){
	bool Convert( LPCSTR szInputStr, LPSTR szOutputStr ){
		DLLCHK(false);
		//m_funcConvert(szOutputStr,szInputStr);
		if ( Convert( szInputStr, szOutputStr, 0x7fffffff ) < 0 )
			return false;
		else
			return true;
	}

	//	Convert
	const char* Conv( LPCSTR szInputStr, const char* szResultEncoding=DEFAULT_RESULT_ENCODING ){
		return Convert(szInputStr,szResultEncoding); }
	const char* Convert( LPCSTR szInputStr, const char* szResultEncoding=DEFAULT_RESULT_ENCODING )
	{
		//DLLCHK(FALSE);
		DLLCHK(NULL);

		//SetResultEncoding(szResultEncoding);

		DWORD dwBufSize = GetConvertNeedSize(szInputStr);

		/*SAFE_DELETE_ARY(m_szpConvertStaticBuffer);
		m_szpConvertStaticBuffer = new char[dwBufSize];
		ZeroMemory( m_szpConvertStaticBuffer, dwBufSize );*/
		BufferAlloc(dwBufSize);

		if ( Convert( szInputStr, m_szpConvertStaticBuffer ) == false )
			return NULL;

		return m_szpConvertStaticBuffer;
/*
		//SetNkfOption
		DWORD dwReturned=0;
		if ( m_funcConvertSafe( szOutputStr, dwOutputStrBufSize, &dwReturned, szInputStr, dwInStrLength ) != TRUE )
			return 0;
		else
			return dwReturned;*/
	}

	//DWORD Cnv( LPCSTR szInputStr, DWORD dwInStrLength, LPSTR szOutputStr, DWORD dwOutputStrBufSize, const char* szResultEncoding=DEFAULT_RESULT_ENCODING ){
	int Cnv( LPCSTR szInputStr, DWORD dwInStrLength, LPSTR szOutputStr, DWORD dwOutputStrBufSize, const char* szResultEncoding=DEFAULT_RESULT_ENCODING ){
		return Convert(szInputStr,dwInStrLength,szOutputStr,dwOutputStrBufSize,szResultEncoding); }
	//DWORD Conv( LPCSTR szInputStr, DWORD dwInStrLength, LPSTR szOutputStr, DWORD dwOutputStrBufSize, const char* szResultEncoding=DEFAULT_RESULT_ENCODING ){
	int Conv( LPCSTR szInputStr, DWORD dwInStrLength, LPSTR szOutputStr, DWORD dwOutputStrBufSize, const char* szResultEncoding=DEFAULT_RESULT_ENCODING ){
		return Convert(szInputStr,dwInStrLength,szOutputStr,dwOutputStrBufSize,szResultEncoding); }
	//DWORD Convert( LPCSTR szInputStr, DWORD dwInStrLength, LPSTR szOutputStr, DWORD dwOutputStrBufSize, const char* szResultEncoding=DEFAULT_RESULT_ENCODING )
	int Convert( LPCSTR szInputStr, DWORD dwInStrLength, LPSTR szOutputStr, DWORD dwOutputStrBufSize, const char* szResultEncoding=DEFAULT_RESULT_ENCODING )
	{
		//DLLCHK(FALSE);
		DLLCHK(0);
		DWORD dwReturned=0;
		if ( m_funcConvertSafe( szOutputStr, dwOutputStrBufSize, &dwReturned, szInputStr, dwInStrLength ) != TRUE )
			//return -1 * (int)(dwReturned);
			return -1 * (int)(dwReturned);
		else
			return dwReturned;
	}
	int Convert( LPCSTR szInputStr, LPSTR szOutputStr, DWORD dwOutputStrBufSize, const char* szResultEncoding=DEFAULT_RESULT_ENCODING ){
		return Convert(szInputStr,strlen(szInputStr),szOutputStr,dwOutputStrBufSize,szResultEncoding); }

	//	必要なバッファサイズを取得
	DWORD GetConvertNeedSize( LPCSTR szInputStr, const char* szResultEncoding=DEFAULT_RESULT_ENCODING )
	{
		DLLCHK(0);
		char work[16];
		DWORD dwReturned;
		if ( m_funcConvertSafe( work, 0, &dwReturned, szInputStr, strlen(szInputStr) ) == FALSE )
			return 0;
		else
			return dwReturned + 1;
	}
	
	//	ワイド文字版
	DWORD GetConvertNeedSizeW( LPCSTR szInputStr, const char* szResultEncoding=DEFAULT_RESULT_ENCODING )
	{
		DLLCHK(0);
		char work[16];
		DWORD dwReturned;
		//if ( m_funcConvertSafe( work, 0, &dwReturned, szInputStr, strlen(szInputStr) ) == FALSE )
		if ( m_funcConvertSafe( work, 0, &dwReturned, szInputStr, wcslen((LPCWSTR)szInputStr) ) == FALSE )
			return 0;
		else
			return dwReturned + 2;
	}

	/*
	//	SafeConvert
	BOOL SafeConvert( LPSTR outStr, DWORD nOutBufferLength, LPDWORD lpBytesReturned, LPCSTR inStr, DWORD nInBufferLength )
	{
		DLLCHK(FALSE);
		return m_funcConvertSafe(outStr,nOutBufferLength,lpBytesReturned,inStr,nInBufferLength);
	}
	*/

	//	ConvertFile
	void ConvertFile( LPCSTR szIoFileName ){
		DLLCHK_NR();
		m_funcFileConvert1(szIoFileName);
	}

	//	ConvertFile (オーバーロード)
	void ConvertFile( LPCSTR szInputFile, LPCSTR szOutputFile ){
		DLLCHK_NR();
		m_funcFileConvert2(szInputFile,szOutputFile);
	}
};
typedef CMyuCharCnv CMyuCharConv;

//extern CMyuCharCnv g_defaultMyuCharCnv;

namespace mwl{

	inline CMyuCharCnv& GetDefaultMyuCharConvInstance()
	{
		extern CMyuCharCnv* g_pDefaultMyuCharCnv;
		if ( g_pDefaultMyuCharCnv == NULL )
			g_pDefaultMyuCharCnv = new CMyuCharCnv();
		return *g_pDefaultMyuCharCnv;
	}
	inline CMyuCharCnv& GetDefaultMyuCharCnvInstance(){ return GetDefaultMyuCharConvInstance(); }
	inline CMyuCharCnv& GetDefaultMyuCharCnv(){ return GetDefaultMyuCharConvInstance(); }
	inline CMyuCharCnv& GetDefaultMyuCharConv(){ return GetDefaultMyuCharConvInstance(); }
	inline CMyuCharCnv* GetDefaultMyuCharCnvPtr(){ return &(GetDefaultMyuCharConvInstance()); }
	inline CMyuCharCnv* GetDefaultMyuCharConvPtr(){ return &(GetDefaultMyuCharConvInstance()); }
}

#endif//__MyuCharCnv_H__
