#include "stdafx.h"
#include <Windows.h>
#include <memory.h>
#include "WD_Def.h"

#pragma comment(lib, "D:\\tmp\\Test_IME\\SogoIMETesting\\SogoIMETesting\\sogoIME\\Sogou_IME_CNS.lib")
#pragma comment(lib, "D:\\tmp\\Test_IME\\SogoIMETesting\\SogoIMETesting\\sogoIME\\Sogou_IME_ENG.lib")
#pragma comment(linker, "/NODEFAULTLIB:libc.lib")
#pragma comment(linker, "/NODEFAULTLIB:libcd.lib")


#define MAX_INPUT_LEN 10
#define MAX_IME_COUNT 10
#define MAX_DISPLAYED_PER_LINE 5

#define USER_TIMER TRUE

//类型定义

typedef wchar_t WCHAR;
typedef WD_UINT32 u32;

typedef enum _INPUT_CMD
{
	IC_HELP = 13000,
	IC_EXIT,
	IC_ERROR
}INPUT_CMD;

typedef struct _IME_TEST_CNTX
{
	WD_UINT8 nLastDisplayedCharCount;
	WD_UINT8 inputMethod[MAX_IME_COUNT];
	WCHAR szOutput[989];
	WD_imeResult imeResult;
}IME_TEST_CNTX;

typedef struct _KEY_MAP
{
	char szInputKey[MAX_INPUT_LEN];
	WD_INT32 nIMEKey;
	char* pszHelpInfo;
}KEY_MAP;

typedef struct EAT_normal_to_long_press_map
{
	u32 normal_press_key;
	u32 long_press_key;
}EAT_normal_to_long_map;

typedef struct _IME_KEY_MAP
{
	u32 deviceValue;
	u32 imeKey;
}IME_KEY_MAP;


#ifndef SEPARATE_VARIABLE
EAT_normal_to_long_map g_key_press_map[] =
{
	{WDK_NORMAL_0,WDK_LONG_0},
	{WDK_NORMAL_1,WDK_LONG_1},
	{WDK_NORMAL_2,WDK_LONG_2},
	{WDK_NORMAL_3,WDK_LONG_3},
	{WDK_NORMAL_4,WDK_LONG_4},
	{WDK_NORMAL_5,WDK_LONG_5},
	{WDK_NORMAL_6,WDK_LONG_6},
	{WDK_NORMAL_7,WDK_LONG_7},
	{WDK_NORMAL_8,WDK_LONG_8},
	{WDK_NORMAL_9,WDK_LONG_9},

	{WDK_NORMAL_A,WDK_LONG_LETTER_A},
	{WDK_NORMAL_B,WDK_LONG_LETTER_B},
	{WDK_NORMAL_C,WDK_LONG_LETTER_C},
	{WDK_NORMAL_D,WDK_LONG_LETTER_D},
	{WDK_NORMAL_E,WDK_LONG_LETTER_E},
	{WDK_NORMAL_F,WDK_LONG_LETTER_F},
	{WDK_NORMAL_G,WDK_LONG_LETTER_G},
	{WDK_NORMAL_H,WDK_LONG_LETTER_H},
	{WDK_NORMAL_I,WDK_LONG_LETTER_I},
	{WDK_NORMAL_J,WDK_LONG_LETTER_J},
	{WDK_NORMAL_K,WDK_LONG_LETTER_K},
	{WDK_NORMAL_L,WDK_LONG_LETTER_L},
	{WDK_NORMAL_M,WDK_LONG_LETTER_M},
	{WDK_NORMAL_N,WDK_LONG_LETTER_N},
	{WDK_NORMAL_O,WDK_LONG_LETTER_O},
	{WDK_NORMAL_P,WDK_LONG_LETTER_P},
	{WDK_NORMAL_Q,WDK_LONG_LETTER_Q},
	{WDK_NORMAL_R,WDK_LONG_LETTER_R},
	{WDK_NORMAL_S,WDK_LONG_LETTER_S},
	{WDK_NORMAL_T,WDK_LONG_LETTER_T},
	{WDK_NORMAL_U,WDK_LONG_LETTER_U},
	{WDK_NORMAL_V,WDK_LONG_LETTER_V},
	{WDK_NORMAL_W,WDK_LONG_LETTER_W},
	{WDK_NORMAL_X,WDK_LONG_LETTER_X},
	{WDK_NORMAL_Y,WDK_LONG_LETTER_Y},
	{WDK_NORMAL_Z,WDK_LONG_LETTER_Z},

	{WDK_STAR,WDK_LONG_STAR},    /* "*" 键                                    */
	{WDK_SHARP,WDK_LONG_SHARP},   /* "#" 键                                    */
	{WDK_UP,WDK_LONG_UP},     /* 方向键                                   */
	{WDK_DOWN,WDK_LONG_DOWN},
	{WDK_LEFT,WDK_LONG_LEFT},
	{WDK_RIGHT,WDK_LONG_RIGHT},
	{WDK_C,WDK_LONG_C},     /* 删除键                                  */
	{WDK_OK,WDK_LONG_OK},     /* 确认键：用于确认当前的选择项        */
	{WDK_MENU,WDK_LONG_MENU},    /* 全键盘时，执行FN键功能                */
	{WDK_SOFTLEFT,WDK_LONG_SOFTLEFT},  /* 左软键：全键盘时，执行空格键功能   */
	{WDK_SOFTRIGHT,WDK_LONG_SOFTRIGHT}, /* 右软键：                                 */
	{WDK_SHIFT,WDK_LONG_SHIFT},    /* Shift                                      */
	{WDK_CAPLOCK,WDK_LONG_CAPLOCK},  /* 大小写切换：                            */
	{WDK_SEPERATER,WDK_LONG_SEPERATER}, /* 分隔                                      */
	{WDK_FUNC,WDK_LONG_FUNC},    /* FN：                                      */
	{WDK_ENTER,WDK_LONG_ENTER},   /* 回车                                      */
	{WDK_ALT,WDK_LONG_ALT},    /* Alt                                        */
	{WDK_CTRL,WDK_LONG_CTRL},    /* Ctrl                                       */
	{WDK_SPACE,WDK_LONG_SPACE},   /* 空格            */
	{WDK_SYMBOL,WDK_LONG_SYMBOL},   /* 符号            */
	{WDK_SWITCHIME,WDK_LONG_SWITCHIME}, /* 切换输入法          */
};

IME_KEY_MAP g_ImeKeyMap[] = 
{
	{'0', WDK_NORMAL_0},
	{'1', WDK_NORMAL_1},
	{'2', WDK_NORMAL_2},
	{'3', WDK_NORMAL_3},
	{'4', WDK_NORMAL_4},
	{'5', WDK_NORMAL_5},
	{'6', WDK_NORMAL_6},
	{'7', WDK_NORMAL_7},
	{'8', WDK_NORMAL_8},
	{'9', WDK_NORMAL_9},

	{'a', WDK_NORMAL_A},
	{'b', WDK_NORMAL_B},
	{'c', WDK_NORMAL_C},
	{'d', WDK_NORMAL_D},
	{'e', WDK_NORMAL_E},
	{'f', WDK_NORMAL_F},
	{'g', WDK_NORMAL_G},
	{'h', WDK_NORMAL_H},
	{'i', WDK_NORMAL_I},
	{'j', WDK_NORMAL_J},
	{'k', WDK_NORMAL_K},
	{'l', WDK_NORMAL_L},
	{'m', WDK_NORMAL_M},
	{'n', WDK_NORMAL_N},
	{'o', WDK_NORMAL_O},
	{'p', WDK_NORMAL_P},
	{'q', WDK_NORMAL_Q},
	{'r', WDK_NORMAL_R},
	{'s', WDK_NORMAL_S},
	{'t', WDK_NORMAL_T},
	{'u', WDK_NORMAL_U},
	{'v', WDK_NORMAL_V},
	{'w', WDK_NORMAL_W},
	{'x', WDK_NORMAL_X},
	{'y', WDK_NORMAL_Y},
	{'z', WDK_NORMAL_Z},

	{'*', WDK_STAR},
	{'#', WDK_SHARP}
};

static KEY_MAP keymapTable[] = {
	{"up", WDK_UP, ":向上键"},
	{"down", WDK_DOWN, ":向下键"},
	{"left", WDK_LEFT, ":向左键"},
	{"right", WDK_RIGHT, ":向右键"},
	{"ok", WDK_OK, ":确认键"},
	{"back", WDK_C, ":清除键"},
	{"lskb", WDK_SOFTLEFT, ":左软键"},
	{"rskb", WDK_SOFTRIGHT, ":右软键"},
	{"shift", WDK_SHIFT, ":上档键"},
	{"alt", WDK_ALT, ""},
	{"caplock", WDK_CAPLOCK, ":大写锁定键"},
	{"enter", WDK_ENTER, ":回车键"},
	{"space", WDK_SPACE, ":空格键"},
	{"switch", WDK_SWITCHIME, ":切换输入法键"},
	{"symbol", WDK_SYMBOL, ":符号键"},
	{"fn", WDK_MENU, ":fn键"},
	{"help", IC_HELP, ":打印帮助"},
	{"exit", IC_EXIT, ":退出"}
};

#endif



//函数声明
#ifndef SEPARATE_FUNCTION
void checkScreenOutput();
WD_INT32 convertToIMEKey(char* pszInput);
IME_TEST_CNTX* getIMETestContext();
WD_UINT8 getMatchLetterIndex();
void outputHelpInfo();
void releaseIMETestContext();
void responseIMEKey(WD_INT32 nIMEKey);
void updateLastDisplayedCharCount();
WD_BOOLEAN updateIMEName(WD_UINT8 u8ImeTypeOld);
void updateLetterSelecting();
void updateWordSelecting();
void waitingUserInput(char* pszInput);
#endif //SEPARATE_FUNCTION



//函数实现

//被测函数begin
static WD_INT32 eat_ime_convert_to_long_press_key(WD_UINT8 normal_key)
{
	WD_UINT8 uIndex = 0;
	int len = sizeof(g_key_press_map)/sizeof(EAT_normal_to_long_map);
	for(;uIndex < len;uIndex++)
	{
		if(normal_key == g_key_press_map[uIndex].normal_press_key)
		{
			break;
		}
	}
	return (uIndex < len) ? g_key_press_map[uIndex].long_press_key : -1;
}

static WD_INT32 eat_ime_convert_to_SoGou_key(WD_INT32 key)
{
	WD_UINT8 uIndex = 0;
	int len = sizeof(g_ImeKeyMap)/sizeof(IME_KEY_MAP);
	for(;uIndex < len;uIndex++)
	{
		if(key == g_ImeKeyMap[uIndex].deviceValue)
		{
			break;
		}
	}
	return (uIndex < len) ? g_ImeKeyMap[uIndex].imeKey : -1;
}
//被测函数end


void checkScreenOutput()
{
	IME_TEST_CNTX* pImeTestContext = getIMETestContext();
	if ('\0' != pImeTestContext->imeResult.output[0])
	{
		_tcscat(pImeTestContext->szOutput, (WCHAR*)(pImeTestContext->imeResult.output));
		_tprintf(_T("屏幕当前输出：%s\n"), pImeTestContext->szOutput);
	}
}

WD_INT32 convertToIMEKey(char* pszInput)
{
	WD_INT32 nInputLen = strlen(pszInput);
	WD_BOOLEAN bLongPress = WD_FALSE;
	WD_INT32 nIMEKey = IC_ERROR;
	char cInput = 0;

	if(1 == nInputLen)
	{
		cInput = pszInput[0];
	}
	else if((2 == nInputLen) && ('l' == pszInput[0]))
	{
		bLongPress = WD_TRUE;
		cInput = pszInput[1];
		nInputLen = 1;
	}
	
	if (1 == nInputLen)
	{
		nIMEKey = eat_ime_convert_to_SoGou_key(cInput);
		if(-1 == nIMEKey)
		{
			nIMEKey = IC_ERROR;	
		}
	}
	else
	{
		WD_INT32 nTableSize = sizeof(keymapTable)/sizeof(keymapTable[0]);
		for (WD_INT32 nIndex = 0; nIndex < nTableSize; nIndex++)
		{
			if (0 == strcmp(pszInput, keymapTable[nIndex].szInputKey))
			{
				nIMEKey = keymapTable[nIndex].nIMEKey;
			}
		}
	}
	
	if(bLongPress && (IC_ERROR != nIMEKey))
	{
		nIMEKey = eat_ime_convert_to_long_press_key(nIMEKey);
		if(-1 == nIMEKey)
		{
			nIMEKey = IC_ERROR;
		}
	}

	return nIMEKey;
}

void CALLBACK TimeProc(HWND hwnd,UINT message,     
					   UINT idTimer,DWORD dwTime)
{
	char szInput[MAX_INPUT_LEN+1] = {0};
	WD_INT32 nIMEKey = -1;
	static bool bPrint = false;

	if(bPrint)
	{
		checkScreenOutput();
		bPrint = false;
	}
	else
	{
		waitingUserInput(szInput);
		nIMEKey = convertToIMEKey(szInput);

		if (IC_ERROR == nIMEKey)
		{
			_tprintf(_T("输入的字符不支持，请重新输入：\n"));
		}
		else if(IC_HELP == nIMEKey)
		{
			outputHelpInfo();
		}
		else if (IC_EXIT == nIMEKey)
		{
			printf("按任意键退出!");
			getchar();
			exit(1);
		}
		else
		{
			responseIMEKey(nIMEKey);
		}
		//bPrint = true;
	}
}


int StartTimer()
{
	SetTimer(NULL,1,300,TimeProc);
	MSG   msg;   
	while(GetMessage(&msg,NULL,0,0))   
	{   
		if(msg.message==WM_TIMER)   
		{   
			DispatchMessage(&msg);   
		}   
	}   
	return 0;
}

void entryTestingTimer()
{
	IME_TEST_CNTX* pImeCntx = getIMETestContext();
	printf("输入法：%s(输入help可查看帮助)", pImeCntx->imeResult.imeString);

	StartTimer();
}

void entryTestingLoop()
{
	IME_TEST_CNTX* pImeCntx = getIMETestContext();
	printf("输入法：%s(输入help可查看帮助)", pImeCntx->imeResult.imeString);
	
	do 
	{
		char szInput[MAX_INPUT_LEN+1] = {0};
		WD_INT32 nIMEKey = -1;
		
		waitingUserInput(szInput);
		nIMEKey = convertToIMEKey(szInput);

		if (IC_ERROR == nIMEKey)
		{
			_tprintf(_T("输入的字符不支持，请重新输入：\n"));
		}
		else if(IC_HELP == nIMEKey)
		{
			outputHelpInfo();
		}
		else if (IC_EXIT == nIMEKey)
		{
			break;
		}
		else
		{
			responseIMEKey(nIMEKey);
		}
	} while (true);

	printf("按任意键退出!");
	getchar();
}

WD_UINT8 getMatchLetterIndex()
{
	IME_TEST_CNTX* pImeTestContext = getIMETestContext();
	WD_imeResult pImeRet = pImeTestContext->imeResult;
	WCHAR* pszOutput = (WCHAR*)pImeRet.outputKeys;
	WCHAR szOutput[MAX_KEYS_LEN*MAX_CHINESE_WORD_LEN+1] = {0};

	WD_BOOLEAN bFind = WD_FALSE;
	WD_UINT8 u8Index = 0;

	if(WDI_CN_CPINYIN == pImeTestContext->imeResult.imeType)
	{
		_tcscpy(szOutput, _tcslwr(pszOutput));
	}
	else
	{
		_tcscpy(szOutput, pszOutput);
	}

	while(0 != pImeRet.letterSelecting[u8Index][0])
	{
		if(0 == _tcscmp(szOutput, (WCHAR*)pImeRet.letterSelecting[u8Index]))
		{
			bFind = WD_TRUE;
			break;
		}

		u8Index++;
	}

	return (bFind ? u8Index : 0);
}


void responseIMEKey(WD_INT32 nIMEKey)
{
	IME_TEST_CNTX* pImeTestContext = getIMETestContext();
	WD_UINT8 u8ImeTypeOld = pImeTestContext->imeResult.imeType;

	if (0 != WD_OnKey(nIMEKey, 0, pImeTestContext->nLastDisplayedCharCount, &pImeTestContext->imeResult))
	{
		_tprintf(_T("按键错误！\n"));
		return;
	}

	if(updateIMEName(u8ImeTypeOld))
	{
		return;
	}
	else
	{
		updateLetterSelecting();
		updateWordSelecting();
		checkScreenOutput();
	}
}

void startIMETesting()
{
	IME_TEST_CNTX* pImeCntx = getIMETestContext();

	if(0 == IME_Initialize(pImeCntx->inputMethod, WDI_CN_CPINYIN, 0, &pImeCntx->imeResult))
	{
		if (USER_TIMER)
		{
			entryTestingTimer();
		}
		else
		{
			entryTestingLoop();
		}
		
		SG_Quit();
	}

	releaseIMETestContext();
}

WD_BOOLEAN updateIMEName(WD_UINT8 u8ImeTypeOld)
{
	IME_TEST_CNTX* pImeTestContext = getIMETestContext();
	if(u8ImeTypeOld != pImeTestContext->imeResult.imeType)
	{
		if((WDI_DIGIT == pImeTestContext->imeResult.imeType)
			||(WDI_CN_FULLPINYIN == pImeTestContext->imeResult.imeType)
			||(WDI_CN_CPINYIN == pImeTestContext->imeResult.imeType)
			||(WDI_CN_BIHUA == pImeTestContext->imeResult.imeType))
		{
			printf("\n输入法:%s", pImeTestContext->imeResult.imeString);
		}
		else
		{
			_tprintf(_T("\n输入法:%s"), pImeTestContext->imeResult.imeString);
		}
		
		return WD_TRUE;
	}

	return WD_FALSE;
}

void updateLetterSelecting()
{
	IME_TEST_CNTX* pImeTestContext = getIMETestContext();
	WD_UINT8 u8CurFocus = getMatchLetterIndex();
	WD_UINT8 u8CharIndex = 0;
	WCHAR szSelChar[100] = {0};
	
	while((u8CharIndex < MAX_KEY_LETTERCOUNT)
		&& (pImeTestContext->imeResult.letterSelecting[u8CharIndex][0] != '\0'))
	{
		if(u8CurFocus == u8CharIndex)
		{
			_tcscat(szSelChar, _T("<"));
		}
		
		_tcscat(szSelChar, (WCHAR*)(pImeTestContext->imeResult.letterSelecting[u8CharIndex]));
		
		if(u8CurFocus == u8CharIndex)
		{
			_tcscat(szSelChar, _T(">"));
		}
		
		_tcscat(szSelChar, _T(" "));

		u8CharIndex++;
	}

	if(WDI_CN_BIHUA != pImeTestContext->imeResult.imeType)
	{
		_tprintf(_T("待选组合符号：%s"),szSelChar);
	}
}

void updateWordSelecting()
{
	IME_TEST_CNTX* pImeTestContext = getIMETestContext();
	WD_UINT8 u8CurFocus = pImeTestContext->imeResult.idxSelecting;
	WD_INT32 nWordIndex = 0;
	WCHAR szSelWord[100] = {0};
	
	while((nWordIndex < MAX_DISPLAYED_PER_LINE)
		&& (pImeTestContext->imeResult.selecting[nWordIndex][0] != '\0'))
	{		
		if(u8CurFocus == nWordIndex)
		{
			_tcscat(szSelWord, _T("<"));
		}

		WCHAR szWordIndex[10] = {0};
		_itot((nWordIndex+1), szWordIndex, 10);
		_tcscat(szSelWord, szWordIndex);
		_tcscat(szSelWord, _T(":"));
		_tcscat(szSelWord, (WCHAR*)(pImeTestContext->imeResult.selecting[nWordIndex]));
		
		if(u8CurFocus == nWordIndex)
		{
			_tcscat(szSelWord, _T(">"));
		}
		
		_tcscat(szSelWord, _T(" "));

		nWordIndex++;
	}
	
	pImeTestContext->nLastDisplayedCharCount = nWordIndex;
	_tprintf(_T("\n待选词：%s\n"),szSelWord);
}

void waitingUserInput(char* pszInput)
{
	if(USER_TIMER)
	{
		static char szInputTable[][MAX_INPUT_LEN] = {
			"2",/*纯拼*/
			"4",
			"8",
			"6",
			"right",
			"ok",
			"7",
			"4",
			"6",
			"right",
			"ok",
			"back",
			"l9",
			"ok",
			"#",/*全拼*/
			"q",
			"u",
			"a",
			"n",
			"ok",
			"p",
			"i",
			"n",
			"ok",
			"back",
			"#",/*ab*/
			"2",
			"ok",
			"2",
			"2",
			"ok",
			"#",/*english*/
			"3",
			"6",
			"4",
			"5",
			"right",
			"ok",
			"#",/*笔画*/
			"3",
			"1",
			"4",
			"3",
			"1",
			"4",
			"3",
			"1",
			"1",
			"ok",
			"back",
			"#",/*数字*/
			"1",
			"2",
			"3"
		};

		static int nTableIndex = 0;

		int nTableLen = sizeof(szInputTable) / sizeof(szInputTable[0]);
		if (nTableIndex < nTableLen)
		{
			strcpy(pszInput, szInputTable[nTableIndex]);
			nTableIndex++;
		}
		else
		{
			strcpy(pszInput, "exit");
			nTableIndex = 0;
		}
	}
	else
	{
		_tprintf(_T("\n请输入字符，最长十个："));
		WD_INT32 nIndex = 0;
		while(nIndex < MAX_INPUT_LEN)
		{
			char c = getchar();
			if ('\n' == c)
			{
				break;
			}

			pszInput[nIndex] = c;
			nIndex++;
		}
	}
}

static IME_TEST_CNTX* pImeTestContext = NULL;
	
IME_TEST_CNTX* getIMETestContext()
{
	if(NULL == pImeTestContext)
	{
		WD_UINT8 inputMethod[MAX_IME_COUNT] =  
		{
			WDI_DIGIT, 
			WDI_CN_CPINYIN,
			WDI_CN_FULLPINYIN,
			WDI_ENGLISH_ABC,
			WDI_ENGLISH, 
			WDI_CN_BIHUA
		};
		
		pImeTestContext = (IME_TEST_CNTX*)malloc(sizeof(IME_TEST_CNTX));
		memset(pImeTestContext, 0, sizeof(IME_TEST_CNTX));
		pImeTestContext->nLastDisplayedCharCount = MAX_DISPLAYED_PER_LINE;
		strcpy((char*)(pImeTestContext->inputMethod), (char*)inputMethod);
	}

	return pImeTestContext;
}

void outputHelpInfo()
{
	WD_INT32 nTableSize = sizeof(keymapTable)/sizeof(keymapTable[0]);
	printf("支持的命令:\n");
	
	for (WD_INT32 nIndex = 0; nIndex < nTableSize; nIndex++)
	{
		printf("%s%s\n", keymapTable[nIndex].szInputKey, keymapTable[nIndex].pszHelpInfo);
	}
}

void releaseIMETestContext()
{
	if(pImeTestContext)
	{
		delete pImeTestContext;
		pImeTestContext = NULL;
	}
}

