#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>

#include "config.h"
#include "encode.h"
#include "kolelog.h"

#define QJBJ_FILE_NAME		"QjBj.txt"
#define PUNCT_FILE_NAME		"Punct.txt"

#define MAX_LINE_LEN 		256
#define FULLWIDE_CHAR_NUM 	94
#define PUNCT_CHAR_NUM 		18

typedef struct _FullWideChar_Struct {
	char bInit;
	char *QjStr[FULLWIDE_CHAR_NUM];
}  FullWideChar_Struct;

typedef struct _PunctChar_Struct {
	char bInit;
	char *PunctStr[PUNCT_CHAR_NUM];
}  PunctChar_Struct;

char *FullWideCharListByLang_CN[FULLWIDE_CHAR_NUM] = {
	"！",
	"＂",
	"＃",
	"＄",
	"％",
	"＆",
	"＇",
	"（",
	"）",
	"＊",
	"＋",
	"，",
	"－",
	"．",
	"／",
	"０",
	"１",
	"２",
	"３",
	"４",
	"５",
	"６",
	"７",
	"８",
	"９",
	"：",
	"；",
	"＜",
	"＝",
	"＞",
	"？",
	"＠",
	"Ａ",
	"Ｂ",
	"Ｃ",
	"Ｄ",
	"Ｅ",
	"Ｆ",
	"Ｇ",
	"Ｈ",
	"Ｉ",
	"Ｊ",
	"Ｋ",
	"Ｌ",
	"Ｍ",
	"Ｎ",
	"Ｏ",
	"Ｐ",
	"Ｑ",
	"Ｒ",
	"Ｓ",
	"Ｔ",
	"Ｕ",
	"Ｖ",
	"Ｗ",
	"Ｘ",
	"Ｙ",
	"Ｚ",
	"［",
	"＼",
	"］",
	"＾",
	"＿",
	"｀",
	"ａ",
	"ｂ",
	"ｃ",
	"ｄ",
	"ｅ",
	"ｆ",
	"ｇ",
	"ｈ",
	"ｉ",
	"ｊ",
	"ｋ",
	"ｌ",
	"ｍ",
	"ｎ",
	"ｏ",
	"ｐ",
	"ｑ",
	"ｒ",
	"ｓ",
	"ｔ",
	"ｕ",
	"ｖ",
	"ｗ",
	"ｘ",
	"ｙ",
	"ｚ",
	"｛",
	"｜",
	"｝",
	"￣",
};

char *FullWideCharListByLang_TW[FULLWIDE_CHAR_NUM] = {
	"！",
	"〃",
	"＃",
	"＄",
	"％",
	"＆",
	"′",
	"（",
	"）",
	"﹡",
	"＋",
	"，",
	"－",
	"．",
	"／",
	"０",
	"１",
	"２",
	"３",
	"４",
	"５",
	"６",
	"７",
	"８",
	"９",
	"：",
	"；",
	"〈",
	"＝",
	"〉",
	"？",
	"＠",
	"Ａ",
	"Ｂ",
	"Ｃ",
	"Ｄ",
	"Ｅ",
	"Ｆ",
	"Ｇ",
	"Ｈ",
	"Ｉ",
	"Ｊ",
	"Ｋ",
	"Ｌ",
	"Ｍ",
	"Ｎ",
	"Ｏ",
	"Ｐ",
	"Ｑ",
	"Ｒ",
	"Ｓ",
	"Ｔ",
	"Ｕ",
	"Ｖ",
	"Ｗ",
	"Ｘ",
	"Ｙ",
	"Ｚ",
	"【",
	"＼",
	"】",
	"︿",
	"＿",
	"‵",
	"ａ",
	"ｂ",
	"ｃ",
	"ｄ",
	"ｅ",
	"ｆ",
	"ｇ",
	"ｈ",
	"ｉ",
	"ｊ",
	"ｋ",
	"ｌ",
	"ｍ",
	"ｎ",
	"ｏ",
	"ｐ",
	"ｑ",
	"ｒ",
	"ｓ",
	"ｔ",
	"ｕ",
	"ｖ",
	"ｗ",
	"ｘ",
	"ｙ",
	"ｚ",
	"｛",
	"｜",
	"｝",
	"∼",
};

char PunctChars[PUNCT_CHAR_NUM] = {
	'!',     '"',     '$',     '&',     '\'',
	'(',     ')',     ',',     '.',
	':',     ';',     '<',     '>',     '?',
	'@',     '\\',    '^',     '_'   
};

char *PunctCharListByLang_CN[PUNCT_CHAR_NUM] = {
	"！",
	"“",
	"￥",
	"─",
	"‘",
	"（",
	"）",
	"，",
	"。",
	"：",
	"；",
	"》",
	"《",
	"？",
	"＠",
	"、",
	"…",
	"＿＿",
};
	
char *PunctCharListByLang_TW[PUNCT_CHAR_NUM] = {
	"！",
	"“",
	"NT$",
	"─",
	"‘",
	"（",
	"）",
	"，",
	"。",
	"：",
	"；",
	"《",
	"》",
	"？",
	"＠",
	"＼",
	"…",
	"＿＿",
};
	
FullWideChar_Struct 	FullWideCharListByLang[LANGS_NUM]; 
PunctChar_Struct 	PunctCharListByLang[LANGS_NUM]; 

void qjbjpunct_init()
{
	int lang_id, char_id;

	for (lang_id=0; lang_id<LANGS_NUM; lang_id++) {
		FullWideCharListByLang[lang_id].bInit = 0;
		for (char_id=0; char_id<FULLWIDE_CHAR_NUM; char_id++) {
			FullWideCharListByLang[lang_id].QjStr[char_id] = NULL;
		}

		PunctCharListByLang[lang_id].bInit = 0;
		for (char_id=0; char_id<PUNCT_CHAR_NUM; char_id++) {
			PunctCharListByLang[lang_id].PunctStr[char_id] = NULL;
		}
	}
}

void qjbjpunct_done()
{
	int lang_id, char_id;
	char *str;

	for (lang_id=0; lang_id<LANGS_NUM; lang_id++) {
		FullWideCharListByLang[lang_id].bInit = 0;
		for (char_id=0; char_id<FULLWIDE_CHAR_NUM; char_id++) {
			str = (char *)FullWideCharListByLang[lang_id].QjStr[char_id];
			if (str != NULL) free(str);
		}

		PunctCharListByLang[lang_id].bInit = 0;
		for (char_id=0; char_id<PUNCT_CHAR_NUM; char_id++) {
			str = (char *)PunctCharListByLang[lang_id].PunctStr[char_id];
			if (str != NULL) free(str);
		}
	}
}

void getline(FILE *fd, char *line)
{
	int line_ptr;
	char line_buf[256], *ptr;

	line_ptr = 0;
	line[0] = '\0';

	/* get line with no space */
 	while(fgets(line_buf, 255, fd) != NULL) {
		ptr = line_buf;

		/* skip space keys */
		while(*ptr && isspace(*ptr)) ptr++;

		/* if is space line, get new line */
		if (*ptr == '\n' || *ptr == '\0')
			continue;

		while(*ptr != '\n' && *ptr != '\0' && line_ptr < MAX_LINE_LEN) 
			line[line_ptr++] = *ptr++;

		while (isspace(line[line_ptr-1])) line_ptr--;
		line[line_ptr] = '\0';

		break;
	}
}

int read_qjbj_config_file(int lang_id)
{
	char	file_name[256], line[MAX_LINE_LEN];
	char 	ch, *kptr, *ptr, *lang_name;
	int 	ch_pos, len;
	FILE 	*fd;

	FullWideCharListByLang[lang_id].bInit = 1;

	lang_name = (char *)get_langname_from_langid(lang_id);
	KOLE_LOG (LOGDEST_STDOUT, "lang_name:%s\n", lang_name);
	sprintf(file_name, "%s/%s", LE_IME_MODULES_DIR, QJBJ_FILE_NAME);
	KOLE_LOG (LOGDEST_STDOUT, "file_name:%s\n", file_name);

	fd = fopen(file_name, "r");
	if (!fd) {
		KOLE_LOG (LOGDEST_STDOUT, "Can not open the file:%s\n", file_name);
		return(-1);
	}

	do {
		getline(fd, line);

		if (line[0] == '\0') break;
		if (line[0] == '#') continue;
		KOLE_LOG (LOGDEST_STDOUT, "line:%s#\n", line);

		kptr = ptr = line;
		while(*ptr && !isspace(*ptr))  ptr++;
		if (!(*ptr)) continue;

		*ptr++ = '\0';

		len = strlen(kptr);
		if (len > 2) continue;

		if (len == 2) {
			if (*kptr == '\\')
				ch = *(kptr + 1);
			else
				continue;
		} else if (len == 1) {
			ch = *kptr;
		}

		/* skip space keys */
		while(*ptr && isspace(*ptr)) ptr++;
		if (!(*ptr)) continue;

		ch_pos = ch - 0x21;
		FullWideCharListByLang[lang_id].QjStr[ch_pos] = (char *)strdup(ptr);

	} while (1);

	fclose(fd);
	return(0);
}

int read_punct_config_file(int lang_id)
{
	char	file_name[256], line[MAX_LINE_LEN];
	char 	ch, *kptr, *ptr, *lang_name;
	int 	i, ch_pos, len;
	FILE 	*fd;

	PunctCharListByLang[lang_id].bInit = 1;

	lang_name = (char *)get_langname_from_langid(lang_id);
	sprintf(file_name, "%s/%s", LE_IME_MODULES_DIR, PUNCT_FILE_NAME);
	KOLE_LOG (LOGDEST_STDOUT, "file_name:%s\n", file_name);

	fd = fopen(file_name, "r");
	if (!fd) {
		KOLE_LOG (LOGDEST_STDOUT, "Can not open the file:%s\n", file_name);
		return(-1);
	}

	do {
		getline(fd, line);

		if (line[0] == '\0') break;
		if (line[0] == '#') continue;

		kptr = ptr = line;
		while(*ptr && !isspace(*ptr))  ptr++;
		if (!(*ptr)) continue;

		*ptr++ = '\0';

		len = strlen(kptr);
		if (len > 2) continue;

		if (len == 2) {
			if (*kptr == '\\')
				ch = *(kptr + 1);
			else
				continue;
		} else if (len == 1) {
			ch = *kptr;
		}

		/* skip space keys */
		while(*ptr && isspace(*ptr)) ptr++;
		if (!(*ptr)) continue;

		ch_pos = -1;
		for (i=0; i<PUNCT_CHAR_NUM; i++) {
			if (ch == PunctChars[i]) {
				ch_pos = i;
				break;
			}
		}
		if (ch_pos == -1) continue;
		PunctCharListByLang[lang_id].PunctStr[ch_pos] = (char *)strdup(ptr);
	} while (1);

	fclose(fd);
	return(0);
}

char *get_qj_str(int lang_id, char ch)
{
	int ch_pos;
	char *str;

	if (lang_id < 0 || lang_id > LANGS_NUM) 
		return(NULL);

	if (FullWideCharListByLang[lang_id].bInit == 0)
		read_qjbj_config_file(lang_id);

	ch_pos = ch - 0x21;

	if (ch_pos < 0 || ch_pos >= FULLWIDE_CHAR_NUM)
		return(NULL);

	str = FullWideCharListByLang[lang_id].QjStr[ch_pos];

	if (str != NULL) return(str);

	if (lang_id == LANG_ZH_CN) 
		return(FullWideCharListByLang_CN[ch_pos]);
	else if (lang_id == LANG_ZH_TW || lang_id == LANG_ZH_HK)
		return(FullWideCharListByLang_TW[ch_pos]);
	else 
		return(NULL);
}

char *get_punct_str(int lang_id, char ch)
{
	int i, ch_pos;
	char *str;

	if (lang_id < 0 || lang_id > LANGS_NUM) 
		return(NULL);

	if (PunctCharListByLang[lang_id].bInit == 0)
		read_punct_config_file(lang_id);


	ch_pos = -1;
	for (i=0; i<PUNCT_CHAR_NUM; i++) {
		if (ch == PunctChars[i]) {
			ch_pos = i;
			break;
		}
	}
	if (ch_pos == -1)
		return(NULL);

	str = PunctCharListByLang[lang_id].PunctStr[ch_pos];

	if (str != NULL) return(str);

	if (lang_id == LANG_ZH_CN) 
		return(PunctCharListByLang_CN[ch_pos]);
	else if (lang_id == LANG_ZH_TW || lang_id == LANG_ZH_HK)
		return(PunctCharListByLang_TW[ch_pos]);
	else 
		return(NULL);
}

