
#include "ikk-debug.h"
#include "ikk-command.h"
#include "ikk-common-utils.h"
#include "ikk-token.h"
#include "ikk-network.h"
#include "ikk-cluster.h"
#include "ikk-factory-test.h"
#include "ikk-interpan.h"
//#define OPCODE_REMAP_TABLE_SIZE		20
static uint16_t opcodeReampTable[][2] =
{
	//FCC0, AA55
	{0xE0, 0x0001}, //write install code,
	{0xE1, 0x0003}, //write cmei
	{0xE2, 0x0005}, //write isn
	{0xE3, 0x0007}, //write mac
	{0xE6, 0x0002},
	{0xE7, 0x0004},
	{0xE8, 0x0006},
	{0xE9, 0x0008},
	{0xEA, 0x0009},
	{0xEB, 0x000A},
	//{0xF0, 0xED14},//????
	//{0xF1, 0xED04},//????
	//{0xF2, 0xED05},//??????
	{0xF3, 0x000C}, //??????
	{0xF4, 0x000D}, //??????
	{0xF5, 0x000E}, //??interPan??
	{0xF6, 0x000F}, //??interPan??
	{0xF7, 0x0010}, //??????
};
uint16_t kCmdGetMsgCrc16Value( uint8_t* msg, uint8_t len)
{
   uint16_t crc = 0xFFFF;
   uint16_t i, j = 0;

    for (i = 0; i < len; i++)
    {
        for (j = 0; j < 8; j++)
        {
            //????×a?? ADD BY YWQ
            uint8_t c15 = (uint8_t)((crc >> 15 & 1) == 1);
            uint8_t bit = (uint8_t)((msg[i] >> (7 - j) & 1) == 1);

            crc <<= 1;

            if (c15 ^ bit)
            {
                crc ^= 0x1021;
            }
        }
    }
    return crc;
}
/*	DESP: remap opcode, arg direction 0: FCC0->AA55  1:AA55->FCC0
 * 	Auth:
 * */
static uint16_t kCmdOpcodeRemap(uint16_t Opcode, uint8_t direction)
{
	for (uint8_t i = 0; i < (sizeof(opcodeReampTable)/(2*sizeof(uint16_t))); i++ ) {
		if (opcodeReampTable[i][0] == Opcode) {
			return opcodeReampTable[i][1];
		}
	}
	return 0xFFFF;
}

kk_err_t kCmdGeneralMsgPaser(UMsgNodeSt *pMsgNode, ComPortEm port, DataField_st *pDataOut)
{
	//UMsgNodeSt uMsgNode = {0};
	uint16_t length = 0;
	uint8_t control_field = 0;
	DataField_st data;
	DataField_st send_buf;
	uint8_t reply_control_field = 0;

	if( NULL == pMsgNode ) {
		return KET_ERR_INVALID_PARAM;
	}

#if 1 // Just for debug
	iKonkeAfSelfPrint("\r\n-- MSG INCOMING[%d]:\r\n", pMsgNode->length);
	iKonkeAfSelfPrintBuffer(pMsgNode->buffer, pMsgNode->length);
	iKonkeAfSelfPrint("\r\n--------------------\r\n");
#endif

	// check for parsable packets
	if( pMsgNode->length < 5 /* Minimum Packet Length */ ) {
		iKonkeAfSelfPrint("Err: Unparsable Packets!!\r\n");
		return KET_ERR_INVALID_PARAM;
	}
	//length(1) pid(4) ch(1) opcode(1) arg
	if (port == ECOM_PORT_FCC0) {
		length = (uint16_t)pMsgNode->length;
		//control_field = pMsgNode->buffer[4];
		data.seq = 0x00;
		data.u8Datalen = pMsgNode->buffer[0];
		data.u8ArgLen = data.u8Datalen - 6; // fcc0 - id (4) - ch(1) - opcode(1)
		data.u8ChannelID = pMsgNode->buffer[5];
		data.u16Opcode =   kCmdOpcodeRemap((uint16_t)(pMsgNode->buffer[6]), 0);

		if(data.u16Opcode == 0xFFFF) {
			return KET_ERR_INVALID_PARAM;
		}

		memcpy(data.u8ARG,&pMsgNode->buffer[7], data.u8ArgLen); //6 =  pid(4) + ch(1) + opcode(1)

		send_buf.seq = data.seq;
		send_buf.u8ChannelID = data.u8ChannelID;
		send_buf.u16Opcode = data.u16Opcode;
	} else {
		length = ((uint16_t)pMsgNode->buffer[2] << 8) | (uint16_t)(pMsgNode->buffer[3]);
		control_field = pMsgNode->buffer[4];

		data.seq = ((uint16_t)pMsgNode->buffer[5] << 8) | (uint16_t)(pMsgNode->buffer[6]);

		data.u8Datalen = pMsgNode->buffer[7];
		data.u8ArgLen = data.u8Datalen - 3; // aa55 - ch(1) - opcode(2)
		data.u8ChannelID = pMsgNode->buffer[8];
		data.u16Opcode = ((uint16_t)pMsgNode->buffer[9] << 8) |  (uint16_t)(pMsgNode->buffer[10]);
		memcpy(data.u8ARG,&pMsgNode->buffer[11],data.u8Datalen - 3);

		send_buf.seq = data.seq;
		send_buf.u8ChannelID = data.u8ChannelID;
		send_buf.u16Opcode = data.u16Opcode;
	}

	send_buf.u8Datalen = 0;
	iKonkeAfSelfPrint("opcode = %x%x\r\n",send_buf.u16Opcode>>8,(u8)send_buf.u16Opcode);
	iKonkeAfSelfPrint("channel = %x\r\n",data.u8ChannelID );
	switch(data.u16Opcode) {
		case (UART_MSG_QUERY_INFO_OPCODE):
		{
			reply_control_field = Z_TO_H_NO_ACK;
			send_buf.u8ARG[0] = ERR_OK;
			send_buf.u8ArgLen = 1;
			break;
		}
		case (UART_MSG_WRITE_INSTALL_CODE_OPCODE): // write install code
		{
			uint8_t buffer[16]= {0};

			//check install code length 20200725
			uint8_t length = data.u8ARG[0];
			if (length != 16) {//如果不是16位的数据就不做任何改变，只回复
				send_buf.u8ARG[0] = ERR_FORMAT;
				send_buf.u8ARG[1] = data.u8ARG[0];
				memcpy(&send_buf.u8ARG[2], &data.u8ARG[1], length);
				//send_buf.u8Datalen = data.u8ARG[0] + 5;
				send_buf.u8ArgLen = length + 1 + 1;
				break;
			}

			memcpy(buffer, &data.u8ARG[1], 16);
			INSTALL_CODE_TOKEN_SET(buffer,16);

			send_buf.u8ARG[0] = ERR_OK;
			send_buf.u8ARG[1] = data.u8ARG[0];
			memcpy(&send_buf.u8ARG[2], &data.u8ARG[1], length);
			send_buf.u8ArgLen = length + 1 + 1;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_READ_INSTALL_CODE_OPCODE): //read install code
		{
			uint8_t install_code_len = 0;
			send_buf.u8ARG[0] = ERR_OK;

			install_code_len = 16;
			memcpy(&send_buf.u8ARG[2], INSTALL_CODE_TOKEN_GET(), install_code_len);

			send_buf.u8ARG[1] = install_code_len;
			send_buf.u8ArgLen = install_code_len + 2; //  err(1) + codelen(1)
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_WRITE_CMEI_CODE_OPCODE): // write cmei
		{
			uint8_t buffer[33];
			uint8_t length = data.u8ARG[0];
			memset(buffer, 0, 33);

			if(length > 32) {
				send_buf.u8ARG[0] = ERR_NOT_EXPECTED;
				//send_buf.u8Datalen = 1 + 1 + 3;
			}else{
				send_buf.u8ARG[0] = ERR_OK;
				memcpy(buffer, &data.u8ARG[1], length);
				CMEI_TOKEN_SET(buffer,length);
			}
			memcpy(&send_buf.u8ARG[1], &data.u8ARG[0], data.u8ARG[0] + 1);
			send_buf.u8ArgLen = data.u8ARG[0] + 1 + 1;
			//send_buf.u8Datalen = data.u8ARG[0] + 4;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_READ_CMEI_CODE_OPCODE): //read cmei
		{
			uint8_t buffer[33];
			uint8_t length = 0;
			memset(buffer, 0, 33);

			uint8_t *data = CMEI_TOKEN_GET();
			iKonkeAfSelfPrint("len %x\r\n",data[0]);
			iKonkeAfSelfPrintBuffer(data+1,32);
			length = data[0];
			memcpy(buffer,data,length +1);

			if(length > 32) {
				send_buf.u8ARG[0] = ERR_NOT_EXPECTED;
				send_buf.u8ARG[1] = 0x00;
				send_buf.u8ArgLen = 2;
			} else {
				send_buf.u8ARG[0] = ERR_OK;
				memcpy(&send_buf.u8ARG[1], buffer, length + 1);
				send_buf.u8ArgLen = length + 1 + 1;
			}
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_WRITE_ISN_CODE_OPCODE): // write isn
		{
			uint8_t buffer[33];
			uint8_t length = data.u8ARG[0];
			memset(buffer, 0, 33);

			if(length > 32) {
				send_buf.u8ARG[0] = ERR_NOT_EXPECTED;
				//send_buf.u8Datalen = 1 + 1 + 3;
			}else{
				send_buf.u8ARG[0] = ERR_OK;
				memcpy(buffer, &data.u8ARG[1], length);
				ISN_TOKEN_SET(buffer,length);
			}
			memcpy(&send_buf.u8ARG[1], &data.u8ARG[0], data.u8ARG[0] + 1);
			send_buf.u8ArgLen = data.u8ARG[0] + 1 + 1;
			//send_buf.u8Datalen = data.u8ARG[0] + 4;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_READ_ISN_CODE_OPCODE): //read isn
		{
			uint8_t buffer[33];
			uint8_t length = 0;
			memset(buffer, 0, 33);

			uint8_t *data = ISN_TOKEN_GET();
			length = data[0];
			iKonkeAfSelfPrint("read ISN len %x\r\n",data[0]);
			iKonkeAfSelfPrintBuffer(data+1,32);
			memcpy(buffer,data,length +1);

			if(length > 32) {
				send_buf.u8ARG[0] = ERR_NOT_EXPECTED;
				send_buf.u8ARG[1] = 0x00;
				send_buf.u8ArgLen = 2;
			} else {
				send_buf.u8ARG[0] = ERR_OK;
				memcpy(&send_buf.u8ARG[1], buffer, length + 1);
				send_buf.u8ArgLen = length + 1 + 1;
			}
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_WRITE_MAC_CODE_OPCODE)://ok
		{
			uint8_t mac_length = 0x00;
			addrExt_t addr,local_addr;
			zb_getLocalExtAddr(local_addr);

			mac_length = data.u8ARG[0];
			if (mac_length != 8) {
				send_buf.u8ARG[0] = ERR_NOT_EXPECTED;
			} else {
				send_buf.u8ARG[0] = ERR_OK;
				memcpy(addr, &data.u8ARG[1], 8);
				SWAP_EUI64((uint8_t *)local_addr);
				if(memcmp(local_addr,addr,8) ){
					SWAP_EUI64((uint8_t *)addr);
					flash_erase(CFG_MAC_ADDRESS);
					flash_write(CFG_MAC_ADDRESS,8,addr);
				}
			}
			send_buf.u8ARG[1] = 8;
			memcpy(&send_buf.u8ARG[2], &data.u8ARG[1], 8);

			send_buf.u8ArgLen = 1 + 1 + 8;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_READ_MAC_CODE_OPCODE)://ok
		{
			addrExt_t addr;
			zb_getLocalExtAddr(addr);

			send_buf.u8ARG[0] = 0x00;
			send_buf.u8ARG[1] = 0x08;
			SWAP_EUI64((uint8_t *)addr);


			iKonkeAfSelfPrintBuffer(addr,8);

			memcpy(&send_buf.u8ARG[2], addr, 8);
			send_buf.u8ArgLen = 1 + 1 + 8;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_WRITE_MOUDLE_ID_OPCODE): // write modeid code
		{
			uint8_t buffer[33];
			uint8_t length = data.u8ARG[0];
			memset(buffer, 0, 33);

			if(length > 32) {
				send_buf.u8ARG[0] = ERR_NOT_EXPECTED;
				//send_buf.u8Datalen = 1 + 1 + 3;
			}else{
				send_buf.u8ARG[0] = ERR_OK;
				memcpy(buffer, &data.u8ARG[1], length);
				MODEL_ID_TOKEN_SET(buffer,length);
			}
			memcpy(&send_buf.u8ARG[1], &data.u8ARG[0], data.u8ARG[0] + 1);
			send_buf.u8ArgLen = data.u8ARG[0] + 1 + 1;
			//send_buf.u8Datalen = data.u8ARG[0] + 4;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_READ_MOUDLE_ID_OPCODE): //read modeid code
		{
			uint8_t buffer[33];
			uint8_t length = 0;
			memset(buffer, 0, 33);

			uint8_t *data = MODEL_ID_TOKEN_GET();
			if(All_Same_Data(&data[1],0xff,32))
			{
				status_t status;
				zclAttrInfo_t *attrInfo = ReadServerAttribute(1,0x0000,0x0005,&status);
				length = attrInfo->data[0];
				iKonkeAfSelfPrint("len %x\r\n",length);
				iKonkeAfSelfPrintBuffer( attrInfo->data+1,32);
				memcpy(buffer,attrInfo->data,length +1);
			}else{
				length = data[0];
				iKonkeAfSelfPrint("len %x\r\n",length);
				iKonkeAfSelfPrintBuffer(data+1,32);
				memcpy(buffer,data,length +1);
			}

			if(length > 32) {
				send_buf.u8ARG[0] = ERR_NOT_EXPECTED;
				send_buf.u8ARG[1] = 0x00;
				send_buf.u8ArgLen = 2;
				//send_buf.u8Datalen = 1 + 1 + 3;
			} else {
				send_buf.u8ARG[0] = ERR_OK;
				memcpy(&send_buf.u8ARG[1], buffer, length + 1);
				send_buf.u8ArgLen = length + 1 + 1;
				//send_buf.u8Datalen = length + 1 + 1 + 3;
			}

			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_READ_DEV_RSSI_OPCODE):
		{
			reply_control_field = Z_TO_H_NO_ACK;
			send_buf.u8ARG[0] = ERR_OK;
			send_buf.u8ARG[1] = kGetLastRssi();
			send_buf.u8ArgLen = 2;
			break;
		}
		case (UART_MSG_WRITE_AGING_TIME_OPCODE)://OK
		{
			uint16_t agingTime = 0;
			agingTime = UINT16_HL(data.u8ARG[0], data.u8ARG[1]);
			kSetAgingMaxTime(agingTime);
			send_buf.u8ARG[0] = ERR_OK;
			send_buf.u8ARG[1] = data.u8ARG[0];
			send_buf.u8ARG[2] = data.u8ARG[1];
			send_buf.u8ArgLen = 3;
			//send_buf.u8Datalen = 3 + 3;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}

		case (UART_MSG_READ_AGING_TIME_OPCODE)://OK
		{
			uint32_t agingTime = 0;
			agingTime = kGetAgingMaxTime();
			agingTime = agingTime / 1000 / 60;

			send_buf.u8ARG[0] = ERR_OK;
			send_buf.u8ARG[1] = H1_UINT32(agingTime);
			send_buf.u8ARG[2] = H0_UINT32(agingTime);
			send_buf.u8ArgLen = 3;
			//send_buf.u8Datalen = 3 + 3;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_WRITE_INTERPAN_PARA_OPCODE):
		{
			extern void GetInterpanPara(uint8_t *enable, uint8_t *channel, uint16_t *panId);
			uint8_t enable = 0;
			uint8_t channel = 0;
			uint16_t panId = 0;

			enable = data.u8ARG[0];
			channel = data.u8ARG[1];
			panId = UINT16_HL(data.u8ARG[2], data.u8ARG[3]);

			SetInterpanPara(channel,panId);
			GetInterpanPara(&enable, &channel, &panId);

			send_buf.u8ARG[0] = ERR_OK;
			send_buf.u8ARG[1] = 0xff;
			send_buf.u8ARG[2] = channel;
			send_buf.u8ARG[3] = HI_UINT16(panId);
			send_buf.u8ARG[4] = LO_UINT16(panId);
			send_buf.u8ArgLen = 5;

			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}

		case (UART_MSG_READ_INTERPAN_PARA_OPCODE):
		{
			extern void GetInterpanPara(uint8_t *enable, uint8_t *channel, uint16_t *panId);
			uint8_t enable = 0;
			uint8_t channel = 0;
			uint16_t panId = 0;

			GetInterpanPara(&enable, &channel, &panId);

			send_buf.u8ARG[0] = ERR_OK;
			send_buf.u8ARG[1] = enable;
			send_buf.u8ARG[2] = channel;
			send_buf.u8ARG[3] = HI_UINT16(panId);
			send_buf.u8ARG[4] = LO_UINT16(panId);
			send_buf.u8ArgLen = 5;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}

		//nwk  operation request
		case (UART_MSG_QUERY_NWK_STATUS_REQUEST_OPCODE)://ok
		{
			send_buf.u8ARG[0] = ERR_OK;
			send_buf.u8ARG[1] = kNwkGetCurrentStatus();
			send_buf.u8ArgLen = 2;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_JOIN_NWK_REQUEST_OPCODE)://ok
		{
			uint8_t duration = data.u8ARG[0];//unit:S

			if (zb_isDeviceJoinedNwk()){
				iKonkeAfSelfPrint("#####NWK Is Joined By Usart Duration(0x%2x)\r\n", duration);
				send_buf.u8ARG[0] = ERR_NOT_EXPECTED;
			}else {
				send_buf.u8ARG[0] = ERR_OK;
				kNwkFactoryReset(false);
				//steering timeout can be set
				iKonkeAfSelfPrint("#####Start Steering By Usart Duration(0x%2x)\r\n", duration);
				if(duration > 0)
					kNwkJoiningStart(duration * 1000, NULL);
			}
			send_buf.u8ARG[1] = duration;
			send_buf.u8ArgLen = 2;
			//send_buf.u8Datalen = 5;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		case (UART_MSG_LEAVE_NWK_REQUEST_OPCODE)://ok
		{
			if( zb_isDeviceJoinedNwk()){
				send_buf.u8ARG[0] = ERR_OK;
				kNwkFactoryReset(true);
			}else {
				send_buf.u8ARG[0] = ERR_NOT_EXPECTED;
			}
			send_buf.u8ArgLen = 1;
			//send_buf.u8Datalen = 4;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
		/*************************************/
		case (UART_MSG_ENTER_FACTORY_TEST_OPCODE):
		{
			uint8_t tmp_value = 0;

			if ((tmp_value & 0x01) == 0x01) {
				kSetSingleBoardValue(0x00);
			}

			if ((tmp_value & 0x02) == 0x02) {
				kSetFullDeviceValue(0x00);
			}

			if ((tmp_value & 0x04) == 0x04) {
				kSetAgingTestValue(0x00);
			}
			send_buf.u8ArgLen = 2;
			send_buf.u8ARG[0] = ERR_OK;
			reply_control_field = Z_TO_H_NO_ACK;
			send_buf.u8ARG[1] = kGetFactoryTestValueStatus();
			break;
		}
		default:
		{
			send_buf.u8ARG[0] = ERR_NOT_EXPECTED;
			send_buf.u8ArgLen = 1;
			//send_buf.u8Datalen = 4;
			reply_control_field = Z_TO_H_NO_ACK;
			break;
		}
	}
	memcpy(pDataOut, (uint8_t *)&send_buf, sizeof(DataField_st));

	if (send_buf.u8ArgLen == 0) { //if cmd exist, lengtg must > 0
		return KET_ERR_CMD_INVALID;
	} else {
		if (port == ECOM_PORT_FCC0) {
			pDataOut->u8Datalen = pDataOut->u8ArgLen;
		} else {
			pDataOut->u8Datalen = pDataOut->u8ArgLen + 3; //AA 55 (opcode(2), ch(1))
		}
		return KET_OK;
	}
}



uint8_t kCmdMsgDataSentByPort(uint8_t u8Control_Field, DataField_st data, bool isGetResult, ComPortEm port)
{
	uint8_t length = 0;
	UMsgNodeSt uMsgNode;

	memset((uint8_t*)&uMsgNode,0,sizeof(UMsgNodeSt));

	uMsgNode.buffer[length++] = 0xAA; //msg header
	uMsgNode.buffer[length++] = 0x55; //msg header

	uMsgNode.buffer[length++] = 0x00;	//msg length
	uMsgNode.buffer[length++] = 0x00;	//msg length
	uMsgNode.buffer[length++] = u8Control_Field;
//	seq++;
	uMsgNode.buffer[length++] = (uint8_t) (data.seq >> 8);
	uMsgNode.buffer[length++] = (uint8_t) data.seq;
	uMsgNode.buffer[length++] = data.u8Datalen;
	uMsgNode.buffer[length++] = data.u8ChannelID;
	uMsgNode.buffer[length++] = (uint8_t) (data.u16Opcode >> 8);
	uMsgNode.buffer[length++] = (uint8_t) data.u16Opcode;


	memmove(&uMsgNode.buffer[length], data.u8ARG, data.u8Datalen - 3);
	length = length + data.u8Datalen - 3;
	uMsgNode.buffer[2] = (uint8_t) ((length - 4) >> 8);
	uMsgNode.buffer[3] = (uint8_t) (length - 4);

	uint16_t crc = kCmdGetMsgCrc16Value(&uMsgNode.buffer[4], length - 4);
	uMsgNode.buffer[length++] = (uint8_t) (crc >> 8);
	uMsgNode.buffer[length++] = (uint8_t) (crc);

	uMsgNode.length = length;
	// setting for matcher content.

	uMsgNode.matcher[0] = uMsgNode.buffer[2];	//seq
	uMsgNode.matcher[1] = uMsgNode.buffer[3];
	uMsgNode.matcher_offset = 2;
	uMsgNode.matcher_n = 2;
	//zigbee send to host ack
	if (u8Control_Field == Z_TO_H_NO_ACK) {
		uMsgNode.sent_try = 0;
	} else if (u8Control_Field == Z_TO_H_WITH_ACK) {
		//zigbee send to host notify or control
		uMsgNode.sent_try = 1;
	}

	if (isGetResult) {
		uMsgNode.ack = uMsgNode.buffer;
	} else {
		uMsgNode.ack = NULL;
		uMsgNode.ack_length = 0;
	}
	iKonkeAfSelfPrint("\r\n-- kCmdMsgDataSentByPort[%d]:\r\n", uMsgNode.length);
	iKonkeAfSelfPrintBuffer(uMsgNode.buffer, uMsgNode.length);
	if (port == ECOM_PORT_UART) {
		return kUartMsgSent(&uMsgNode);
	}
	else if (port == ECOM_PORT_INTERPAN) {
		return kInterPanSend(&uMsgNode);
	}

	return 0;
}

