#include "settings.h"
#include "PalmChip.h"

BOOLEAN Key_bPressed;					// Key pressed
BOOLEAN Key_bLetter;

extern BOOLEAN Menu_bPasswordOK;

#ifdef NEWUI
extern BOOLEAN NewUI_bSetup;
#endif

static BOOLEAN _bCapital = FALSE;

static XCHAR	_iInputTimer;			// Key input timer value
static XCHAR	_iOldIndex;				// Previous key index
static XCHAR	_iMapPos;				// Char map position

// Capital MAP
#define	MAP_ROW			10
#define	MAP_COL			6
static CCHAR _cLetterMap[MAP_ROW][MAP_COL] =
{
	{'0', ' ', '@', '-', '&', 0},
	{'1', '.', ',', '_', '!', 0},
	{'2', 'a', 'b', 'c', '[',   0},
	{'3', 'd', 'e', 'f', ']',   0},
	{'4', 'g', 'h', 'i', '*', 0},
	{'5', 'j', 'k', 'l', 0,   0},
	{'6', 'm', 'n', 'o', '#', 0},
	{'7', 'p', 'q', 'r', 's', 0},
	{'8', 't', 'u', 'v', 0,   0},
	{'9', 'w', 'x', 'y', 'z', 0}
};

static CCHAR _cCapitalMap[MAP_ROW][MAP_COL] =
{
	{'0', ' ', ':', ';', '\'', 0},
	{'1', '.', ',', '?', '/', 0},
	{'2', 'A', 'B', 'C', '[',   0},
	{'3', 'D', 'E', 'F', ']',   0},
	{'4', 'G', 'H', 'I', '*', 0},
	{'5', 'J', 'K', 'L', 0,   0},
	{'6', 'M', 'N', 'O', '#', 0},
	{'7', 'P', 'Q', 'R', 'S', 0},
	{'8', 'T', 'U', 'V', 0,   0},
	{'9', 'W', 'X', 'Y', 'Z', 0}
};

void _OnImpossibleKey()
{
	Cam_LedOff(Sys_cOptions[0]);
	DebugCString((PCCHAR)"");
	DisplayInitialize();
	DisplayStatus((PCCHAR)"", 0, 0);
	IsFunctionMode();
#if defined MT28F016 || defined _USE_FXS
	LoadPcmRing();
#endif	// MT28F016
	OnReboot();
#ifdef GUI_UPGRADE_RING
	OnUpdateRingFile(0);
#endif
	OutputString(0);
	p_getKeyId(0);
	p_IsNewLine((PXCHAR)0);
	p_memcmp_ip((PXCHAR)0, (PXCHAR)0);
	p_memset_ip_0((PXCHAR)0);
	p_rand_array((PXCHAR)0, 0);
	p_rand_char();
	SdramCopyData(0, (PXCHAR)0);
	SdramCopyData_0(0, (PXCHAR)0);
	SdramCopyEthernetFrame(0, (PXCHAR)0, 0);
	SdramSaveEthernetFrame(0, (PXCHAR)0, 0);
	SdramSaveData(0, (PXCHAR)0, 0);
	Cam_LedOn(0);
#ifdef _USE_FAKE_FXO
	DualModeStartup();
	DualModeHandleTimer();
	CheckDualModePrefix();
	CheckDualModeStatus();
#endif
}

UCHAR KeypadInitialize()
{
	DCHAR iKey;

	_iOldIndex = MAP_COL;
	Key_bLetter = TRUE;

//	XBYTE[INT_ENABLE] |= INT_MASK_KEY;	// Enable keypad interrupt

	XBYTE[KEY_DOUT] = KEYPAD_COLUMN;
	XBYTE[KEY_ENABLE] = KEYPAD_COLUMN;			// drive 4-bit of keyboard 
	iKey = XBYTE[KEY_DIN] & KEYPAD_ROW;			// read row 
	XBYTE[KEY_ENABLE] = KEYPAD_ROW;				// switch to read column 
	iKey += XBYTE[KEY_DIN] & KEYPAD_COLUMN;		// read column 
	XBYTE[KEY_ENABLE] = KEYPAD_COLUMN;			// drive 4-bit of keyboard 
//	XBYTE[KEY_INTEN] = KEYPAD_ROW;				// enable 3-bit iSelection detect 
//	XBYTE[KEY_EDGE] = KEYPAD_ROW;				// all edge detect keys 
	return iKey;
}

void KeypadDisplay()
{
	DCHAR iLen;

	iLen = p_strlen_x(Key_pBuf);
	if (!Menu_bPasswordOK)
	{
		p_memset_x((PXCHAR)Sdram_pDataCache, '*', iLen);
		X_VAL(Sdram_pDataCache, iLen) = 0;
		DisplayLine((PXCHAR)Sdram_pDataCache, 1);
		return;
	}

	if (Key_bInputMode)
	{
		if (iLen <= DISPLAY_MAX_CHAR)
		{
			Display(Key_pBuf, 1, 0, (_iMapPos) ? Key_bPressed : FALSE);
		}
		else
		{
			Display(Key_pBuf, 0, 0, TRUE);
			Display((PXCHAR)(Key_pBuf+DISPLAY_MAX_CHAR), 1, 0, (_iMapPos) ? Key_bPressed : FALSE);
		}
	}
}

void KeypadClearAll()
{
	Key_bInputMode = TRUE;
#if defined VER_KINGTEL || defined VER_YODAO
	DisplayCursor(FALSE);
#else
	DisplayCursor(TRUE);
#endif
	Key_bPressed = FALSE;
	KeypadClear();
	KeypadDisplay();
}

void HandleNumberKeys()
{
	DCHAR iIndex, iLen;
	PCCHAR pMap;

	if (!Key_bInputMode)	return;

#ifdef NEWUI
	if(NewUI_bSetup)
	{
		OnOK();
		return;
	}
#endif

	iLen = p_strlen_x(Key_pBuf);

	if (Key_iCurrentID == '#')
	{
		_bCapital = !_bCapital;
		_iInputTimer = 0;	// start count again
		return;
	}
	else if (Key_iCurrentID == '*')
	{
		Key_iCurrentID = '.';
		Key_bPressed = FALSE;
	}
	else if (Key_bLetter)
	{
		_iInputTimer = 0;
		iIndex = Key_iCurrentID - '0';
		if (_bCapital)	pMap = (PCCHAR)_cCapitalMap[iIndex];
		else			pMap = (PCCHAR)_cLetterMap[iIndex];

		if ((!Key_bPressed) || (iIndex != _iOldIndex))
		{
			_iMapPos = 0;
			Key_iCurrentID = pMap[0]; 
			Key_bPressed = TRUE;
			_iOldIndex = iIndex;
		}
		else
		{
			_iMapPos ++;
			Key_iCurrentID = pMap[_iMapPos];
			if (!Key_iCurrentID)
			{
				_iMapPos = 0;
				Key_iCurrentID = pMap[0]; 
			}
			iLen --;
		}
	}
	else
	{
		Key_bPressed = FALSE;
	}

	if (iLen == MAX_KEYBUF_LEN)
	{
		iLen = 0;
	}
	Key_pBuf[iLen] = Key_iCurrentID;
	iLen ++;
	Key_pBuf[iLen] = 0;
	KeypadDisplay();
}

void KeyInputHandleTimer()
{
	if (!Key_bPressed)	return;

	_iInputTimer ++;

	if (_iInputTimer == 100)		// 2 secs
	{
		Key_bPressed = FALSE;
		KeypadDisplay();
	}
}

#ifdef VER_IPH_E00
void HandleFunctionKeys()
{
#ifdef NEWUI
	if(NewUI_bSetup) return;
#endif
	SettingsStopRoll();

#ifndef VER_IPH_E00_2G
	switch (Key_iCurrentID)
	{
	case 'A':		// Redial as "Cancel"	
		OnCancel();
		break;
	case 'C':		// Local ip as "Set"	
		OnSet();
		break;
	case 'M':		// Call/Mute as "BackSpace"
		OnBackSpace();
		break;
	case 'N':		// Handfree as "OK"	
		OnOK();
		break;
	case 'O':		// VOL- as "MenuUp"	
		OnMenuUp();
		break;
	case 'P':		// VOL+ as "MenuDown"
		OnMenuDown();
		break;
	case 'X':
		_OnImpossibleKey();
		break;
	}
#else
	switch (Key_iCurrentID)
	{
	case 'E':		// Servicel as "Cancel"	
//		if(!Menu_bPasswordOK)
//			SwitchPage(4);
//		else	
			OnCancel();
		break;		
	case 'M':		// Handfree as "Set"
		OnSet();
		break;
	case 'K':		// Enter as "OK"
		OnOK();
		break;
	case 'J':		// VOL- as "MenuUp"	
		OnMenuUp();
		break;
	case 'I':		// VOL+ as "MenuDown"
		OnMenuDown();
		break;
	case 'F':		// Redial as "BackSpace"
		OnBackSpace();
		break;		
	case 'X':
		_OnImpossibleKey();
		break;
	}
#endif
}
#elif defined VER_KINGTEL
void HandleFunctionKeys()
{
	SettingsStopRoll();

	switch (Key_iCurrentID)
	{
	case 'g':		// Kingtel's SET Key
		OnSet();
		break;
	case 'D':		// back space key
		OnBackSpace();
		if (!Key_bInputMode)
		{
			OnCancel();
		}
		break;
	case 'F':		// Kingtel's Menu/Enter Key
		OnOK();
		break;
	case 'O':		// VOL- as "MenuUp"
		OnMenuUp();
		break;
	case 'P':		// VOL+ as "MenuDown"
		OnMenuDown();
		break;
	case 'X':
		_OnImpossibleKey();
		break;
	}
}

#elif defined VER_YWH500

void HandleFunctionKeys()
{
	SettingsStopRoll();
	
	switch (Key_iCurrentID)
	{
	case 'm':  // Redial as "Cancel"
		OnCancel();
		break;
	case 'A':  // Local ip as "Set"
		OnSet();
		break;
	case 'k':  // back space key
		OnBackSpace();
		break;
	case 'l':  // Handfree as "OK"
		OnOK();
		break;
	case 'O':  // VOL- as "MenuUp"
		OnMenuUp();
		break;
	case 'G':  // VOL+ as "MenuDown"
		OnMenuDown();
		break;
	case 'X':
		_OnImpossibleKey();
		break;
	}
}

#elif defined VER_YWH300

void HandleFunctionKeys()
{
	SettingsStopRoll();
	
	switch (Key_iCurrentID)
	{
	case 'H':  // Redial as "Cancel"
		OnCancel();
		break;
	case 'C':  // Local ip as "Set"
		OnSet();
		break;
	case 'D':  // back space key
		OnBackSpace();
		break;
	case 'O':  // Handfree as "OK"
		OnOK();
		break;
	case 'A':  // VOL- as "MenuUp"
		OnMenuUp();
		break;
	case 'E':  // VOL+ as "MenuDown"
		OnMenuDown();
		break;
	case 'X':
		_OnImpossibleKey();
		break;
	}
}

#elif defined VER_YWH200

void HandleFunctionKeys()
{
	SettingsStopRoll();
	
	switch (Key_iCurrentID)
	{
	case 'O':  // Redial as "Cancel"
		OnCancel();
		break;
	case 'D':  // Local ip as "Set"
		OnSet();
		break;
	case 'F':  // back space key
		OnBackSpace();
		break;
	case 'N':  // Handfree as "OK"
		OnOK();
		break;
	case 'A':  // VOL- as "MenuUp"
		OnMenuUp();
		break;
	case 'C':  // VOL+ as "MenuDown"
		OnMenuDown();
		break;
	case 'X':
		_OnImpossibleKey();
		break;
	}
}

#elif defined VER_EP668
void HandleFunctionKeys()
{
	SettingsStopRoll();

	switch (Key_iCurrentID)
	{
	case 'A':		// Redial as "Cancel"
		OnCancel();
		break;
	case 'C':		// Local ip as "Set"
		OnSet();
		break;
	case 'M':		// back space key
		OnBackSpace();
		break;
	case 'N':		// Handfree as "OK"
		OnOK();
		break;
	case 'O':		// VOL- as "MenuUp"
		OnMenuUp();
		break;
	case 'F':		// VOL+ as "MenuDown"
		OnMenuDown();
		break;
	case 'X':
		_OnImpossibleKey();
		break;
	}
}

#elif defined OEM_JR168
void HandleFunctionKeys()
{
	SettingsStopRoll();

	switch (Key_iCurrentID)
	{
	case 'a':		// for 6*7 keypad, a is Set key
		OnSet();
		break;
	case 'D':		// back space key
		OnBackSpace();
		if (!Key_bInputMode)
		{
			OnCancel();
		}
		break;
	case 'h':		// for 6*7 keypad, h is menu/Enter key
	case 'N':		// Handfree as "OK"
		OnOK();
		break;
	case 'O':		// VOL- as "MenuUp"
		OnMenuUp();
		break;
	case 'P':		// VOL+ as "MenuDown"
		OnMenuDown();
		break;
	case 'X':
		_OnImpossibleKey();
		break;
	}
}

#else	// PA168X
void HandleFunctionKeys()
{
	SettingsStopRoll();

	switch (Key_iCurrentID)
	{
	case 'A':		// Redial as "Cancel"
		OnCancel();
		break;
#ifdef VER_MAXLINK
	case 'L':		// Local ip as "Set"
#else
	case 'a':		// for 6*7 keypad, a is Set key
	case 'C':		// Local ip as "Set"
#endif
		OnSet();
		break;
#ifdef GUI_5111
	case 'J':	
#else
	case 'D':		// back space key
#endif
		OnBackSpace();
		break;
	case 'h':		// for 6*7 keypad, h is menu/Enter key
	case 'N':		// Handfree as "OK"
		OnOK();
		break;
	case 'O':		// VOL- as "MenuUp"
		OnMenuUp();
		break;
	case 'P':		// VOL+ as "MenuDown"
		OnMenuDown();
		break;
	case 'X':
		_OnImpossibleKey();
		break;
	}
}

#endif


