#include "kk_device_table_db.h"
#include "sqlite3.h"
#include "kk_ncp_queue.h"

void kk_mac_conver(EmberEUI64 mac,char* macString)
{
	sprintf(macString, "%02X%02X%02X%02X%02X%02X%02X%02X",
			mac[7],
			mac[6],
			mac[5],
			mac[4],
			mac[3],
			mac[2],
			mac[1],
			mac[0]);
}
void kk_macString_conver_mac(EmberEUI64 mac,char* macString)
{
	sscanf(macString, "%02X%02X%02X%02X%02X%02X%02X%02X",
			&mac[7],
			&mac[6],
			&mac[5],
			&mac[4],
			&mac[3],
			&mac[2],
			&mac[1],
			&mac[0]);
}


static kk_device_table_s *kk_zb_device_table=NULL;


kk_device_table_s *kk_get_device_table_pointer(void)
{
	return kk_zb_device_table;
}



void kk_print_device_table(void)
{
	int i,cnt = 0;
	kk_device_table_s *ptr = kk_zb_device_table;
	emberAfAppPrint("\n-----------kk device table-----------\n");

	while(ptr!=NULL){
		emberAfAppPrint("\n%d:",++cnt);
		emberAfAppPrint("\nMAC = " );
		emberAfPrintBigEndianEui64(ptr->mac);
		emberAfAppPrint("\nproductCode = %s",(ptr->productCode!=NULL)?ptr->productCode:"unknow");
		emberAfAppPrint("\nidentifyCnt = %d",ptr->identifyCnt);
		
		ptr = ptr->next;
	}
}
static kk_device_table_s *kk_device_table_create()
{
	kk_device_table_s *node = (kk_device_table_s *)malloc(sizeof(kk_device_table_s));

	if(node==NULL){
		return node;
	}

	MEMSET(node, 0, sizeof(kk_device_table_s));
	MEMSET(&node->manage, 0, sizeof(SubDevManage_s));

	return node;
}

static kk_device_table_s *kk_device_table_find_next_empty()
{
	kk_device_table_s *ptr = kk_zb_device_table;

	if(ptr==NULL) return ptr;
	
	while(ptr!=NULL){
		if(ptr->next==NULL) return ptr;
		ptr = ptr->next;
	}
}

static void kk_device_fill(kk_device_table_s *ptr,EmberEUI64 mac,EmberNodeId nodeId,char *productCode,uint16_t deviceId)
{
	memcpy(ptr->mac,mac,sizeof(EmberEUI64));
	ptr->nodeId = nodeId;
	ptr->deviceId = deviceId;

	ptr->identifyCnt = KK_MAX_READ_MODLE_ID_COUNT;
	if(productCode!=NULL){
		memcpy(ptr->productCode,productCode,strlen(productCode));
	}
	
}

char * kk_device_find_productCode(EmberEUI64 mac)
{
	kk_device_table_s *dev;
	dev = kk_device_find_by_mac(mac);
	
	if(dev==NULL) return NULL;

	return dev->productCode;
}

kk_device_table_s * kk_device_find_by_mac(EmberEUI64 mac)
{
	kk_device_table_s *ptr = kk_zb_device_table;
	
	while(ptr!=NULL){
		if(MEMCOMPARE(ptr->mac,mac,sizeof(EmberEUI64))==0){
			return ptr;
		}
		ptr = ptr->next;
	}
	return NULL;
}
kk_device_table_s * kk_device_find_by_node(EmberNodeId node)
{
	kk_device_table_s *ptr = kk_zb_device_table;
	
	while(ptr!=NULL){
		if(ptr->nodeId==node){
			return ptr;
		}
		ptr = ptr->next;
	}
	return NULL;
}



void kk_device_table_add(EmberEUI64 mac,EmberNodeId nodeId,const char *productCode,uint16_t deviceId)
{
	kk_device_table_s *ptr = kk_zb_device_table;
	kk_device_table_s *newNode;

	emberAfDebugPrintln("\n--------------------kk device table add--------------------\n");
	emberAfDebugPrint("mac:");
	emberAfPrintBigEndianEui64(mac);
	
	if(kk_device_find_by_node(nodeId)!=NULL){ 
		emberAfDebugPrintln(" is already in device table!!!");
		kk_print_device_table();
		return ;
	}
	
	emberAfAppPrintln(",nodeId:0x%04x,productCode:%s,device id:0x%04x",nodeId,(productCode==NULL)?"nukown":productCode,deviceId);

	if(ptr==NULL){
		kk_zb_device_table = kk_device_table_create();
		ptr = kk_zb_device_table;		
		
		kk_device_fill(ptr,mac,nodeId,productCode,deviceId);
		
		return;
	}

	ptr = kk_device_table_find_next_empty();
	if(ptr!=NULL){
		newNode = kk_device_table_create();
		
		if(newNode!=NULL){
			ptr->next = newNode;
			kk_device_fill(newNode,mac,nodeId,productCode,deviceId);
		}
	}else{
		emberAfCorePrintln("[KK device table] fatal!!!%s",__LINE__);
	}
}

void kk_device_joined(EmberNodeId node)
{
	EmberEUI64 mac;
	uint16_t deviceId;
	uint16_t deviceTableIndex;
	EmberAfPluginDeviceTableEntry*devPtr;
	
	UTIL_LOG_INFO("\n********************kk device joined********************\n");
	
	if(emberAfDeviceTableGetEui64FromNodeId(node,mac)==true){
		deviceTableIndex = emberAfDeviceTableGetIndexFromNodeId(node);
		if(deviceTableIndex!=0xffff){
			devPtr = emberAfDeviceTablePointer();
			kk_add_device_to_table(mac,node,devPtr[deviceTableIndex].deviceId);
		}
	}else{
		emberAfDebugPrintln("[not find 111]");
		if(emberLookupEui64ByNodeId(node,mac)==EMBER_SUCCESS){
			deviceTableIndex = emberAfDeviceTableGetIndexFromNodeId(node);
			if(deviceTableIndex!=0xffff){
				devPtr = emberAfDeviceTablePointer();
				kk_add_device_to_table(mac,node,devPtr[deviceTableIndex].deviceId);
			}
		}else{
			emberAfDebugPrintln("[not find 222]");
		}
	}
}

void kk_device_table_delete(EmberEUI64 mac)
{
	kk_device_table_s *ptr = kk_zb_device_table;
	kk_device_table_s *ptr_temp = kk_zb_device_table;
	if(ptr==NULL){
		emberAfCorePrintln("[KK device table] is empty!!!");
		return ;
	}
	while(ptr!=NULL){
		if(MEMCOMPARE(ptr->mac,mac,sizeof(EmberEUI64))==0){
			if(ptr->next==NULL){
				free(ptr);
				ptr_temp->next = NULL;
				emberAfCorePrintln("[KK device table]delete,now is empty !!!");
				return ;
			}else{
				if(ptr==kk_zb_device_table){
					kk_zb_device_table = ptr->next;
					emberAfCorePrintln("[KK device table] delete list header");
			
					free(ptr);
					return ;
				}else{
					ptr_temp->next = ptr->next;
				
					free(ptr);
					emberAfCorePrintln("[KK device table] delete ");
					return ;
				}
			}
		}
		ptr_temp = ptr;
		ptr = ptr->next;
	}
}


/*
void kk_device_table_save(void)
{
	FILE *fp;
	int i;
	uint16_t pLen;
	kk_device_table_s *ptr = kk_zb_device_table;

	fp = fopen("kk_devices.txt", "w");
	
	while(ptr!=NULL){
		for (i = 0; i < 8; i++) {
			fprintf(fp, "%x ", ptr->mac[i]);
		}
		
		fprintf(fp, "%x ",ptr->nodeId);
		fprintf(fp, "%x ",ptr->deviceId);

		if(ptr->productCode==NULL){
			pLen = 0;
		}else{
			pLen = strlen(ptr->productCode);
		}
		
		fprintf(fp,"%x ",pLen);
		for(i=0;i<pLen;i++){
			fprintf(fp,"%x ",ptr->productCode[i]);
		}
		ptr = ptr->next;
	}

	fclose(fp);
}

void kk_device_table_load(void)
{
	UTIL_LOG_INFO("\n********************kk load device table********************\n");
	
	FILE *fp;
	int i;
	EmberEUI64 mac;
	uint16_t nodeId;
	uint16_t deviceId;
	uint16_t len;
	char pCode[33];

	fp = fopen("kk_devices.txt", "r");
	
	if(fp==NULL) return;
	while(feof(fp) == false){
		emberAfDebugPrintln("111");
		for (i = 0; i< 8; i++) {
			fscanf(fp, "%x ", &mac[i]);
		}
		emberAfDebugPrintln("222");
		fscanf(fp, "%x", &nodeId);
		fscanf(fp, "%x ", &deviceId);
	

		emberAfDebugPrintln("len=%d",len);
		fscanf(fp, "%x", &len);

		for(i=0;i<len;i++){
			fscanf(fp,"%x ",&pCode[i]);
		}
		pCode[i] = 0;
		if(len==0){
			kk_device_table_add(mac,nodeId,NULL,deviceId);
		}else{
			kk_device_table_add(mac,nodeId,pCode,deviceId);
		}
		
	}
	fclose(fp);
	//kk_device_table_add(EmberEUI64 mac,EmberNodeId nodeId,uint8_t epNum,uint8_t* epVal,char *productCode)
	//kk_print_device_table();
}
void kk_device_table_clear(void)
{
	kk_device_table_s *ptr = kk_zb_device_table;
	kk_device_table_s *ptr_temp = kk_zb_device_table;
	if(ptr==NULL){
		return ;
	}
	while(ptr!=NULL){
		if(ptr->next==NULL){
			free(ptr);
			kk_zb_device_table = NULL;
			return ;
		}else{
			if(ptr==kk_zb_device_table){
				kk_zb_device_table = ptr->next;
				free(ptr);
				return ;
			}else{
				ptr_temp->next = ptr->next;
			
				free(ptr);
				return ;
			}
		}
		ptr_temp = ptr;
		ptr = ptr->next;
	}
	kk_device_table_save();
}
*/
//************************************************************************

char *insertCmd="insert into "KK_DEVICE_DB_TABLE" values('%s','%d','%d','%s');";
char *createCmd="create table "KK_DEVICE_DB_TABLE" (MAC text PRIMARY KEY, node integer, deviceId integer, productCode text);";
char *deleteCmd="delete from "KK_DEVICE_DB_TABLE" where MAC = '%s'";
char *searchCmd = "select * from "KK_DEVICE_DB_TABLE";";







void kk_device_db_init(void)
{
	sqlite3 *db = NULL;
	char *errmsg = NULL;

	int ret = sqlite3_open(KK_DEVICE_DB_FILE, &db);
	if(ret){
		emberAfDebugPrintln("can not open database.\n");
		return ;
	}else{
		emberAfDebugPrintln("open database succsee.\n");
		ret =  sqlite3_exec(db,createCmd, NULL, NULL, &errmsg);
		if(ret!=0){
			emberAfDebugPrintln("create fail,%s\n",errmsg);
		}
	}
	sqlite3_close(db);
}

void kk_device_db_insert(EmberEUI64 mac,EmberNodeId nodeId,uint16_t deviceId,char* productCode)
{
	sqlite3 *db = NULL;
	char *errmsg = NULL;
	char *sqlCmd;
	int ret = sqlite3_open(KK_DEVICE_DB_FILE, &db);
	char macString[17] = {0};
	if(ret==0){
		kk_mac_conver(mac,macString);
		sqlCmd = sqlite3_mprintf(insertCmd,macString,nodeId,deviceId,productCode);

		emberAfDebugPrintln("sqlCmd=%s",sqlCmd);
		if(sqlite3_exec(db,sqlCmd, NULL, NULL, &errmsg)!=0){
			emberAfDebugPrintln("insert fail,%s\n",errmsg);
			kk_device_db_init();
			if(sqlite3_exec(db,sqlCmd, NULL, NULL, &errmsg)!=0){
				emberAfDebugPrintln("insert fail again,%s\n",errmsg);
			}
		}
	}else{
		emberAfDebugPrintln("open database fail,%s\n",__LINE__);
		return ;
	}
	
	sqlite3_close(db);
}

void kk_device_db_delete(EmberEUI64 mac)
{
	sqlite3 *db = NULL;
	char *errmsg = NULL;
	char *sqlCmd;
	int ret = sqlite3_open(KK_DEVICE_DB_FILE, &db);
	char macString[17] = {0};
	if(ret==0){
		kk_mac_conver(mac,macString);
		sqlCmd = sqlite3_mprintf(deleteCmd,macString);
		emberAfDebugPrintln("sqlCmd=%s",sqlCmd);
		if(sqlite3_exec(db,sqlCmd, NULL, NULL, &errmsg)!=0){
			emberAfDebugPrintln("delete fail,%s\n",errmsg);
		}
	}else{
		emberAfDebugPrintln("open database fail,%s\n",__LINE__);
		return ;
	}
	
	sqlite3_close(db);
}




void kk_device_db_update(EmberEUI64 mac,EmberNodeId nodeId,uint16_t deviceId,char* productCode)
{
	kk_device_db_delete(mac);
	kk_device_db_insert(mac,nodeId,deviceId,productCode);
}
bool kk_device_db_check(EmberEUI64 mac)
{
	sqlite3_stmt *stmt;
	sqlite3 *db = NULL;
	char *errmsg = NULL;
	char *sqlCmd;
	char *eui64 = NULL;
	int ret = sqlite3_open(KK_DEVICE_DB_FILE, &db);
	char macString[17] = {0};
	bool flag = false;
	if(ret==0){
		kk_mac_conver(mac,macString);
		sqlite3_prepare_v2(db, searchCmd, strlen(searchCmd), &stmt, NULL);
		while(sqlite3_step(stmt) == SQLITE_ROW){
			eui64 = sqlite3_column_text(stmt, 0);
			if(!strcmp(eui64,macString)){
				flag = true;
				break;
			}
		}
		sqlite3_finalize(stmt);
		if(flag==true){
			emberAfDebugPrintln("find,%s\n",macString);
		}else{
			emberAfDebugPrintln("not find,%s\n",macString);
		}
	}else{
		emberAfDebugPrintln("open database fail,%s\n",__LINE__);
		return false;
	}
	
	sqlite3_close(db);
	return flag;
}

void kk_device_db_load()
{
	sqlite3_stmt *stmt;
	sqlite3 *db = NULL;
	char *errmsg = NULL;
	char *macString = NULL;
	EmberEUI64 mac;
	EmberNodeId nodeId;
	char *productCode;
	uint16_t deviceId;
	UTIL_LOG_INFO("\n********************kk device table load********************\n");
	int ret = sqlite3_open(KK_DEVICE_DB_FILE, &db);

	sqlite3_prepare_v2(db, searchCmd, strlen(searchCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
		macString = sqlite3_column_text(stmt, 0);
		//kk_macString_conver_mac(mac,macString); //todo: why???
		rpc_get_mac(macString,mac);
		nodeId = sqlite3_column_int(stmt, 1);
		deviceId = sqlite3_column_int(stmt, 2);
		productCode = sqlite3_column_text(stmt, 3);
		if(productCode==""){
			productCode = NULL;
			emberAfDebugPrintln("unkown product code");
		}
		kk_device_table_add(mac,nodeId,productCode,deviceId);
	}
	sqlite3_finalize(stmt);
	sqlite3_close(db);

}
int kk_device_db_get_num()
{
	sqlite3 *db = NULL;
	char *errmsg = NULL;
	int nRow = 0; 
	int nColumn = 0;
	char **dbResult; 

	sqlite3_open(KK_DEVICE_DB_FILE, &db);

	sqlite3_get_table( db , searchCmd, &dbResult, &nRow, &nColumn, &errmsg );
	emberAfDebugPrintln("nRow=%d,nColumn=%d,errmsg=%s",nRow,nColumn,errmsg);
	
	sqlite3_close(db);
}



void kk_device_config_load_from_db(void)
{
	kk_device_table_s *ptr = kk_zb_device_table;

	while(ptr!=NULL){
		if(ptr->productCode!=NULL&&strlen(ptr->productCode)!=0){
			kk_device_config_map_add(ptr->productCode);
		}
		ptr = ptr->next;
	}

}

void emberAfPluginDeviceTableInitialized(void)
{
	kk_device_db_load();
	kk_print_device_table();

	kk_load_dev_map_table();
	kk_device_map_print();
	kk_device_config_load_from_db();
	ncp_queue_init();
}

void test_123(int val)
{
	uint8_t buffer[258];
	int ix =1;
	kk_dev_config_item_extra_data * mode = kk_find_extra_data_by_productCode("3073","Mode");
	while(mode!=NULL){
		if(ix++==10){
			emberAfCorePrintln("~~~~~~~~~~~data_%d~~~~~~~~~~",val,mode->len);
			buffer[0] = mode->len;
			memcpy(&buffer[1],mode->data,buffer[0] - 1);
			
			emberAfCorePrintBuffer(buffer,buffer[0]+1,true);
			emberAfCorePrintln("\n");
			kk_private_protocol(0xb350,buffer[0]+1,buffer);
			break;
		}
		mode = mode->next;
	}
}

