#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <linux/input.h>
#include <unistd.h>
#include "umf_debug.h"
#include "umf_ir.h"
#include "gl_mempool.h"
#include "gl_sema.h"
#include "app_event.h"
#include "umf_keyBoard.h"

#define KEY_BOARD_DEFAULT_DATA_LENGTH (256)

#define KEY_BOARD_DEBUG
#ifdef KEY_BOARD_DEBUG
#define keyBoard_printf(fmt, arg...) UMFDBG(0,"[umf_keyboard][%s:%d]"fmt, __FUNCTION__, __LINE__, ##arg)
#else
#define keyBoard_printf(fmt, arg...) ((void) 0)
#endif

static char* key_board_value = NULL;
static pthread_t keyboard_thread = 0;
KeyBoardParam_t KeyBoard;
Boolean g_StartFlag = FALSE;

static char keyBoard_Code2Char(int keyCode)
{
    char retChar = 0;
    
    switch(keyCode)
    {
        case KEY_0:
        case KEY_KP0:    
            retChar = '0';
            break;
        case KEY_1:
        case KEY_KP1:    
            retChar = '1';
            break;
        case KEY_KP2:    
        case KEY_2:
            retChar = '2';
            break;
        case KEY_KP3:    
        case KEY_3:
            retChar = '3';
            break;
        case KEY_KP4:    
        case KEY_4:
            retChar = '4';
            break;
        case KEY_5:
        case KEY_KP5:    
            retChar = '5';
            break;
        case KEY_6:
        case KEY_KP6:    
            retChar = '6';
            break;
        case KEY_KP7:    
        case KEY_7:
            retChar = '7';
            break;
        case KEY_KP8:    
        case KEY_8:
            retChar = '8';
            break;
        case KEY_KP9:    
        case KEY_9:
            retChar = '9';
            break;
                
        case KEY_Q:
            retChar = 'Q';
            break;
        case KEY_W:
            retChar = 'W';
            break;
        case KEY_E:
            retChar = 'E';
            break;
        case KEY_R:
            retChar = 'R';
            break;
        case KEY_T:
            retChar = 'T';
            break;
        case KEY_Y:
            retChar = 'Y';
            break;
        case KEY_U:
            retChar = 'U';
            break;
        case KEY_I:
            retChar = 'I';
            break;
        case KEY_O:
            retChar = 'O';
            break;
        case KEY_P:
            retChar = 'P';
            break;
        case KEY_A:
            retChar = 'A';
            break;
        case KEY_S:
            retChar = 'S';
            break;
        case KEY_D:
            retChar = 'D';
            break;
        case KEY_F:
            retChar = 'F';
            break;
        case KEY_G:
            retChar = 'G';
            break;
        case KEY_H:
            retChar = 'H';
            break;
        case KEY_J:
            retChar = 'J';
            break;
        case KEY_K:
            retChar = 'K';
            break;
        case KEY_L:
            retChar = 'L';
            break;
        case KEY_Z:
            retChar = 'Z';
            break;
        case KEY_X:
            retChar = 'X';
            break;
        case KEY_C:
            retChar = 'C';
            break;
        case KEY_V:
            retChar = 'V';
            break;
        case KEY_B:
            retChar = 'B';
            break;
        case KEY_N:
            retChar = 'N';
            break;
        case KEY_M:
            retChar = 'M';
            break;
        default:

            break;
    }
    
    return retChar;
}

static void* _t_KeyBoard_MainRoutine(void *pParam)
{
    int           fd = 0;
    int           rc;
    INT32 key_board_index = 0;
    INT32 rcLength = 0;
    KeyBoardParam_t* pKeyBoard = (KeyBoardParam_t*)pParam;
    struct input_event event;
    rcLength = pKeyBoard->dataLength;
    pKeyBoard->dataLength = 0;

    prctl(PR_SET_NAME , "KeyBoard_MainRoutine", NULL, NULL, NULL);
	
    if ((fd = open("/dev/input/key_board", O_RDWR, 0)) <= 0) 
    {
        keyBoard_printf("open dev/input/key_board error!!!\n");
        keyboard_thread = 0;
        return NULL;
    }
    
    keyBoard_printf("open key_board success!!\n");

    if (pKeyBoard->StartCode == -1)
    {
        g_StartFlag = TRUE;
    }
    while ((rc = read(fd, &event, sizeof(event))) > 0)
    {
        if ((event.code == pKeyBoard->StartCode))
        {
            g_StartFlag = TRUE;
        }
    
        if (!g_StartFlag)
        {
            continue;
        }
        
        if (key_board_index)
        {
            pKeyBoard->dataLength = key_board_index;
            if (key_board_index == rcLength || (event.code == pKeyBoard->EndCode))
            {
                break;
            }
        }
        
        if (event.type == EV_KEY && event.value)//event.value is down by 1, up by 0, repeat by 2
        {
            char tmpChar = keyBoard_Code2Char(event.code);
            keyBoard_printf("key_board_index:%d, key:%d, char:%c\n", key_board_index, event.code, tmpChar);
            if (!tmpChar)
                continue;
            key_board_value[key_board_index++] = tmpChar;
        }
    }

#if 0
    for(rc = 0; rc < pKeyBoard->dataLength; rc++)
    {
        keyBoard_printf("dataLength:%d, rc:%d, key:%d\n", pKeyBoard->dataLength, rc, key_board_value[rc]);
    }
#endif

    keyBoard_printf("thread finish!!\n");
    key_board_index = 0;
    close(fd);
    keyboard_thread = 0;
    return NULL;
}

void keyBoard_Start(KeyBoardParam_t* pstKeyboard)
{    
	if (keyboard_thread != 0)
    {
        return;
    }
    
    keyBoard_printf("keyBoard_Start\n");

    g_StartFlag = FALSE;
    memset(&KeyBoard, 0, sizeof(KeyBoardParam_t));
    
    KeyBoard.dataLength = KEY_BOARD_DEFAULT_DATA_LENGTH;
    KeyBoard.StartCode = -1;
    KeyBoard.EndCode = -1;

    if (pstKeyboard)
    {
        if (pstKeyboard->dataLength)
        {
            KeyBoard.dataLength = pstKeyboard->dataLength;
        }
        
        if (pstKeyboard->StartCode)
        {
            KeyBoard.StartCode = pstKeyboard->StartCode;
        }
        
        if (pstKeyboard->EndCode)
        {
            KeyBoard.EndCode = pstKeyboard->EndCode;
        }
    }

    if (key_board_value)
    {
        free(key_board_value);
        key_board_value = NULL;
    }

    key_board_value = (char*)malloc(KeyBoard.dataLength);

    if (key_board_value == NULL)
    {
        printf("keyBoard_Start: malloc key_board_value Error!!!!!!\n");
        return ;
    }

    memset(key_board_value, 0, (KeyBoard.dataLength));
	size_t stacksize = 16*1024;
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setstacksize(&attr, stacksize);
	if (pthread_create(&keyboard_thread, &attr, _t_KeyBoard_MainRoutine, (void*)&KeyBoard) != 0)
    {
        printf("_t_KeyBoard_MainRoutine fail \n");
    }
	pthread_attr_destroy(&attr);
}

void keyBoard_Cancel(void)
{
    keyBoard_printf("\n");
    if (keyboard_thread)
    {
        pthread_cancel(keyboard_thread);
        keyboard_thread = 0;
    }
}

INT32 keyBoard_GetRcValue(char *ReturnArray, INT32 Arraylength)
{   
    keyBoard_printf("\n");
    INT32 returnLength = (Arraylength > KeyBoard.dataLength) ? KeyBoard.dataLength : Arraylength;
    memcpy(ReturnArray, key_board_value, returnLength);
    return returnLength;
}

INT32 keyBoard_GetRcDataLength(void)
{
    keyBoard_printf("\n");
    return KeyBoard.dataLength;
}


