#include <stdio.h>
#include "klist.h"
#include "kk_tsl_common.h"
#include ".././jsonrpc/jsonrpc-c.h"
#include ".././jsonrpc/rpccJSON.h"
#include "kk_ncp_common.h"

typedef struct {
	char productCode[PRODUCT_CODE_MAXLEN];	
	char deviceCode[DEVICE_CODE_MAXLEN];
	char mac[DEVICE_MAC_MAXLEN];	
    struct list_head linked_list;	
} kk_topo_dev_node_t;

typedef struct {
    void *mutex;
    void *semaphore;	
    int num;
    void *g_batch_handle_thread;	
    struct list_head dev_add_list;
    struct list_head dev_del_list;	
} kk_topo_batch_handle_ctx;

static kk_topo_batch_handle_ctx g_kk_topo_batch_handle = {0};
static kk_topo_batch_handle_ctx *_kk_topo_batch_handle_ctx(void)
{
    return &g_kk_topo_batch_handle;
}

static void _kk_topo_batch_handle_mutex_lock(void)
{
    kk_topo_batch_handle_ctx *ctx = _kk_topo_batch_handle_ctx();
    if (ctx->mutex) {
		HAL_MutexLock(ctx->mutex);
    }
}

static void _kk_topo_batch_handle_mutex_unlock(void)
{
    kk_topo_batch_handle_ctx *ctx = _kk_topo_batch_handle_ctx();
    if (ctx->mutex) {
        HAL_MutexUnlock(ctx->mutex);
    }
}

void kk_topo_batch_handle_semaphone_post(void)
{
	kk_topo_batch_handle_ctx *ctx = _kk_topo_batch_handle_ctx();
	if(ctx->semaphore){
		HAL_SemaphorePost(ctx->semaphore);
	}
}
#define PLATFORM_WAIT_INFINITE (~0)
int kk_topo_batch_handle_semaphone_wait(void)
{
	kk_topo_batch_handle_ctx *ctx = _kk_topo_batch_handle_ctx();
	if(ctx->semaphore){
		HAL_SemaphoreWait(ctx->semaphore,PLATFORM_WAIT_INFINITE);
	}
	return 0;
}

void *kk_topo_batch_handle(void *args)
{
    kk_topo_batch_handle_ctx *ctx = _kk_topo_batch_handle_ctx();
	cJSON* root_add = NULL;
	cJSON* root_del = NULL;	
	cJSON* array_add = NULL;
	cJSON* device= NULL;	
	cJSON* array_del = NULL;
		
	kk_topo_dev_node_t *node = NULL;
	EmberEUI64 gwEui64  = {0};
	char gw_macString[17] = {0};
	emberAfGetEui64(gwEui64);
	rpc_eui64ToString(gwEui64,gw_macString);

    while (1) {
        if(!kk_topo_batch_handle_semaphone_wait()){
			array_add = rpc_cJSON_CreateArray();
			if(array_add == NULL){
				continue;
			}
			root_add = rpc_cJSON_CreateObject();
			if(root_add == NULL){
				continue;
			}
			array_del = rpc_cJSON_CreateArray();
			if(array_del == NULL){
				continue;
			}
			root_del = rpc_cJSON_CreateObject();
			if(root_del == NULL){
				continue;
			}			
			if(!list_empty(&ctx->dev_add_list)){
				while(!list_empty(&ctx->dev_add_list)){
					device = rpc_cJSON_CreateObject();
					_kk_topo_batch_handle_mutex_lock();
					node = list_first_entry(&ctx->dev_add_list, kk_topo_dev_node_t, linked_list);
					if(node != NULL){
						rpc_cJSON_AddStringToObject(device, "productCode",node->productCode);
						rpc_cJSON_AddStringToObject(device, "deviceCode",node->deviceCode);
						rpc_cJSON_AddStringToObject(device, "mac",node->mac);		
						rpc_cJSON_AddStringToObject(device, "parentCode",gw_macString);
						rpc_cJSON_AddItemToArray(array_add, device);
						list_del(&node->linked_list);
						free(node);
						node = NULL;
					}
					_kk_topo_batch_handle_mutex_unlock();
				}
				rpc_cJSON_AddItemToObject(root_add, "devices", array_add);
				kk_msg_report_batch_joined(root_add,gwEui64);
			}
			if(!list_empty(&ctx->dev_del_list)){
				while(!list_empty(&ctx->dev_del_list)){
					device = rpc_cJSON_CreateObject();
					_kk_topo_batch_handle_mutex_lock();
					node = list_first_entry(&ctx->dev_del_list, kk_topo_dev_node_t, linked_list);
					if(node != NULL){
						rpc_cJSON_AddStringToObject(device, "productCode",node->productCode);
						rpc_cJSON_AddStringToObject(device, "deviceCode",node->deviceCode);
						rpc_cJSON_AddItemToArray(array_del, device);
						list_del(&node->linked_list);
						free(node);
						node = NULL;
					}
					_kk_topo_batch_handle_mutex_unlock();

				}
				rpc_cJSON_AddItemToObject(root_del, "devices", array_del);
				kk_msg_report_batch_leave(root_del,gwEui64);				
			}
		}
    }

    return NULL;
}

int kk_topo_batch_handle_init(void)
{
	int res = 0;
	kk_topo_batch_handle_ctx *ctx = _kk_topo_batch_handle_ctx();
    ctx->mutex = HAL_MutexCreate();
    if (ctx->mutex == NULL) {
        return FAIL_RETURN;
    }	
    INIT_LIST_HEAD(&ctx->dev_add_list);	
    INIT_LIST_HEAD(&ctx->dev_del_list);		
	ctx->semaphore = HAL_SemaphoreCreate();
    if (ctx->semaphore == NULL) {
        return FAIL_RETURN;
    }	

	res = pthread_create(&ctx->g_batch_handle_thread, NULL, kk_topo_batch_handle, NULL);
	if (res < 0) {
		printf("HAL_ThreadCreate kk_topo_batch_handle Failed\n");
		//IOT_Linkkit_Close(mid_ctx->master_devid);
		return -1;
	}


	return SUCCESS_RETURN;

}
static int _kk_topo_batch_check_exist(const char *deviceCode)
{
    kk_topo_dev_node_t *search_node = NULL;
	kk_topo_batch_handle_ctx *ctx = _kk_topo_batch_handle_ctx();

	if(deviceCode == NULL){
		return  INVALID_PARAMETER;
	}
    list_for_each_entry(search_node, &ctx->dev_add_list, linked_list, kk_topo_dev_node_t) {
        if ( (strlen(search_node->deviceCode) == strlen(deviceCode)) &&
            (memcmp(search_node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
            /* dm_log_debug("Device Found, Product Key: %s, Device Name: %s", product_key, device_name); */
            return SUCCESS_RETURN;
        }
    }
	return FAIL_RETURN;
}

int _kk_topo_batch_handle_add_dev(const char *productCode,const char *deviceCode,const char *macString)
{
    kk_topo_dev_node_t *node = NULL;
	kk_topo_batch_handle_ctx *ctx = _kk_topo_batch_handle_ctx();
	int res = 0;
	
	if(productCode == NULL || deviceCode == NULL || macString == NULL)
	{
		return INVALID_PARAMETER;
	}
	//rpc_eui64ToString(device_mac,macString);
	if(_kk_topo_batch_check_exist(deviceCode) == SUCCESS_RETURN){
		return SUCCESS_RETURN;
	}
    node = malloc(sizeof(kk_topo_dev_node_t));
    if (node == NULL) {
        return MEMORY_NOT_ENOUGH;
    }
	_kk_topo_batch_handle_mutex_lock();
	memset(node,0,sizeof(kk_topo_dev_node_t) );
	memcpy(node->deviceCode, deviceCode, strlen(deviceCode));
	memcpy(node->productCode, productCode, strlen(productCode));
	memcpy(node->mac, macString, strlen(macString));
    INIT_LIST_HEAD(&node->linked_list);
    list_add_tail(&node->linked_list, &ctx->dev_add_list);
	_kk_topo_batch_handle_mutex_unlock();	
	return SUCCESS_RETURN;

}

int _kk_topo_batch_handle_del_dev(const char *productCode,const char *deviceCode)
{
    kk_topo_dev_node_t *node = NULL;
	kk_topo_batch_handle_ctx *ctx = _kk_topo_batch_handle_ctx();
	int res = 0;
	
	if(productCode == NULL || deviceCode == NULL)
	{
		return INVALID_PARAMETER;
	}

    node = malloc(sizeof(kk_topo_dev_node_t));
    if (node == NULL) {
        return MEMORY_NOT_ENOUGH;
    }
	_kk_topo_batch_handle_mutex_lock();
	memset(node,0,sizeof(kk_topo_dev_node_t) );
	memcpy(node->deviceCode, deviceCode, strlen(deviceCode));
	memcpy(node->productCode, productCode, strlen(productCode));
    INIT_LIST_HEAD(&node->linked_list);
    list_add_tail(&node->linked_list, &ctx->dev_del_list);
	_kk_topo_batch_handle_mutex_unlock();	
	return SUCCESS_RETURN;

}



