#include <stdlib.h>
#include "kmf_ioctl.h"
#include "ap_extern.h"
#include "drv_pq_external.h"
#include "nvm_ioctl.h"
#include "util_ioctl.h"
#include "al_fw.h"
#include "subcustomer_setting.h"
#include "umf_ir.h"
#include "MM_media_qsd_gui.h"
#include "drv_tuner_external.h"
#include <sys/time.h>
#include "mid_tvfe.h"
#include "drv_uart_def.h"
#include "keyupdate.h"
#include "app_data_setting.h"
#include "pin_config.h"
#include "util_ioctl.h"
#include "app_led_control.h"
#include "board_config.h"
#include "customize.h"
//#include "app_video.h"
#include "app_guiobj_source.h"
#include "app_guiobj_software_upgrade.h"
#ifdef CONFIG_TPV_UART_FAC_MODE
#include "al_console_TpvRs232.h"
#endif

const UINT8 TpvAckTable[]=
{
#if 0
	0xC2,0xC7,0xCB,0xCC,0xD3,0xD4,0xD8,0xDD,0xE3,0xE4,0xE8,0xED,0xF0,0xF5,0xF9,0xFE,
#else
    0xF0,
#endif
};
const UINT16 g_TpvAckTableSize = sizeof(TpvAckTable)/sizeof(UINT8);
static UINT8 g_currentAckIndex = 0;
static TpvRs232_autotest_Cbk_pf g_pfpTpvRs232_AutoTestCallback = NULL;

static UINT8 _conTpvRs232_Dtata_Checksum(UINT8 * dataBuf ,UINT8 datalen)
{

	UINT8 checkSum = 0;
	UINT8   i = 0;
	for (i=0;i<datalen;i++)
	{
		checkSum ^= dataBuf[i];
	}
	return checkSum;
}

static TpvRS232Type _con_TpvRs232_GetCMDType(TpvExtCommandFrame_t frame)
{

	TpvRS232Type enReturnValue = TPV_CMD_NUM_MAX;

    switch(frame.Pre1)
    {
        //===Write cmd===========0x03
        case TPV_RW_WRITE:
            switch(frame.Pre2)
            {
                //===write pre2 cmd===========0xFE
                case TPV_PRE2:
                    switch(frame.Cmd)
                    {
                        //===write pre2 FCode01 cmd===========0xE1
                        case TPV_FCode01://FCode01
                            //===write pre2 FCode01 ExtByte cmd===========
                            switch(frame.ExtByte)
                            {
                                case 0xA0://Factory Mode
                                    enReturnValue = TPV_CMD_Factory_Mode;
                                    break;
                                case 0xA2://BurnIn Mode
                                    enReturnValue = TPV_CMD_Set_BurnInMode;
                                    break;
                                case 0xA7://Set Smart Picture mode
                                    enReturnValue = TPV_CMD_Set_Smart_Picture_mode;
                                    break;
                                case 0xA8://Set (Monitor/TV) internal Test Pattern
                                    enReturnValue = TPV_CMD_Set_internal_Test_Pattern;
                                    break;
                                
                                default:
                                    break;
                            }
                            break;
                        case TPV_FCode04://FCode04
                            //===write pre2 FCode04 ExtByte cmd===========
                            switch(frame.ExtByte)
                            {
                                case 0x02://RESET Picture mode setting (Alias: Select Picture preset (scene) mode)
                                    enReturnValue = TPV_CMD_Reset_Picture_mode_setting;
                                    break;
                                case 0x04: //Set Picture function
                                    enReturnValue = TPV_CMD_set_picture_functon;
                                    break;
                                
                                default:
                                    break;
                            }
                            break;
                            
                        case 0x14:
                            break;
                        
                        default:
                            break;
                    }
                    break;
                
                default:
                    break;
            }
            break;
            
        //===Read cmd============
        case TPV_RW_READ://read cmd 0x01
            switch(frame.Pre2)
            {
                //===read pre2 cmd=========== 0xFE
                case TPV_PRE2:
                    switch(frame.Cmd)
                    {
                        //===read pre2 FCode01 cmd===========0xE1
                        case TPV_FCode01:
                            break;
                            
                        case 0x14:
                            break;
                        
                        default:
                            break;
                    }
                    break;
                
                default:
                    break;
            }
            break;

        default:
            break;
    }

	return enReturnValue;
}

static bool _con_TpvRs232_SendAac(UINT8* data, UINT8 datalen)
{

    UINT8 ackHeader[3] ={0xF0,0x0F,0x00};
    UINT8 *ackData = NULL;
    UINT8 ackLen = 3;

    ackHeader[0] = TpvAckTable[g_currentAckIndex];
    ackHeader[1] = 0xFF - TpvAckTable[g_currentAckIndex];
    g_currentAckIndex = (g_currentAckIndex + 1) % g_TpvAckTableSize;

    if(data == NULL || datalen == 0)
    {
        ackLen = 3;
        con_echo_sfu(ackLen, ackHeader);
    }
    else
    {
        ackLen = 3 + datalen;
        ackData = (UINT8*)malloc(ackLen);
        if(ackData == NULL)
            return false;
        memset(ackData,0x0,datalen + 3);
        memcpy(ackData,ackHeader,2);
        memcpy(ackData+2,&datalen,1);
        memcpy(ackData+3,data,datalen);
        con_echo_sfu(ackLen, ackData);
        free(ackData);
        ackData = NULL;
    }

    return true;
}


bool con_TpvRs232_AutoTest_parser(pCON_DEV pcon, UINT8* msg, UINT8 msgLen)
{
	int ret = 0;
	UINT8 checkSum = 0;
	UINT8 frameLen = 0;
    TpvExtCommandFrame_t CurrentExtFrame;
	TpvRS232Type cmdIdType = TPV_CMD_NUM_MAX;
    
    memset(&CurrentExtFrame, 0, sizeof(CurrentExtFrame));

#ifdef TPV_DEBUG	
    con_echo_sfu(msgLen, msg);
#endif 

    //check header valid
    if(*msg != 0x6e || *(msg+1) != 0x51 || *(msg+2)-0x80+4 != msgLen)
        return ret;

    //check checksum valid
    checkSum = _conTpvRs232_Dtata_Checksum(msg,msgLen-1);
    if(checkSum != *(msg+msgLen-1))
    {
        printf("invalid cmd type!");
        goto END;
    }

    frameLen =  *(msg+2)-0x80;
    CurrentExtFrame.Data = (UINT8 *)malloc(frameLen - 0x4);
    if(CurrentExtFrame.Data == NULL)
        return ret;
    memset(CurrentExtFrame.Data, 0x0, frameLen - 0x4);
    memcpy((UINT8 *)&CurrentExtFrame, msg, 7); 
    memcpy(CurrentExtFrame.Data, msg+7, frameLen - 0x4);
    CurrentExtFrame.CheckSum = checkSum;
        
    cmdIdType = _con_TpvRs232_GetCMDType(CurrentExtFrame);

    if(TPV_CMD_NUM_MAX == cmdIdType)
    {
        printf("invalid cmd type!");
        goto END;
    }

	//you can deal with here, also bypass to app deal with
	//pass to app paser
	//ret = g_pfpTpvRs232_AutoTestCallback(pcon,data);

    //use CurrentExtFrame, get n th byte value => *(CurrentExtFrame.Data+n)
    switch (cmdIdType)
    {
		case TPV_CMD_Factory_Mode:
		    if(*(CurrentExtFrame.Data+0) == 0 && *(CurrentExtFrame.Data+1)==1)//enter
		    {

		    }
		    else if(*(CurrentExtFrame.Data+0) == 0 && *(CurrentExtFrame.Data+1)==0) //exit
		    {

		    }
		    else if(*(CurrentExtFrame.Data+0) == 1 && *(CurrentExtFrame.Data+1)==1) //Enter Continuous
		    {

		    }
		    else if(*(CurrentExtFrame.Data+0) == 1 && *(CurrentExtFrame.Data+1)==0) //Exit  Continuous
		    {

		    }
            _con_TpvRs232_SendAac(NULL,0);
			break;
			
		case TPV_CMD_Set_BurnInMode:
		    if(*(CurrentExtFrame.Data+1) == 1)//on
		    {

		    }
		    else //off
		    {

		    }
		    break;
		case TPV_CMD_Set_Smart_Picture_mode:
		    //CurrentFrame.Data2
		    break;
		    
        case TPV_CMD_Set_internal_Test_Pattern:
            //CurrentFrame.Data2
            break; 
            
        case TPV_CMD_Reset_Picture_mode_setting:
            //CurrentFrame.Data2
            break; 

        case TPV_CMD_set_picture_functon:
            //CurrentFrame.Data2
            if(*(CurrentExtFrame.Data+0) == 0x1)//Set Picture Size (Picture Format) and location RDM
            {

            }
            else if(*(CurrentExtFrame.Data+0) == 0x2)//Set and store noise reduction
            {

            }
            else if(*(CurrentExtFrame.Data+0) == 0x3)//Set and store color enhancement
            {

            }
            else if(*(CurrentExtFrame.Data+0) == 0x4)//sets and stores the digital natural motion
            {

            }
            else if(*(CurrentExtFrame.Data+0) == 0x5)//Sets and store the dynamic backlight
            {

            }            
            break; 
            
		    

		default:
			break;
	}

END:    
   if(CurrentExtFrame.Data)
      free(CurrentExtFrame.Data);
   CurrentExtFrame.Data= NULL;
   
   return ret;
}

void al_tpvrs232_autotest_init(TpvRs232_autotest_Cbk_t *pConsole_autotest_Cfg)
{
	if ((pConsole_autotest_Cfg != NULL) && (pConsole_autotest_Cfg->pfCallBack != NULL))
	{
		g_pfpTpvRs232_AutoTestCallback = pConsole_autotest_Cfg->pfCallBack;
	}
}
  


