#include <stdio.h>
#include "kk_tsl_api.h"
#include "kk_dm_mng.h"
#include "sqlite3.h"
#include "kk_log.h"
#include "kk_area_handle.h"
#include "kk_hal.h"
#include "id.h"

extern sqlite3 *g_kk_pDb;

static kk_dev_list_t *s_device_list = NULL;

typedef struct {
	void *mutex;
	int  roomNum;
	sqlite3 *pDb;	
} kk_area_ctx_t;



static kk_area_ctx_t s_kk_area_ctx = {NULL,0,NULL};

static kk_area_ctx_t *_kk_area_get_ctx(void)
{
	return &s_kk_area_ctx;
}
static void _kk_area_lock(void)
{
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	if (ctx->mutex) {
		HAL_MutexLock(ctx->mutex);
	}
}

static void _kk_area_unlock(void)
{
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	
	if (ctx->mutex) {
		HAL_MutexUnlock(ctx->mutex);
	}
}
static int _kk_area_db_init(void)
{
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	char *pcErr;

	//eUtils_LockLock(&sLock);
	_kk_area_lock();
	ctx->pDb = g_kk_pDb;

	INFO_PRINT("area db Database opened\n");

	const char *pAreaTable = "CREATE TABLE IF NOT EXISTS AreaInfo( \
		idx INTEGER PRIMARY KEY, \
		name varchar(256), \
		roomId varchar(256), \
		armingstate INTEGER)";

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

	const char *pAreaDevTable = "CREATE TABLE IF NOT EXISTS AreaDevInfo( \
		idx INTEGER PRIMARY KEY, \
		roomId varchar(256), \
		roomName varchar(256), \
		deviceCode varchar(33), \
		epNum varchar(10), \
		devName varchar(256))";

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

	_kk_area_unlock();
	return SUCCESS_RETURN;
}
int kk_area_init(void)
{
	int res = 0;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	set_workid(100);
	/* Create Mutex */
	ctx->mutex = HAL_MutexCreate();
	if (ctx->mutex == NULL) {
		return FAIL_RETURN;
	}

	res = _kk_area_db_init();
	if(res != SUCCESS_RETURN){
		ERROR_PRINT("[%s][%d]kk_area_init FAIL!!!\n",__FUNCTION__,__LINE__);
	}
	return SUCCESS_RETURN;
}
static int kk_check_room_exist(const char *roomId)
{
	int isExist = 0;
	sqlite3_stmt *stmt;
	char *proomId = NULL;

	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	const char *searchCmd = "select * from AreaInfo;";
	_kk_area_lock();
	
	sqlite3_prepare_v2(ctx->pDb, searchCmd, strlen(searchCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
		proomId = (char*)sqlite3_column_text(stmt, DB_ROOM_ID);

		if(!strcmp(proomId,roomId))
		{
			isExist = 1;
			break;
		}
	}

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

static int _kk_room_add(const char *name,const char *roomId)
{
	int res = 0;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;

	const char *insertCmd = "insert into AreaInfo (name, roomId) \
								values ('%s','%s');";						
	_kk_area_lock();
	ctx->roomNum++;

	sqlCmd = sqlite3_mprintf(insertCmd,name,roomId);	
	res = sqlite3_exec(ctx->pDb, sqlCmd, NULL, NULL, &zErrMsg);
	if( res != SQLITE_OK ){
		ERROR_PRINT("SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}else{
		//INFO_PRINT("sub device insert data successfully\n");
	}
	sqlite3_free(sqlCmd);
	_kk_area_unlock();
	return SUCCESS_RETURN;
}

static int _kk_room_update(const char *name,const char *roomId)
{
	int res = 0;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;

	sqlCmd = sqlite3_mprintf("UPDATE AreaInfo SET name='%s'  WHERE roomId= '%s'",name,roomId);	

	_kk_area_lock();

	res = sqlite3_exec(ctx->pDb, sqlCmd, NULL, NULL, &zErrMsg);
	if( res != SQLITE_OK ){
		ERROR_PRINT("SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}else{
		//INFO_PRINT("sub device insert data successfully\n");
	}
	sqlite3_free(sqlCmd);
	_kk_area_unlock();
	return SUCCESS_RETURN;
}
static int _kk_room_dev_update(const char *name,const char *roomId)
{
	int res = 0;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;

	sqlCmd = sqlite3_mprintf("UPDATE AreaDevInfo SET roomName='%s'  WHERE roomId= '%s'",name,roomId);	

	_kk_area_lock();
	
	res = sqlite3_exec(ctx->pDb, sqlCmd, NULL, NULL, &zErrMsg);
	if( res != SQLITE_OK ){
		ERROR_PRINT("SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}else{
		//INFO_PRINT("sub device insert data successfully\n");
	}
	sqlite3_free(sqlCmd);
	_kk_area_unlock();
	return SUCCESS_RETURN;
}
int kk_room_add(const char *name,const char *roomId)
{
	if(kk_check_room_exist(roomId)){
		printf("name=%s,room id=%s\n",name,roomId);
		_kk_room_dev_update(name,roomId);
		_kk_room_update(name,roomId);
		return 0;
	}else{
		return _kk_room_add(name,roomId);
	}

}
int kk_room_update_armingstate(int state,const char *roomid)
{
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();

	_kk_area_lock();
	sqlCmd = sqlite3_mprintf("UPDATE AreaInfo SET armingstate=%d  WHERE roomId= '%s'",state,roomid);	
	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 updata data successfully\n");
	}
	sqlite3_free(sqlCmd);
	_kk_area_unlock();
	return SUCCESS_RETURN;
}
int kk_room_delete(const char *roomId)
{
	int res = 0;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	const char *deleteCmd = "delete from AreaInfo where roomId = '%s';";

	_kk_area_lock();
	sqlCmd = sqlite3_mprintf(deleteCmd,roomId);	

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

static int _kk_check_dev_exist(const char* deviceCode,const char *epNum)
{
	int isExist = 0;
	sqlite3_stmt *stmt;
	char *pDeviceCode = NULL;
	char *pEpNum = NULL;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	const char *searchCmd = "select * from AreaDevInfo;";
	_kk_area_lock();
	
	sqlite3_prepare_v2(ctx->pDb, searchCmd, strlen(searchCmd), &stmt, NULL);
	//INFO_PRINT("total_column = %d\n", sqlite3_column_count(stmt));
	while(sqlite3_step(stmt) == SQLITE_ROW){
		pDeviceCode = (char*)sqlite3_column_text(stmt, DB_DEV_DEVICECODE);
		pEpNum = (char*)sqlite3_column_text(stmt, DB_DEV_EPNUM);
		if(!strcmp(deviceCode,pDeviceCode) && !strcmp(pEpNum,epNum))
		{
			isExist = 1;
			break;
		}
	}
	//INFO_PRINT("\n");
	sqlite3_finalize(stmt);
	_kk_area_unlock();
	return isExist;
}

int kk_room_dev_add(const char *roomId,const char *roomName,const char *deviceCode,const char *epNum,const char *devName)
{
	int res = 0;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;


	if(_kk_check_dev_exist(deviceCode,epNum)){
		sqlCmd = sqlite3_mprintf("UPDATE AreaDevInfo SET roomId='%s', devName='%s', devName='%s'\
					WHERE deviceCode= '%s' and epNum = '%s'",roomId,roomName,devName,deviceCode,epNum);	
	}
	else{
		const char *insertCmd = "insert into AreaDevInfo (roomId, roomName, deviceCode, epNum, devName) \
							values ('%s','%s','%s','%s','%s');";	
		sqlCmd = sqlite3_mprintf(insertCmd,roomId,roomName,deviceCode,epNum,devName);
	}
								
	_kk_area_lock();
	res = sqlite3_exec(ctx->pDb, sqlCmd, NULL, NULL, &zErrMsg);
	if( res != SQLITE_OK ){
		ERROR_PRINT("SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}else{
		//INFO_PRINT("sub device insert data successfully\n");
	}
	sqlite3_free(sqlCmd);
	_kk_area_unlock();
	return SUCCESS_RETURN;
}
int kk_room_reset_armingstate(void)
{
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();

	_kk_area_lock();
	sqlCmd = sqlite3_mprintf("UPDATE AreaInfo SET armingstate=%d ",0);	
	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 updata data successfully\n");
	}
	sqlite3_free(sqlCmd);
	_kk_area_unlock();
	return SUCCESS_RETURN;
}
int kk_get_room_armingstate(const char* roomId)
{
	sqlite3_stmt *stmt;
	int state = 0;
	char *sqlCmd = NULL;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	const char *searchCmd = "select * from AreaInfo where roomId = '%s';";
	_kk_area_lock();
	sqlCmd = sqlite3_mprintf(searchCmd,roomId);
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
		state = sqlite3_column_int(stmt, DB_ROOM_ARMING);
	}
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);
	_kk_area_unlock();
	return state;
}
int kk_get_roomId_by_deviceCode(const char* deviceCode,const char *epNum,char *roomId,int size)
{
	int isGet = 0;
	sqlite3_stmt *stmt;
	char *pDeviceCode = NULL;
	char *pEpNum = NULL;
	char *pRoomId = NULL;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	const char *searchCmd = "select * from AreaDevInfo;";
	_kk_area_lock();
	sqlite3_prepare_v2(ctx->pDb, searchCmd, strlen(searchCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
		pDeviceCode = (char*)sqlite3_column_text(stmt, DB_DEV_DEVICECODE);
		pEpNum = (char*)sqlite3_column_text(stmt, DB_DEV_EPNUM);
		if(!strcmp(deviceCode,pDeviceCode) && !strcmp(pEpNum,epNum))
		{
			pRoomId = (char*)sqlite3_column_text(stmt, DB_DEV_ROOM_ID);
			memset(roomId,0,size);
			snprintf(roomId,size,"%s",pRoomId);
			isGet = 1;
		}
	}
	//INFO_PRINT("\n");
	sqlite3_finalize(stmt);
	_kk_area_unlock();
	return isGet;
}
int kk_get_device_name(const char* deviceCode,const char *epNum,char *devName,int size)
{
	int isGet = 0;
	sqlite3_stmt *stmt;
	char *pDeviceCode = NULL;
	char *pEpNum = NULL;
	char *pDevName = NULL;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	const char *searchCmd = "select * from AreaDevInfo;";
	_kk_area_lock();
	
	sqlite3_prepare_v2(ctx->pDb, searchCmd, strlen(searchCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
		pDeviceCode = (char*)sqlite3_column_text(stmt, DB_DEV_DEVICECODE);
		pEpNum = (char*)sqlite3_column_text(stmt, DB_DEV_EPNUM);
		if(!strcmp(deviceCode,pDeviceCode) && !strcmp(pEpNum,epNum))
		{
			pDevName = (char*)sqlite3_column_text(stmt, DB_DEV_DEV_NAME);
			memset(devName,0,size);
			snprintf(devName,size,"%s",pDevName);
			isGet = 1;
		}
	}
	//INFO_PRINT("\n");
	sqlite3_finalize(stmt);
	_kk_area_unlock();
	return isGet;
}
int kk_get_device_roomInfo(const char* deviceCode,int epNum,char *roomName,char *roomId)
{
	int isGet = 0;
	char *sqlCmd = NULL;
	char *proomName = NULL;
	char *proomId = NULL;
	sqlite3_stmt *stmt;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	const char *searchCmd = "select * from AreaDevInfo where deviceCode = '%s' and epNum = '%d';";
	_kk_area_lock();
	sqlCmd = sqlite3_mprintf(searchCmd,deviceCode,epNum);
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
		proomName = (char*)sqlite3_column_text(stmt, DB_DEV_ROOM_NAME);
		proomId = (char*)sqlite3_column_text(stmt, DB_DEV_ROOM_ID);
		if(strlen(proomName) < 256){
			memcpy(roomName,proomName,strlen(proomName));
		}else{
			memcpy(roomName,proomName,255);
		}
		memcpy(roomId,proomId,strlen(proomId));
		isGet = 1;
	}
	//INFO_PRINT("\n");
	sqlite3_free(sqlCmd);
	sqlite3_finalize(stmt);
	_kk_area_unlock();
	return isGet;
}
int kk_room_dev_remove(const char *deviceCode,const char *epNum)
{
	int res = 0;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	const char *insertCmd = NULL;

	
	printf("deviceCode---->%s,%s\n",deviceCode,epNum);

	if(epNum == NULL){
		insertCmd = "delete from AreaDevInfo where deviceCode = '%s';";
	}
	else{
		insertCmd = "delete from AreaDevInfo where deviceCode = '%s' and epNum = '%s';";
	}

	_kk_area_lock();
	sqlCmd = sqlite3_mprintf(insertCmd,deviceCode,epNum);	
	res = sqlite3_exec(ctx->pDb, sqlCmd, NULL, NULL, &zErrMsg);
	if( res != SQLITE_OK ){
		ERROR_PRINT("SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}else{
		//INFO_PRINT("sub device insert data successfully\n");
	}
	sqlite3_free(sqlCmd);
	_kk_area_unlock();
	return SUCCESS_RETURN;
}

int kk_room_device_list_add(const char *deviceCode)
{
	//int len;
	kk_dev_list_t *ptr,*pre;
	
	ptr = pre = s_device_list;
	if(deviceCode == NULL){
		return FAIL_RETURN;
	}
	
	while(ptr!=NULL){
		pre = ptr;
		if(strcmp(ptr->deviceCode,deviceCode) == 0){
			return SUCCESS_RETURN;
		}
		ptr = ptr->next;
	}
	ptr = (kk_dev_list_t*)malloc(sizeof(kk_dev_list_t));
	memset(ptr,0,sizeof(kk_dev_list_t));
	memcpy(ptr->deviceCode,deviceCode,strlen(deviceCode));

	if(s_device_list==NULL){
		s_device_list = ptr;
	}else{
		pre->next = ptr;
	}

	return SUCCESS_RETURN;
}

cJSON *kk_get_roomIds_ary(void)
{
	int isExist = 0;
	sqlite3_stmt *stmt;
	char *proomId = NULL;
	int armingstate= 0;
	cJSON *roomIdsAry = cJSON_CreateArray();

	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	const char *searchCmd = "select * from AreaInfo;";
	_kk_area_lock();
	
	sqlite3_prepare_v2(ctx->pDb, searchCmd, strlen(searchCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
		armingstate = (int)sqlite3_column_int(stmt, DB_ROOM_ARMING);
		if(armingstate!=0){
			proomId = (char*)sqlite3_column_text(stmt, DB_ROOM_ID);
			cJSON_AddItemToArray(roomIdsAry,cJSON_CreateNumber(atoi(proomId)));
		}
		
	}

	sqlite3_finalize(stmt);
	_kk_area_unlock();
	
	return roomIdsAry;
}




kk_dev_list_t* kk_get_room_deviceCode(const char* roomId)
{
	sqlite3_stmt *stmt;
	char *sqlCmd = NULL;
	kk_area_ctx_t *ctx = _kk_area_get_ctx();
	const char *searchCmd = "select * from AreaDevInfo where epNum = 1;";	
	_kk_area_lock();
	sqlCmd = sqlite3_mprintf(searchCmd,roomId);	
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	//INFO_PRINT("total_column = %d\n", sqlite3_column_count(stmt));
	while(sqlite3_step(stmt) == SQLITE_ROW){
		if(strcmp((char*)sqlite3_column_text(stmt, DB_DEV_ROOM_ID),roomId) == 0){
			kk_room_device_list_add((char*)sqlite3_column_text(stmt, DB_DEV_DEVICECODE));
		}
	}
	sqlite3_finalize(stmt);
	_kk_area_unlock();
	return s_device_list;
}
void kk_free_room_dev_list(void)
{
	kk_dev_list_t *ptr = s_device_list;
	kk_dev_list_t *ptmp = NULL;
	while(ptr != NULL){
		ptmp = ptr->next;
		free(ptr);
		ptr = NULL;
		ptr = ptmp;
	}
	s_device_list = NULL;
}



