/** pahooNormalizeText.hpp
 * テキスト正規化クラス：C++ヘッダ
 *
 * @copyright	(c)studio pahoo
 * @author		パパぱふぅ
 * @動作環境	MinGW C++ + Boost C++ Libraries + MeCab
 * @参考URL		https://www.pahoo.org/e-soul/webtech/cpp01-18-01.shtm
 * @補足
 *	1) MeCab使用時には MECAB を定義
 */
#ifndef PAHOONORMALIZETEXT_HPP
#define PAHOONORMALIZETEXT_HPP

#include <stdlib.h>
#include <vector>

// 文字コード変換
std::wstring __sjis_wstring(std::string src);
#define _SW(s)	__sjis_wstring(s)
std::string __wstring_sjis(std::wstring src);
#define _WS(s)	__wstring_sjis(s)
std::wstring __utf8_wstring(std::string src);
#define _UW(s)	__utf8_wstring(s)
std::string __wstring_utf8(std::wstring src);
#define _WU(s)	__wstring_utf8(s)
std::string sjis_utf8(std::string src);
#define _SU(s)	sjis_utf8(s)
std::string utf8_sjis(std::string src);
#define _US(s)	utf8_sjis(s)
std::wstring wconvString(std::wstring wsour, DWORD method);

// 正規化オプション
#define OPTION_SPC_TRIM1	't'		// 行頭・行末の空白文字を除く
#define OPTION_SPC_TRIM2	'T'		// 全角文字と隣り合う空白文字を除く
#define OPTION_NUM_HAN		'n'		// 数字を半角に統一
#define OPTION_NUM_ZEN		'N'		// 数字を全角に統一
#define OPTION_NUM_KAN		'K'		// 数字を漢字に統一
#define OPTION_NUM_KAN2		'k'		// 数字を漢字(単純)に統一
#define OPTION_ALP_HAN		'a'		// 英字を半角に統一
#define OPTION_ALP_ZEN		'A'		// 英字を全角に統一
#define OPTION_YAK_HAN		'y'		// 記号を半角に統一
#define OPTION_YAK_ZEN		'Y'		// 記号を全角に統一
#define OPTION_KANA_HAN		'h'		// カタカナを半角に統一
#define OPTION_KANA_ZEN		'H'		// カタカナを全角に統一
#define OPTION_SPEC_HAN		's'		// 特殊文字を半角に統一
#define OPTION_SPEC_ZEN		'S'		// 特殊文字を全角に統一
#define OPTION_NUM_SCALE	'F'		// 数字を位取り記法にする
#define OPTION_NUM_NOSCALE 	'f'		// 数字を位取り記法にしない
#define OPTION_CONTROL_DEL 	'c'		// 制御文字を削除する
#define OPTION_DBL_QUOTE 	'D'		// 二重引用符の開閉置換
#define OPTION_VARIABLE		'V'		// 表記ゆれを統一する

// 正規化オプションの初期値
#define OPTION_INIT			"anYSHF"

// 和暦・西暦年号変換オプション
#define OPTION_MODE_AD		'A'		// 西暦に統一
#define OPTION_MODE_ERA		'W'		// 和暦に統一
#define OPTION_MODE_ADERA  	'C'		// 西暦(和暦)
#define OPTION_SCOPE_1		'1'		// 奈良時代以降
#define OPTION_SCOPE_2		'2'		// 明治以降
#define OPTION_SCOPE_0		'0'		// 変換しない
#define OPTION_AD_HAN		'h'		// 数字変換(西暦)：半角数字
#define OPTION_AD_ZEN		'z'		//　　同上　　　：全角数字
#define OPTION_AD_KAN1		'k'		//　　同上　　　：漢数字(単純)
#define OPTION_AD_KAN2  	'l'		//　　同上　　　：漢数字
#define OPTION_ERA_HAN		'H'		// 数字変換(和暦)：半角数字
#define OPTION_ERA_ZEN		'Z'		//　　同上　　　：全角数字
#define OPTION_ERA_KAN1		'K'		//　　同上　　　：漢数字(単純)
#define OPTION_ERA_KAN2		'L'		//　　同上　　　：漢数字

// 文字列置換定義ファイル
#define FRONT_REPLACE_CSV	".\\etc\\frontrep.csv"

// 表記ゆれ統一辞書ファイル
#define VARIABILITY_REPLACE_CSV	".\\etc\\vardic.csv"

// 年号変換オプションの初期値
#define CONVOPT_INIT		"C1hH"

// クラス定義
class pahooNormalizeText {
public:
// コンストラクタ
pahooNormalizeText();
~pahooNormalizeText();

std::wstring errmsg = L"";		// エラーメッセージ

bool isError(void);
std::wstring getError(void);
void resetError(void);
void setError(std::wstring msg);

std::wstring frontend_replace(std::wstring sour);
std::wstring num2kanji(std::wstring instr);
std::wstring num2scale(std::wstring instr);
std::wstring num2kan(std::wstring wsour);
std::wstring num2kanSimple(std::wstring wsour);
std::wstring bignum2scale(std::wstring wsour);
std::wstring kan2num(std::wstring kanji, int mode);
std::wstring convString(std::wstring wsour, DWORD flags);
std::wstring toHankaku(std::wstring wsour, bool trim, bool variable);
std::wstring normalizeText(std::wstring wsour, const char* option, bool trim);

// 表記ゆれ統一辞書
std::vector<std::pair<std::wstring, std::wstring>> VariableDict;

std::vector<std::pair<std::wstring, std::wstring>> loadVariableDictionary(const std::string& filename);
std::wstring variable2standard(std::wstring word);

// 西暦⇔元号変換テーブル
struct _tableEra {
	long start;				// 開始年月日
	std::wstring era;		// 元号
};
std::vector<_tableEra> TableEra;

// 西暦⇔元号変換範囲
long convStart = 11110101;			// 開始年月日（西暦）
long convEnd   = 99999999;			// 終了年月日（西暦）
#define START_SCOPE1	06450717	// 大化元年
#define START_SCOPE2	18730101	// 明治6年1月1日
#define END_SCOPE		99999999
#define ESCYEAR			L"^\\\\"	// エスケープ文字（この後の年号は変換しない）

void readTableEra(const char* fname);
void setScope(long start, long end);
bool isConvEra(long yyyymmdd);
bool isEra(std::wstring wstr);
std::wstring convNengo(std::wstring wsour, const char* option);

private:
#ifdef MECAB
MeCab::Tagger *tagger = MeCab::createTagger("--dicdir=etc --userdic=etc/user_wiki.dic --node-format=%M\\t%f[0],%f[1],%f[2],%f[3],%f[4],%f[5],%f[6],%f[7],%f[8]\\n --unk-format=%M\\t%f[0],%f[1],%f[2],%f[3],%f[4],%f[5]\\n");
#endif
std::wstring kanword2num(std::wstring kanji);
std::wstring hanfloat(std::wstring wsour);
std::wstring han2zen(std::wstring wsour, bool (*func)(wchar_t wch));

std::wstring ad2era(std::wstring prefix, int year, int month, int day, const char* option);
std::wstring era2ad(std::wstring prefix, int year, int month, int day, const char* option);
std::wstring seireki2wareki(std::wsmatch mt, const char* option);
std::wstring wareki2seireki(std::wsmatch mt, const char* option);
std::wstring seireki2mix(std::wsmatch mt, const char* option);
std::wstring wareki(std::wstring wsour, const char* option, bool flag);
std::wstring seireki(std::wstring wsour, const char* option, bool flag);
std::wstring mixture(std::wstring wsour, const char* option, bool flag);
std::wstring monthday(std::wstring wsour, const char* option);

};

#endif
