#include <stdio.h>
#include "kk_tsl_api.h"

#include "kk_log.h"
#include "kk_dm_mng.h"
#include "kk_lan_node_db.h"





static sqlite3 *g_lan_pDb;
static kk_lan_node_db_ctx_t s_kk_lan_node_db_ctx = {0};
static kk_lan_node_db_ctx_t *_kk_lan_node_db_get_ctx(void)
{
	return &s_kk_lan_node_db_ctx;
}
static void _kk_lan_node_db_lock(void)
{
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();
	if (ctx->mutex) {
		HAL_MutexLock(ctx->mutex);
	}
}

static void _kk_lan_node_db_unlock(void)
{
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();
	if (ctx->mutex) {
		HAL_MutexUnlock(ctx->mutex);
	}
}

/************************************************************
*功能描述： 属性数据表初始化
*输入参数： 无
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/
static int _kk_lan_node_db_Init(void)
{
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();

	const char *pNodeTable = "CREATE TABLE IF NOT EXISTS Map2Node( \
		idx INTEGER PRIMARY KEY, \
		deviceCode varchar(33), \
		channel INTEGER, \
		nodeId INTEGER)"; 

	char *pcErr;

	_kk_lan_node_db_lock();
	
	if (sqlite3_open_v2(KK_LAN_NODE_DB_FILE, &g_lan_pDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL) != SQLITE_OK)
	{
		ERROR_PRINT("Error initialising linkage database fail!!!\n");
		return -1; 
	}
	
	ctx->pDb = g_lan_pDb;
	
	if (sqlite3_exec(ctx->pDb, pNodeTable, NULL, NULL, &pcErr) != SQLITE_OK)
	{
		ERROR_PRINT("Error creating table (%s)\n", pcErr);
		sqlite3_free(pcErr);
		_kk_lan_node_db_unlock();
		return -1;
	}
	
	_kk_lan_node_db_unlock();
	return 0;
}

/************************************************************
*功能描述： 属性模块初始化
*输入参数： 无
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/
int kk_lan_db_node_init(void)
{
	int res = 0;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();
	
	ctx->mutex = HAL_MutexCreate();
	if (ctx->mutex == NULL) {
		return -1;
	}

	res = _kk_lan_node_db_Init();
	if(res != 0){
		ERROR_PRINT("[%s][%d]kk_lan_node_db_init FAIL!!!\n",__FUNCTION__,__LINE__);
		return res;
	}

	return 0;
}



int kk_check_lan_node(int nodeId)
{
	int isExist = 0;
	sqlite3_stmt *stmt;
	char *pDeviceCode = NULL;
	int node = 0;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();
	const char *searchCmd = "select * from Map2Node;";	
	_kk_lan_node_db_lock();
	sqlite3_prepare_v2(ctx->pDb, searchCmd, strlen(searchCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
		node = sqlite3_column_int(stmt, LAN_DB_NODE);
		printf("$$$$$$$$$$$$$$$$$$check node=%d,nodeId=%d\n",node,nodeId);
		if( node==nodeId)
		{
			isExist = 1;
			break;
		}
	}

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


/************************************************************
*功能描述： check属性是否重复
*输入参数： deviceCode：设备deviceCode
          identifier：属性名称
*输出参数： 无
*返 回 值：  1：已经存在；0：不存在
*其他说明：
*************************************************************/
int kk_check_lan_node_exist(const char* deviceCode,int channel)
{
	int isExist = 0;
	sqlite3_stmt *stmt;
	char *pDeviceCode = NULL;
	int ch = 0;
	int node = 0;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();
	const char *searchCmd = "select * from Map2Node;";	
	_kk_lan_node_db_lock();
	sqlite3_prepare_v2(ctx->pDb, searchCmd, strlen(searchCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
		pDeviceCode = sqlite3_column_text(stmt, LAN_DB_DEVICECODE);
		ch = sqlite3_column_int(stmt, LAN_DB_CHANNEL);
		if(!strcmp(deviceCode,pDeviceCode) && ch==channel)
		{
			isExist = 1;
			break;
		}
	}

	sqlite3_finalize(stmt);
	_kk_lan_node_db_unlock();
	return isExist;
}
static int _kk_check_lan_node_same(const char* deviceCode,int channel,int nodeId)
{
	int same = 0;
	sqlite3_stmt *stmt;
	char *pDeviceCode = NULL;
	int ch = 0;
	int node = 0;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();
	const char *searchCmd = "select * from Map2Node;";	
	_kk_lan_node_db_lock();
	sqlite3_prepare_v2(ctx->pDb, searchCmd, strlen(searchCmd), &stmt, NULL);

	while(sqlite3_step(stmt) == SQLITE_ROW){
		pDeviceCode = sqlite3_column_text(stmt, LAN_DB_DEVICECODE);
		ch = sqlite3_column_int(stmt, LAN_DB_CHANNEL);
		node = sqlite3_column_int(stmt, LAN_DB_NODE);
		if(!strcmp(deviceCode,pDeviceCode) && ch==channel &&node==nodeId)
		{
			same = 1;
			break;
		}
	}

	sqlite3_finalize(stmt);
	_kk_lan_node_db_unlock();
	return same;
}


/************************************************************
*功能描述： 更新属性值
*输入参数： deviceCode：设备deviceCode
          identifier：属性名称
          value：属性值
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/
static int kk_lan_db_node_update(const char *deviceCode,int channel,int node)
{
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();

	_kk_lan_node_db_lock();

	sqlCmd = sqlite3_mprintf("UPDATE Map2Node SET nodeId='%d'  WHERE deviceCode= '%s' and channel = '%d'",node,deviceCode,channel);	


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

/************************************************************
*功能描述： 插入属性到数据库
*输入参数： deviceCode：设备deviceCode
          identifier：属性名称
          valuetype：属性值类型
          devtype：设备类型
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：属性的值插入的时候先置空，后续再update
*************************************************************/
int kk_lan_db_node_insert(const char *deviceCode,int channel,int node)
{
	const char *insertCmd = "insert into Map2Node (deviceCode,channel,nodeId) \
								values ('%s','%d','%d');";
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();

	if(kk_check_lan_node_exist(deviceCode,channel)){
		if(_kk_check_lan_node_same(deviceCode,channel,node)){
			kk_lan_db_node_update(deviceCode,channel,node);
		}
		return 0;
	}
	
	_kk_lan_node_db_lock();
	sqlCmd = sqlite3_mprintf(insertCmd,deviceCode,channel,node);	

	rc = sqlite3_exec(ctx->pDb, sqlCmd, NULL, NULL, &zErrMsg);
	if( rc != SQLITE_OK ){
		ERROR_PRINT("SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}else{

	}
	sqlite3_free(sqlCmd);
	_kk_lan_node_db_unlock();
	return SUCCESS_RETURN;
}



/*
int kk_lan_db_node_get_max(const char *deviceCode,int channel)
{
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	sqlite3_stmt *stmt;
	int node = -1;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();

	_kk_lan_node_db_lock();
	sqlCmd = sqlite3_mprintf("select Max(cast(nodeId as int)) from Map2Node",);	
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
		node = sqlite3_column_value(stmt, LAN_DB_NODE);
	}
	sqlite3_free(sqlCmd);
	_kk_lan_node_db_unlock();
	sqlite3_finalize(stmt);

	return node;
}
*/

/************************************************************
*功能描述： 获取属性值
*输入参数： deviceCode：设备deviceCode
          identifier：属性名称
*输出参数： value：属性值,返回的是字串
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/
int kk_lan_db_node_get_all(const char *deviceCode,int *nodes)
{
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	sqlite3_stmt *stmt;
	int num = 0;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();

	_kk_lan_node_db_lock();
	sqlCmd = sqlite3_mprintf("select * from Map2Node WHERE deviceCode= '%s'",deviceCode);

	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
		nodes[num++] = sqlite3_column_int(stmt, LAN_DB_NODE);
	}
	sqlite3_free(sqlCmd);
	_kk_lan_node_db_unlock();
	sqlite3_finalize(stmt);

	return num;
}


int kk_lan_db_node_get(const char *deviceCode,int channel)
{
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	sqlite3_stmt *stmt;
	int node = -1;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();

	_kk_lan_node_db_lock();
	sqlCmd = sqlite3_mprintf("select * from Map2Node WHERE deviceCode= '%s' and channel = '%d'",deviceCode,channel);	

	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
		node = sqlite3_column_int(stmt, LAN_DB_NODE);
	}
	sqlite3_free(sqlCmd);
	_kk_lan_node_db_unlock();
	sqlite3_finalize(stmt);

	return node;
}



int kk_lan_db_get_item_by_node(int node,char *deviceCode,int *channel)
{
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	sqlite3_stmt *stmt;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();
	char *dCode = 0;
	
	_kk_lan_node_db_lock();
	sqlCmd = sqlite3_mprintf("select * from Map2Node WHERE nodeId= '%d' ",node);	
	sqlite3_prepare_v2(ctx->pDb, sqlCmd, strlen(sqlCmd), &stmt, NULL);
	while(sqlite3_step(stmt) == SQLITE_ROW){
		if(deviceCode!=NULL){
			dCode = sqlite3_column_text(stmt, LAN_DB_DEVICECODE);
			memcpy(deviceCode,dCode,strlen(dCode));
			
		}
		if(channel!=NULL){
			*channel = sqlite3_column_int(stmt, LAN_DB_CHANNEL);
		}
	}
	sqlite3_free(sqlCmd);
	_kk_lan_node_db_unlock();
	sqlite3_finalize(stmt);

	return 0;

}
int kk_lan_db_channel_get(int node,int *channel)
{
	kk_lan_db_get_item_by_node(node,NULL,channel);
}

int kk_lan_db_deviceCode_get(int node,char *deviceCode)
{
	kk_lan_db_get_item_by_node(node,deviceCode,NULL);
}



/************************************************************
*功能描述：通过deviceCode删除设备属性
*输入参数： deviceCode：设备deviceCode
*输出参数： 无
*返 回 值：  0：成功；其他：失败
*其他说明：
*************************************************************/
int kk_lan_db_node_delete(char *deviceCode)
{
	const char *deleteCmd = "delete from Map2Node where deviceCode = '%s';";
	char *sqlCmd = NULL;
	int rc = 0;
	char *zErrMsg = 0;
	kk_lan_node_db_ctx_t *ctx = _kk_lan_node_db_get_ctx();

	_kk_lan_node_db_lock();
	sqlCmd = sqlite3_mprintf(deleteCmd,deviceCode);	

	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_lan_node_db_unlock();
	return SUCCESS_RETURN;
}







