/************************************************************
*版权所有 （C）2020，公司（或个人）名称
*
*文件名称： kk_scene.db.c
*内容摘要： 场景功能数据库处理
*其他说明： 
*当前版本：  
*************************************************************/
 
/*************************************************************
头文件引用 
*************************************************************/
	
#include <stdio.h>
#include "kk_tsl_api.h"
#include "sqlite3.h"
#include "kk_log.h"
#include "kk_scene_handle.h"
#include "kk_scene_db.h"


 /*************************************************************
全局变量定义 
*************************************************************/
extern sqlite3 *g_kk_pDb;

/*************************************************************
函数实现 
*************************************************************/





int kk_scene_db_init(void)
{
    kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
    char *pcErr;
	/************************************************************
	*功能描述： 场景数据库初始化
	*输入参数： 无
	*输出参数： 无
	*返 回 值：  0：成功；其他：失败
	*其他说明：
	*************************************************************/

    //eUtils_LockLock(&sLock);
    _kk_scene_lock();
    ctx->pDb = g_kk_pDb;
   
    INFO_PRINT("scene db Database opened\n");
    
	const char *pSceneTable = "CREATE TABLE IF NOT EXISTS SceneInfo( \
		name varchar(255), \
		sceneType INTEGER, \
		enable INTEGER, \
		sceneId varchar(255) UNIQUE)";

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

	const char *pSceneTriggerTable = "CREATE TABLE IF NOT EXISTS SceneTriggerInfo( \
		type varchar(255), \
		deviceCode varchar(255), \
		epNum INTEGER, \
		propertyName varchar(255), \
		compareType varchar(255), \
		compareValue varchar(255), \
		sceneId varchar(255), \
		isAnd INTEGER)";


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

	const char *pSceneConditionTable = "CREATE TABLE IF NOT EXISTS SceneConditionInfo( \
		type varchar(255), \
		startTime INTEGER, \
		endTime INTEGER, \
		crossDay INTEGER, \
		repeat_days INTEGER, \
		sceneId varchar(255))";


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

	const char *pSceneActionTable = "CREATE TABLE IF NOT EXISTS SceneActionInfo( \
		type varchar(255), \
		deviceCode varchar(255), \
		epNum INTEGER, \
		propertyName varchar(255), \
		propertyValue varchar(255), \
		delay INTEGER, \
		sceneId varchar(255),\
		gwdeviceCode varchar(255))";


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

	const char *pSceneTimerTable = "CREATE TABLE IF NOT EXISTS SceneTimerInfo( \
		week INTEGER, \
		time INTEGER, \
		sceneId varchar(255))";

    if (sqlite3_exec(ctx->pDb, pSceneTimerTable, NULL, NULL, &pcErr) != SQLITE_OK)
    {
        ERROR_PRINT("Error creating table (%s)\n", pcErr);
        sqlite3_free(pcErr);
        //eUtils_LockUnlock(&sLock);
        _kk_scene_unlock();
        return FAIL_RETURN;
    }
	/*内嵌场景关联表*/
	const char *pSceneEmbedTable = "CREATE TABLE IF NOT EXISTS SceneEmbedInfo( \
		delay INTEGER, \
		executeSceneId varchar(255), \
		sceneId varchar(255))";

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

    _kk_scene_unlock();
    return SUCCESS_RETURN;
}
/************************************************************
*功能描述： 场景使能位更新
*输入参数： sceneId：场景Id
          enable: 1,使能；0，不使能
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_scene_update_scene_enable(int enable,const char *sceneId)
{
	char *sqlCmd = NULL;
	int len =0;
	int rc = 0;
	char *zErrMsg = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();

	//_kk_subDb_lock();
	sqlCmd = sqlite3_mprintf("UPDATE SceneInfo SET enable=%d  WHERE sceneId= '%s'",enable,sceneId);	
	INFO_PRINT("kk_scene_update_scene_enable,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 updata data successfully\n");
	}
    sqlite3_free(sqlCmd);
	//_kk_subDb_unlock();
	return SUCCESS_RETURN;
}

/************************************************************
*功能描述： 添加场景信息到数据库
*输入参数： name：场景名称
          enable: 1,使能；0，不使能
          sceneType：场景类型
          sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_scene_insert_scene_info(const char* name,const char* sceneType,const char* enable,const char* sceneId)
{
	int res = 0;
    kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;

	const char *insertCmd = "insert into SceneInfo (name, sceneType,enable,sceneId) \
								values ('%s','%d','%d','%s');";	
								
	_kk_scene_lock();
	sqlCmd = sqlite3_mprintf(insertCmd,name,sceneType,enable,sceneId);	
	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_scene_unlock();	
	   return FAIL_RETURN;
	}
	
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	return SUCCESS_RETURN;

}
/************************************************************
*功能描述： 检查场景触发是否已经存在
*输入参数： deviceCode：设备deviceCode
          epNum: 设备路数
          propertyName：属性名称
          compareType：比对符号
          compareValue：value值
          sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

static int kk_scene_check_trigger_exist(const char* deviceCode,int epNum,const char* propertyName,
												const char* compareType,const char* compareValue,const char* sceneId)
{
	int res = 0;
    kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	sqlite3_stmt *stmt; 
	int dbepNum = 0;
	char *dbcompareValue =NULL;
	char *dbcompareType =NULL;
	char *dbsceneId =NULL;

	const char *selectCmd = "select * from SceneTriggerInfo WHERE deviceCode = '%s' and propertyName = '%s';";	
								
	_kk_scene_lock();
	sqlCmd = sqlite3_mprintf(selectCmd,deviceCode,propertyName);	
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
	    dbepNum = sqlite3_column_int(stmt, DB_SCENETRIGGER_EPNUM);
		dbcompareType = sqlite3_column_text(stmt, DB_SCENETRIGGER_COMPARETYPE);
		dbcompareValue = sqlite3_column_text(stmt, DB_SCENETRIGGER_COMPAREVALUE);
		dbsceneId = sqlite3_column_text(stmt, DB_SCENETRIGGER_SCENEID);
		if((epNum == dbepNum) && (!strcmp(dbcompareType,compareType)) && \
				(!strcmp(compareValue,compareValue)) && (!strcmp(dbsceneId,sceneId))){
			res =  1;
			INFO_PRINT("kk_scene_check_trigger_exist!!!\n");
			break;
		}
		
	}
	sqlite3_finalize(stmt);
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	
	return res;

}

/************************************************************
*功能描述： 添加场景触发信息到数据库
*输入参数： type：类型
          deviceCode：设备deviceCode
          epNum: 设备路数
          propertyName：属性名称
          compareType：比对符号
          compareValue：value值
          sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_scene_insert_scene_trigger(const char* type,const char* deviceCode,int epNum,const char* propertyName,
												const char* compareType,const char* compareValue,const char* sceneId,int isAnd)
{
	int res = 0;
    kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	/*此触发条件已经存在*/
	if(kk_scene_check_trigger_exist(deviceCode,epNum,propertyName,compareType,compareValue,sceneId)){
		return SUCCESS_RETURN;
	}
	const char *insertCmd = "insert into SceneTriggerInfo (type, deviceCode,epNum,propertyName,compareType,compareValue,sceneId,isAnd) \
								values ('%s','%s','%d','%s','%s','%s','%s','%d');";	
								
	_kk_scene_lock();
	sqlCmd = sqlite3_mprintf(insertCmd,type,deviceCode,epNum,propertyName,compareType,compareValue,sceneId,isAnd);	
	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_scene_unlock();	
	   return FAIL_RETURN;	
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	
	return SUCCESS_RETURN;

}
/************************************************************
*功能描述： 添加场景时间触发条件到数据库
*输入参数： type：类型
		  startTime：开始时间
		  endTime：结束时间
		  crossDay：是否跨天
		  repeat_days: 重复星期
		  sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_scene_insert_scene_condition(const char* type,int startTime,int endTime,int crossDay,
												char repeat_days,const char* sceneId)
{
	int res = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;

	const char *insertCmd = "insert into SceneConditionInfo (type, startTime,endTime,crossDay,repeat_days,sceneId) \
								values ('%s','%d','%d','%d','%d','%s');";	
								
	_kk_scene_lock();
	sqlCmd = sqlite3_mprintf(insertCmd,type,startTime,endTime,crossDay,repeat_days,sceneId);	
	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_scene_unlock();	
	   return FAIL_RETURN;	
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	
	return SUCCESS_RETURN;

}

/************************************************************
*功能描述： 添加定时场景信息到数据库
*输入参数：startTime：开始时间
		  weekflag: 重复星期
		  sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_scene_insert_scene_timer(time_t startTime,char weekflag,const char* sceneId)
{
	int res = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;

	const char *insertCmd = "insert into SceneTimerInfo (week,time,sceneId) \
								values ('%d','%d','%s');";	
								
	_kk_scene_lock();
	sqlCmd = sqlite3_mprintf(insertCmd,weekflag,startTime,sceneId);	
	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_scene_unlock();	
	   return FAIL_RETURN;	
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	
	return SUCCESS_RETURN;

}
/************************************************************
*功能描述： 添加嵌套场景信息到数据库
*输入参数：executeSceneId：要执行的场景Id
		  delay: 延迟时间
		  sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_scene_insert_scene_embed(int delay,const char* executeSceneId,const char* sceneId)
{
	int res = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;

	const char *insertCmd = "insert into SceneEmbedInfo (delay,executeSceneId,sceneId) \
								values ('%d','%s','%s');";	
								
	_kk_scene_lock();
	sqlCmd = sqlite3_mprintf(insertCmd,delay,executeSceneId,sceneId);	
	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_scene_unlock();	
	   return FAIL_RETURN;	
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	
	return SUCCESS_RETURN;

}
/************************************************************
*功能描述： 添加场景执行动作到数据库
*输入参数：type：类型
          deviceCode：设备deviceCode
          epNum: 设备路数
          propertyName：属性名称
          delay：延迟时间
          compareValue：value值
          sceneId：场景Id
          gwdeviceCode：网关deviceCode
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_scene_insert_scene_action(const char* type,const char* deviceCode,int epNum,const char* propertyName,
												const char* propertyValue,int delay,const char* sceneId,const char *gwdeviceCode)
{
	int res = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;

	const char *insertCmd = "insert into SceneActionInfo (type, deviceCode,epNum,propertyName,propertyValue,delay,sceneId,gwdeviceCode) \
								values ('%s','%s','%d','%s','%s','%d','%s','%s');";	
								
	_kk_scene_lock();
	sqlCmd = sqlite3_mprintf(insertCmd,type,deviceCode,epNum,propertyName,propertyValue,delay,sceneId,gwdeviceCode);	
	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_scene_unlock();	
	   return FAIL_RETURN;	
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	
	return SUCCESS_RETURN;

}
/************************************************************
*功能描述： 从数据库删除场景的基本数据
*输入参数： sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_scene_delete_scene_info(const char *sceneId)
{
	int res = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	const char *deleteCmd = "delete from SceneInfo where sceneId = '%s';";
						
	_kk_scene_lock();
	 sqlCmd = sqlite3_mprintf(deleteCmd,sceneId);	
	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_scene_unlock();	
	   return FAIL_RETURN;		
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	return SUCCESS_RETURN;
}
/************************************************************
*功能描述： 从数据库删除场景触发的基本数据
*输入参数： sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_scene_delete_scene_trigger(const char *sceneId)
{
	int res = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	const char *deleteCmd = "delete from SceneTriggerInfo where sceneId = '%s';";
						
	_kk_scene_lock();
	 sqlCmd = sqlite3_mprintf(deleteCmd,sceneId);	
	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_scene_unlock();	
	   return FAIL_RETURN;		
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	return SUCCESS_RETURN;
}
/************************************************************
*功能描述： 从数据库删除场景触发条件的基本数据
*输入参数： sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/
int kk_scene_delete_scene_condition(const char *sceneId)
{
	int res = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	const char *deleteCmd = "delete from SceneConditionInfo where sceneId = '%s';";
						
	_kk_scene_lock();
	 sqlCmd = sqlite3_mprintf(deleteCmd,sceneId);	
	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_scene_unlock();	
	   return FAIL_RETURN;		
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	return SUCCESS_RETURN;
}
/************************************************************
*功能描述： 从数据库删除定时场景的基本数据
*输入参数： sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/
int kk_scene_delete_scene_timing(const char *sceneId)
{
	int res = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	const char *deleteCmd = "delete from SceneTimerInfo where sceneId = '%s';";
						
	_kk_scene_lock();
	 sqlCmd = sqlite3_mprintf(deleteCmd,sceneId);	
	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_scene_unlock();	
	   return FAIL_RETURN;		
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	return SUCCESS_RETURN;
}
/************************************************************
*功能描述： 从数据库删除嵌套场景的基本数据
*输入参数： sceneId：场景Id
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/
int kk_scene_delete_scene_embed(const char *sceneId)
{
	int res = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	const char *deleteCmd = "delete from SceneEmbedInfo where sceneId = '%s';";
						
	_kk_scene_lock();
	 sqlCmd = sqlite3_mprintf(deleteCmd,sceneId);	
	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_scene_unlock();	
	   return FAIL_RETURN;		
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	return SUCCESS_RETURN;
}

/************************************************************
*功能描述： 从数据库删除场景执行动作的基本数据
*输入参数： sceneId：场景Id
          isforword：1,updateScene;0,addScene;
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/

int kk_scene_delete_scene_action(const char *sceneId,int isforword)
{
	int res = 0;
	kk_scene_ctx_t *ctx = _kk_scene_get_ctx();
	char *sqlCmd = NULL;
	char *zErrMsg = 0;
	sqlite3_stmt *stmt; 

	if(isforword){
		kk_scene_delete_send_to_gw(sceneId);
	}

	const char *deleteCmd = "delete from SceneActionInfo where sceneId = '%s';";	
	_kk_scene_lock();
	 sqlCmd = sqlite3_mprintf(deleteCmd,sceneId);	
	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_scene_unlock();	
	   return FAIL_RETURN;		
	}
	sqlite3_free(sqlCmd);
	_kk_scene_unlock();
	return SUCCESS_RETURN;
}



