#include <stdio.h>
#include "kk_tsl_api.h"
#include "sqlite3.h"
#include "kk_log.h"
#include "kk_hal.h"
#include "kk_group_db.h"
#include "kk_dm_mng.h"
#include "cJSON.h"

 /*************************************************************
全局变量定义 
*************************************************************/
extern sqlite3 *g_kk_pDb;
/*************************************************************
函数实现 
*************************************************************/
typedef struct {
	void *mutex;
	sqlite3 *pDb;
} kk_group_ctx_t;

static kk_group_ctx_t s_kk_group_ctx = {NULL};
static kk_group_ctx_t *_kk_group_get_ctx(void)
{
	return &s_kk_group_ctx;
}
static void _kk_group_lock(void)
{
	kk_group_ctx_t *ctx = _kk_group_get_ctx();
	if (ctx->mutex) {
		HAL_MutexLock(ctx->mutex);
	}
}

static void _kk_group_unlock(void)
{
	kk_group_ctx_t *ctx = _kk_group_get_ctx();

	if (ctx->mutex) {
		HAL_MutexUnlock(ctx->mutex);
	}
}

static int kk_group_device_db_init(void)
{
	kk_group_ctx_t *ctx = _kk_group_get_ctx();
	char *pcErr;

	ctx->pDb = g_kk_pDb;

	INFO_PRINT("kk_group_db_init db Database opened\n");
	
	/* Create Mutex */
	ctx->mutex = HAL_MutexCreate();
	if (ctx->mutex == NULL) {
		return FAIL_RETURN;
	}
	_kk_group_lock();	
	const char *pPanelBindMotor = "CREATE TABLE IF NOT EXISTS GroupDevice( \
		groupId varchar(255), \
		epNum varchar(255), \
		deviceCode varchar(255), \
		parentDeviceCode varchar(255))";

	if (sqlite3_exec(ctx->pDb, pPanelBindMotor, NULL, NULL, &pcErr) != SQLITE_OK)
	{
		ERROR_PRINT("Error creating table (%s)\n", pcErr);
		sqlite3_free(pcErr);
		//eUtils_LockUnlock(&sLock);
		_kk_group_unlock();
		return FAIL_RETURN;
	}

	_kk_group_unlock();
	return SUCCESS_RETURN;
}

static int kk_group_info_db_init(void)
{
	kk_group_ctx_t *ctx = _kk_group_get_ctx();
	char *pcErr;

	ctx->pDb = g_kk_pDb;
	
	/* Create Mutex */
	ctx->mutex = HAL_MutexCreate();
	if (ctx->mutex == NULL) {
		return FAIL_RETURN;
	}
	_kk_group_lock();	
	const char *pPanelBindMotor = "CREATE TABLE IF NOT EXISTS GroupInfo( \
		groupId varchar(255), \
		groupName varchar(255), \
		ccuRoomId varchar(255))";


	if (sqlite3_exec(ctx->pDb, pPanelBindMotor, NULL, NULL, &pcErr) != SQLITE_OK)
	{
		ERROR_PRINT("Error creating table (%s)\n", pcErr);
		sqlite3_free(pcErr);
		//eUtils_LockUnlock(&sLock);
		_kk_group_unlock();
		return FAIL_RETURN;
	}

	_kk_group_unlock();
	return SUCCESS_RETURN;
}

int kk_group_db_init(void)
{
	INFO_PRINT("kk_group_db_init db Database opened\n");
	kk_group_info_db_init();
	kk_group_device_db_init();
	return 0;
}

static int kk_group_info_db_check(const char* groupId)
{
	int isExist = 0;
	sqlite3_stmt *stmt;
	const unsigned char *groupIdStr = NULL;
	kk_group_ctx_t *ctx = _kk_group_get_ctx();

	const char *searchCmd = "select * from GroupInfo;";	
	_kk_group_lock();
	sqlite3_prepare_v2(ctx->pDb, searchCmd, strlen(searchCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
		groupIdStr = sqlite3_column_text(stmt, GROUP_DEVICE_DB_ID);
		
		if(!strcmp(groupId,(const char *)groupIdStr))
		{
			isExist = 1;
			break;
		}
	}

	sqlite3_finalize(stmt);
	_kk_group_unlock();
	return isExist;
}


static int kk_group_device_db_check(const char* groupId,const char* epNum,const char* deviceCode)
{
	int isExist = 0;
	sqlite3_stmt *stmt;
	const unsigned char *groupIdStr = NULL;
	const unsigned char *epNumStr = NULL;
	const unsigned char *deviceCodeStr = NULL;
	kk_group_ctx_t *ctx = _kk_group_get_ctx();

	const char *searchCmd = "select * from GroupDevice;";	
	_kk_group_lock();
	sqlite3_prepare_v2(ctx->pDb, searchCmd, strlen(searchCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
		groupIdStr = sqlite3_column_text(stmt, GROUP_DEVICE_DB_ID);
		epNumStr = sqlite3_column_text(stmt, GROUP_DEVICE_DB_EPNUM);
		deviceCodeStr = sqlite3_column_text(stmt, GROUP_DEVICE_DB_DEVICECODE);

		if(!strcmp(groupId,(const char *)groupIdStr) && 
			!strcmp(epNum,(const char *)epNumStr) && 
			!strcmp(deviceCode,(const char *)deviceCodeStr))
		{
			isExist = 1;
			break;
		}
	}

	sqlite3_finalize(stmt);
	_kk_group_unlock();
	return isExist;
}

static int kk_group_info_db_insert(const char* groupId,const char* groupName,const char* ccuRoomId)
{
	int res = 0;
	kk_group_ctx_t *ctx = _kk_group_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	sqlite3_stmt *stmt;
	time_t rtime = 0;
	int count = 0;

	const char *insertCmd = "insert into GroupInfo (groupId, groupName,ccuRoomId) \
								values ('%s','%s','%s');";

	if(kk_group_info_db_check(groupId)){
		return SUCCESS_RETURN;
	}

	INFO_PRINT("[GroupInfo INSERT] groupId:%s,groupName:%s,ccuRoomId:%s\n",groupId,groupName,ccuRoomId);
	_kk_group_lock();
	sqlCmd = sqlite3_mprintf(insertCmd,groupId,groupName,ccuRoomId);
	res = sqlite3_exec(ctx->pDb, sqlCmd, NULL, NULL, &zErrMsg);
	if( res != SQLITE_OK ){
		ERROR_PRINT("SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
		sqlite3_free(sqlCmd);
		_kk_group_unlock(); 
		return FAIL_RETURN;
	}
	sqlite3_free(sqlCmd);
	_kk_group_unlock();

	return SUCCESS_RETURN;
}


static int kk_group_device_db_insert(const char* groupId,const char* epNum,const char* deviceCode,const char* parent)
{
	int res = 0;
	kk_group_ctx_t *ctx = _kk_group_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	sqlite3_stmt *stmt;
	time_t rtime = 0;
	int count = 0;

	const char *insertCmd = "insert into GroupDevice (groupId,epNum,deviceCode,parentDeviceCode) \
								values ('%s','%s','%s','%s');";
								
	if(kk_group_device_db_check(groupId,epNum,deviceCode)){
		INFO_PRINT("already exist.--->groupId:%s,epNum:%s,deviceCode:%s,parent:%s\n",groupId,epNum,deviceCode,parent);
		return SUCCESS_RETURN;
	}


	INFO_PRINT("[GroupDevice INSERT] groupId:%s,epNum:%s,deviceCode:%s,parent:%s\n",groupId,epNum,deviceCode,parent);
	_kk_group_lock();
	sqlCmd = sqlite3_mprintf(insertCmd,groupId,epNum,deviceCode,parent);	
	res = sqlite3_exec(ctx->pDb, sqlCmd, NULL, NULL, &zErrMsg);
	if( res != SQLITE_OK ){
		ERROR_PRINT("SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
		sqlite3_free(sqlCmd);
		_kk_group_unlock();	
		return FAIL_RETURN;
	}
	sqlite3_free(sqlCmd);
	_kk_group_unlock();
	return SUCCESS_RETURN;
}

int kk_group_db_insert(const char* groupId,const char* groupName,const char* ccuRoomId,const char* epNum,const char* deviceCode,const char* parent)
{
	kk_group_info_db_insert(groupId,groupName,ccuRoomId);
	return kk_group_device_db_insert(groupId,epNum,deviceCode,parent);
}

static int kk_group_info_db_delete(const char* groupId)
{
	const char *deleteCmd = "delete from GroupInfo where groupId = '%s' ;";
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	kk_group_ctx_t *ctx = _kk_group_get_ctx();

	_kk_group_lock();
	sqlCmd = sqlite3_mprintf(deleteCmd,groupId);

	INFO_PRINT("Table delete data sqlCmd:%s\n",sqlCmd);
	rc = sqlite3_exec(ctx->pDb, sqlCmd, NULL, NULL, &zErrMsg);
	if( rc != SQLITE_OK ){
		ERROR_PRINT("SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}else{
		INFO_PRINT("Table delete data successfully\n");
	}
	sqlite3_free(sqlCmd);
	_kk_group_unlock();
	return SUCCESS_RETURN;
}


static int kk_group_device_db_delete(const char* groupId)
{
	const char *deleteCmd = "delete from GroupDevice where groupId = '%s' ;";
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	kk_group_ctx_t *ctx = _kk_group_get_ctx();

	_kk_group_lock();
	sqlCmd = sqlite3_mprintf(deleteCmd,groupId);

	INFO_PRINT("Table delete data sqlCmd:%s\n",sqlCmd);
	rc = sqlite3_exec(ctx->pDb, sqlCmd, NULL, NULL, &zErrMsg);
	if( rc != SQLITE_OK ){
		ERROR_PRINT("SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}else{
		INFO_PRINT("Table delete data successfully\n");
	}
	sqlite3_free(sqlCmd);
	_kk_group_unlock();
	return SUCCESS_RETURN;
}

int kk_group_db_delete(const char* groupId)
{
	kk_group_info_db_delete(groupId);
	kk_group_device_db_delete(groupId);
	return SUCCESS_RETURN;
}




static cJSON *kk_group_device_db_query(const char *groupId,int isSync)
{
	sqlite3_stmt *stmt;
	char *sqlCmd = NULL;
	const unsigned char *epnum = NULL;
	const unsigned char *deviceCode = NULL;
	kk_group_ctx_t *ctx = _kk_group_get_ctx();
	
	cJSON *didListAry = cJSON_CreateArray();
	cJSON *didListItem = NULL;

	const char *searchCmd = "select * from GroupDevice where groupId = '%s'; ";
	sqlCmd = sqlite3_mprintf(searchCmd,groupId);
	INFO_PRINT("Table searchCmd:%s\n",sqlCmd);
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){ 
		epnum = sqlite3_column_text(stmt, GROUP_DEVICE_DB_EPNUM);
		deviceCode = sqlite3_column_text(stmt, GROUP_DEVICE_DB_DEVICECODE);
		INFO_PRINT("groupId=%s,epnum=%s,deviceCode=%s\n",groupId,epnum,deviceCode);
		
		didListItem = cJSON_CreateObject();
		if(isSync!=0){
			cJSON_AddNumberToObject(didListItem,"epNum",atoi((char*)epnum));
		}else{
			cJSON_AddStringToObject(didListItem,"epNum",(char*)epnum);
		}
		
		cJSON_AddStringToObject(didListItem,"deviceCode",(char*)deviceCode);
		cJSON_AddItemToArray(didListAry, didListItem);
	}
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);
	return didListAry;
}

cJSON *kk_group_db_query(int isSync)
{
   sqlite3_stmt *stmt;
   char *sqlCmd = NULL;
   const unsigned char *groupId = NULL;
   const unsigned char *groupName = NULL;
   const unsigned char *ccuRoomId = NULL;
   cJSON *groupListAry = cJSON_CreateArray();
   cJSON *groupListItem = NULL;
   cJSON *didListAry = NULL;
   

   kk_group_ctx_t *ctx = _kk_group_get_ctx();

   const char *searchCmd = "select * from GroupInfo"; 
   _kk_group_lock();
   sqlCmd = sqlite3_mprintf(searchCmd);
   INFO_PRINT("Table searchCmd:%s\n",sqlCmd);
   sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);


   while(sqlite3_step(stmt) == SQLITE_ROW){	
	   groupId = sqlite3_column_text(stmt, GROUP_INFO_DB_ID);
	   groupName = sqlite3_column_text(stmt, GROUP_INFO_DB_NAME);
	   ccuRoomId = sqlite3_column_text(stmt, GROUP_INFO_DB_CCUROOMID);
	   INFO_PRINT("groupId=%s,groupName=%s,ccuRoomId=%s\n",groupId,groupName,ccuRoomId);
		didListAry = kk_group_device_db_query((const char*)groupId,isSync);

		groupListItem = cJSON_CreateObject();
		cJSON_AddStringToObject(groupListItem,"groupId",(char*)groupId);
		cJSON_AddStringToObject(groupListItem,"groupName",(char*)groupName);
		if(isSync!=0){
			cJSON_AddStringToObject(groupListItem,"roomId",(char*)ccuRoomId);
		}else{
			cJSON_AddStringToObject(groupListItem,"ccuRoomId",(char*)ccuRoomId);
		}
		
		cJSON_AddItemToObject(groupListItem,"didList",didListAry);
		cJSON_AddItemToArray(groupListAry, groupListItem);
   }
   sqlite3_free(sqlCmd);
   sqlite3_finalize(stmt);
   _kk_group_unlock();
   return groupListAry;
}


cJSON *kk_group_device_db_exe_act(const char *groupId,int controlType,int propertyValue,char *parent)
{
	sqlite3_stmt *stmt;
	char *sqlCmd = NULL;
	const unsigned char *epnum = NULL;
	const unsigned char *deviceCode = NULL;
	const unsigned char *fatherDeviceCode = NULL;
	kk_group_ctx_t *ctx = _kk_group_get_ctx();
	
	cJSON *actionsAry = cJSON_CreateArray();
	cJSON *actionItem = NULL;

	const char *searchCmd = "select * from GroupDevice where groupId = '%s'; ";
	sqlCmd = sqlite3_mprintf(searchCmd,groupId);
	INFO_PRINT("Table searchCmd:%s\n",sqlCmd);
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){ 
		epnum = sqlite3_column_text(stmt, GROUP_DEVICE_DB_EPNUM);
		deviceCode = sqlite3_column_text(stmt, GROUP_DEVICE_DB_DEVICECODE);
		INFO_PRINT("groupId=%s,epnum=%s,deviceCode=%s\n",groupId,epnum,deviceCode);

		if(strlen(parent)==0){
			fatherDeviceCode = sqlite3_column_text(stmt, GROUP_DEVICE_DB_PARENT_DEVICECODE);
			sprintf(parent,"%s",fatherDeviceCode);
		}
		
		actionItem = cJSON_CreateObject();
		cJSON_AddStringToObject(actionItem,"type","action/thing/cluster");
		cJSON_AddStringToObject(actionItem,"epNum",(char*)epnum);
		cJSON_AddStringToObject(actionItem,"deviceCode",(char*)deviceCode);

		char buf[64];
		memset(buf,0,sizeof(buf));
		
		if(controlType==1){
			snprintf(buf,sizeof(buf),"PowerSwitch_%s",epnum);
		}else if(controlType==2){
			snprintf(buf,sizeof(buf),"Brightness_%s",epnum);
		}else if(controlType==3){
			snprintf(buf,sizeof(buf),"ColorTemperature_%s",epnum);
		}
		
		cJSON_AddStringToObject(actionItem,"propertyName",buf);
		cJSON_AddNumberToObject(actionItem,"propertyValue",propertyValue);
			
		cJSON_AddItemToArray(actionsAry, actionItem);
	}
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);
	return actionsAry;
}


int kk_group_device_db_find_parent(const char *groupId,char *parent)
{
	sqlite3_stmt *stmt;
	char *sqlCmd = NULL;
	const unsigned char *fatherDeviceCode = NULL;
	kk_group_ctx_t *ctx = _kk_group_get_ctx();
	

	const char *searchCmd = "select * from GroupDevice where groupId = '%s'; ";
	sqlCmd = sqlite3_mprintf(searchCmd,groupId);
	INFO_PRINT("Table searchCmd:%s\n",sqlCmd);
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){ 
		fatherDeviceCode = sqlite3_column_text(stmt, GROUP_DEVICE_DB_PARENT_DEVICECODE);
		sprintf(parent,"%s",fatherDeviceCode);
		break;
	}
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);
	return 0;
}




