#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "kk_utils.h"
#include "kk_log.h"
#include "kk_tsl_parse.h"

typedef int (*kk_tsl_data_parse)(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
typedef int (*kk_tsl_array_parse)(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);

typedef struct {
	kk_tsl_data_type_e type;
	const char *name;
	kk_tsl_data_parse  func_parse;
	kk_tsl_array_parse func_array_parse;
} kk_tsl_mapping_t;
static int _kk_tsl_data_array_search(_IN_ kk_tsl_data_t *input, _IN_ int input_index, _IN_ char *key,
		_IN_ int key_len, _OU_ kk_tsl_data_t **output, _OU_ int *output_index);

//Data Parse
static int _kk_tsl_int_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_float_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_double_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_text_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_enum_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_date_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_bool_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_array_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_struct_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_property_parse(_IN_ kk_tsl_data_t *property, _IN_ lite_cjson_t *root);

//Array Data Parse
static int _kk_tsl_array_int_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_array_float_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_array_double_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_array_text_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_array_enum_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_array_date_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_array_bool_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_array_array_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);
static int _kk_tsl_array_struct_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root);

static kk_tsl_mapping_t s_kk_tsl_mapping[] = {
	{KK_TSL_DATA_TYPE_NONE,     "none",     NULL,                      NULL                          },
	{KK_TSL_DATA_TYPE_INT,      "int",      _kk_tsl_int_parse,      _kk_tsl_array_int_parse      },
	{KK_TSL_DATA_TYPE_FLOAT,    "float",    _kk_tsl_float_parse,    _kk_tsl_array_float_parse    },
	{KK_TSL_DATA_TYPE_DOUBLE,   "double",   _kk_tsl_double_parse,   _kk_tsl_array_double_parse   },
	{KK_TSL_DATA_TYPE_TEXT,     "text",     _kk_tsl_text_parse,     _kk_tsl_array_text_parse     },
	{KK_TSL_DATA_TYPE_ENUM,     "enum",     _kk_tsl_enum_parse,     _kk_tsl_array_enum_parse     },
	{KK_TSL_DATA_TYPE_DATE,     "date",     _kk_tsl_date_parse,     _kk_tsl_array_date_parse     },
	{KK_TSL_DATA_TYPE_BOOL,     "bool",     _kk_tsl_bool_parse,     _kk_tsl_array_bool_parse     },
	{KK_TSL_DATA_TYPE_ARRAY,    "array",    _kk_tsl_array_parse,    _kk_tsl_array_array_parse    },
	{KK_TSL_DATA_TYPE_STRUCT,   "struct",   _kk_tsl_struct_parse,   _kk_tsl_array_struct_parse   }
};

static int _kk_tsl_get_type(_IN_ const char *name, _IN_ int name_len, _OU_ kk_tsl_data_type_e *type)
{
	if (name == NULL || name_len <= 0 || type == NULL) {
		return INVALID_PARAMETER;
	}

	int index = 0;

	for (index = 0; index < sizeof(s_kk_tsl_mapping) / sizeof(kk_tsl_mapping_t); index++) {
		if (strlen(s_kk_tsl_mapping[index].name) == name_len &&
			memcmp(s_kk_tsl_mapping[index].name, name, name_len) == 0) {
			*type = s_kk_tsl_mapping[index].type;
			return SUCCESS_RETURN;
		}
	}

	return FAIL_RETURN;
}

static int _kk_tsl_int_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	return SUCCESS_RETURN;
}

static int _kk_tsl_float_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	return SUCCESS_RETURN;
}

static int _kk_tsl_double_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	return SUCCESS_RETURN;
}

static int _kk_tsl_text_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	return SUCCESS_RETURN;
}

static int _kk_tsl_enum_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	return SUCCESS_RETURN;
}

static int _kk_tsl_date_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	return SUCCESS_RETURN;
}

static int _kk_tsl_bool_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	return SUCCESS_RETURN;
}
static int _kk_tsl_array_int_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	kk_tsl_data_value_complex_t *complex_array = (kk_tsl_data_value_complex_t *)data_value->value;

	complex_array->value = malloc((complex_array->size) * (sizeof(int)));
	if (complex_array->value == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_array->value, 0, (complex_array->size) * (sizeof(int)));

	return SUCCESS_RETURN;
}

static int _kk_tsl_array_float_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	kk_tsl_data_value_complex_t *complex_array = (kk_tsl_data_value_complex_t *)data_value->value;

	complex_array->value = malloc((complex_array->size) * (sizeof(float)));
	if (complex_array->value == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_array->value, 0, (complex_array->size) * (sizeof(float)));

	return SUCCESS_RETURN;
}
static int _kk_tsl_array_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	int res = 0;
	char size_str[DM_UTILS_UINT32_STRLEN] = {0};
	lite_cjson_t lite_item, lite_type, lite_specs;
	kk_tsl_data_value_complex_t *complex_array = NULL;

	/* dm_log_debug("DM_SHW_DATA_TYPE_ARRAY"); */

	if (root == NULL || !lite_cjson_is_object(root)) {
		return INVALID_PARAMETER;
	}

	//Allocate Memory For Data Type Specs
	complex_array = malloc(sizeof(kk_tsl_data_value_complex_t));
	if (complex_array == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_array, 0, sizeof(kk_tsl_data_value_complex_t));
	data_value->value = (void *)complex_array;

	//Parse Size (Mandatory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_SIZE, strlen(KK_TSL_KEY_SIZE), &lite_item);
	if (res != SUCCESS_RETURN && !lite_cjson_is_string(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	if (lite_item.value_length > DM_UTILS_UINT32_STRLEN) {
		return FAIL_RETURN;
	}
	memcpy(size_str, lite_item.value, lite_item.value_length);
	complex_array->size = atoi(size_str);

	/* dm_log_debug("TSL Property Array Size: %d",complex_array->size); */

	//Parse Item And Type (Mandatory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_ITEM, strlen(KK_TSL_KEY_ITEM), &lite_item);
	if (res != SUCCESS_RETURN && !lite_cjson_is_object(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	memset(&lite_type, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(&lite_item, KK_TSL_KEY_TYPE, strlen(KK_TSL_KEY_TYPE), &lite_type);
	if (res != SUCCESS_RETURN && !lite_cjson_is_string(&lite_type)) {
		return JSON_PARSE_FAILED;
	}
	res = _kk_tsl_get_type(lite_type.value, lite_type.value_length, &complex_array->type);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	/* dm_log_debug("TSL Property Array Type: %d",complex_array->type); */

	//Parse Specs (Optional)
	memset(&lite_specs, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(&lite_item, KK_TSL_KEY_SPECS, strlen(KK_TSL_KEY_SPECS), &lite_specs);
	if ((complex_array->type == KK_TSL_DATA_TYPE_ARRAY || complex_array->type == KK_TSL_DATA_TYPE_STRUCT) &&
		(res != SUCCESS_RETURN)) {
		return JSON_PARSE_FAILED;
	}

	if (s_kk_tsl_mapping[complex_array->type].func_array_parse == NULL) {
		return FAIL_RETURN;
	}
	/* dm_log_debug("TSL Property Specs Type: %s",g_dm_tsl_alink_mapping[complex_array->type].name); */

	//Parse Array Type
	res = s_kk_tsl_mapping[complex_array->type].func_array_parse(data_value, &lite_specs);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	return SUCCESS_RETURN;
}

static int _kk_tsl_struct_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	int res = 0, index = 0;
	lite_cjson_t lite_item;
	kk_tsl_data_t *property = NULL;
	kk_tsl_data_value_complex_t *complex_struct = NULL;

	/* dm_log_debug("DM_SHW_DATA_TYPE_STRUCT"); */

	if (root == NULL || !lite_cjson_is_array(root) || root->size == 0) {
		return INVALID_PARAMETER;
	}

	//printf("TSL Property Struct Size: %d",root->size); 

	//Allocate Memory For Data Type Specs
	complex_struct = malloc(sizeof(kk_tsl_data_value_complex_t));
	if (complex_struct == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_struct, 0, sizeof(kk_tsl_data_value_complex_t));
	data_value->value = (void *)complex_struct;

	complex_struct->size = root->size;

	//Allocate Memory For Multi Identifier
	complex_struct->value = malloc((complex_struct->size) * (sizeof(kk_tsl_data_t)));
	if (complex_struct->value == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_struct->value, 0, (complex_struct->size) * (sizeof(kk_tsl_data_t)));

	for (index = 0; index < complex_struct->size; index++) {
		memset(&lite_item, 0, sizeof(lite_cjson_t));
		property = (kk_tsl_data_t *)complex_struct->value + index;
		/* dm_log_debug("TSL Property Struct Index: %d",index); */

		res = lite_cjson_array_item(root, index, &lite_item);
		if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
			return JSON_PARSE_FAILED;
		}
		//printf("TSL Property Struct Property: %.*s",lite_item.value_length,lite_item.value); 
		res = _kk_tsl_property_parse(property, &lite_item);
		if (res != SUCCESS_RETURN) {
			return FAIL_RETURN;
		}
	}

	return SUCCESS_RETURN;
}
static int _kk_tsl_array_double_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	kk_tsl_data_value_complex_t *complex_array = (kk_tsl_data_value_complex_t *)data_value->value;

	complex_array->value = malloc((complex_array->size) * (sizeof(double)));
	if (complex_array->value == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_array->value, 0, (complex_array->size) * (sizeof(double)));

	return SUCCESS_RETURN;
}
static int _kk_tsl_array_text_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	kk_tsl_data_value_complex_t *complex_array = (kk_tsl_data_value_complex_t *)data_value->value;

	complex_array->value = malloc((complex_array->size) * (sizeof(char *)));
	if (complex_array->value == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_array->value, 0, (complex_array->size) * (sizeof(char *)));
	return SUCCESS_RETURN;
}
static int _kk_tsl_array_enum_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	kk_tsl_data_value_complex_t *complex_array = (kk_tsl_data_value_complex_t *)data_value->value;

	complex_array->value = malloc((complex_array->size) * (sizeof(int)));
	if (complex_array->value == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_array->value, 0, (complex_array->size) * (sizeof(int)));

	return SUCCESS_RETURN;
}
static int _kk_tsl_array_date_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	kk_tsl_data_value_complex_t *complex_array = (kk_tsl_data_value_t *)data_value->value;

	complex_array->value = malloc((complex_array->size) * (sizeof(char *)));
	if (complex_array->value == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_array->value, 0, (complex_array->size) * (sizeof(char *)));

	return SUCCESS_RETURN;
}
static int _kk_tsl_array_bool_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	kk_tsl_data_value_complex_t *complex_array = (kk_tsl_data_value_complex_t *)data_value->value;

	complex_array->value = malloc((complex_array->size) * (sizeof(int)));
	if (complex_array->value == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_array->value, 0, (complex_array->size) * (sizeof(int)));

	return SUCCESS_RETURN;
}

static int _kk_tsl_array_array_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	return SUCCESS_RETURN;
}
static int _kk_tsl_array_struct_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	int res = 0, index = 0;
	kk_tsl_data_value_complex_t *complex_array = (kk_tsl_data_value_complex_t *)data_value->value;
	kk_tsl_data_t *data = NULL;

	if (!lite_cjson_is_array(root) || root->size <= 0) {
		return INVALID_PARAMETER;
	}

	printf("Array Struct Size: %d\n", complex_array->size);
	complex_array->value = malloc((complex_array->size) * (sizeof(kk_tsl_data_t)));
	if (complex_array->value == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(complex_array->value, 0, (complex_array->size) * (sizeof(kk_tsl_data_t)));

	printf("Array Struct Spec Size: %d", root->size);
	for (index = 0; index < complex_array->size; index++) {
		data = (kk_tsl_data_t *)complex_array->value + index;

		data->data_value.type = KK_TSL_DATA_TYPE_STRUCT;

		res = _kk_tsl_struct_parse(&data->data_value, root);
		if (res != SUCCESS_RETURN) {
			continue;
		}
	}

	return SUCCESS_RETURN;
}

static int _kk_tsl_opt_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	int res = 0;
	lite_cjson_t lite_item;
	if(data_value->type == KK_TSL_DATA_TYPE_TEXT){
		res = lite_cjson_object_item(root, KK_TSL_KEY_LENGTH, strlen(KK_TSL_KEY_LENGTH), &lite_item);
		if(res == SUCCESS_RETURN){
			data_value->length = atoi(lite_item.value);
		}
	}
	else if(data_value->type == KK_TSL_DATA_TYPE_INT){
		res = lite_cjson_object_item(root, KK_TSL_KEY_MIN, strlen(KK_TSL_KEY_MIN), &lite_item);
		if(res == SUCCESS_RETURN){
			data_value->mix = atoi(lite_item.value);
			//printf("------------>[%s][%d]data_value->mix:%d\n",__FUNCTION__,__LINE__,data_value->mix);
		}
		res = lite_cjson_object_item(root, KK_TSL_KEY_MAX, strlen(KK_TSL_KEY_MAX), &lite_item);
		if(res == SUCCESS_RETURN){
			data_value->max = atoi(lite_item.value);
			//printf("------------>[%s][%d]data_value->max:%d\n",__FUNCTION__,__LINE__,data_value->max);
		}

	}else if(data_value->type == KK_TSL_DATA_TYPE_FLOAT||
			data_value->type == KK_TSL_DATA_TYPE_DOUBLE){
		res = lite_cjson_object_item(root, KK_TSL_KEY_MIN, strlen(KK_TSL_KEY_MIN), &lite_item);
		if(res == SUCCESS_RETURN){
			data_value->mix = atof(lite_item.value);
			//printf("------------>[%s][%d]data_value->mix:%d\n",__FUNCTION__,__LINE__,data_value->mix);
		}
		res = lite_cjson_object_item(root, KK_TSL_KEY_MAX, strlen(KK_TSL_KEY_MAX), &lite_item);
		if(res == SUCCESS_RETURN){
			data_value->max = atof(lite_item.value);
			//printf("------------>[%s][%d]data_value->max:%d\n",__FUNCTION__,__LINE__,data_value->max);
		}
	}

	return SUCCESS_RETURN;

}

static int _kk_tsl_data_parse(_IN_ kk_tsl_data_value_t *data_value, _IN_ lite_cjson_t *root)
{
	int res = 0;
	lite_cjson_t lite_item;

	memset(data_value, 0, sizeof(kk_tsl_data_value_t));

	//Parse Type
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_TYPE, strlen(KK_TSL_KEY_TYPE), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	//printf("TSL Data Type: %.*s\n", lite_item.value_length, lite_item.value);
	res = _kk_tsl_get_type(lite_item.value, lite_item.value_length, &data_value->type);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	//Parse Specs
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_SPECS, strlen(KK_TSL_KEY_SPECS), &lite_item);
	if (res == SUCCESS_RETURN) {
		_kk_tsl_opt_parse(data_value,&lite_item);
	}

	//Parse Type And Value
	if (s_kk_tsl_mapping[data_value->type].func_parse == NULL) {
		return FAIL_RETURN;
	}
	res = s_kk_tsl_mapping[data_value->type].func_parse(data_value, &lite_item);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	return SUCCESS_RETURN;
}

static int _kk_tsl_property_parse(_IN_ kk_tsl_data_t *property, _IN_ lite_cjson_t *root)
{
	int res = 0;
	lite_cjson_t lite_item;
	//Parse Identifier (Mandatory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_IDENTIFIER, strlen(KK_TSL_KEY_IDENTIFIER), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	res = kk_utils_copy(lite_item.value, lite_item.value_length, (void **)(&property->identifier),
						lite_item.value_length + 1);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	//printf("----------->%s\n",root->value);
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_ACCESS_MODE, strlen(KK_TSL_KEY_ACCESS_MODE), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
		goto next;
	}
	res = kk_utils_copy(lite_item.value, lite_item.value_length, (void **)(&property->accessMode),
						lite_item.value_length + 1);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	//Parse DataType
next:
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_DATATYPE, strlen(KK_TSL_KEY_DATATYPE), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	/* dm_log_debug("TSL Property Data Type: %.*s",lite_item.value_length,lite_item.value); */
	res = _kk_tsl_data_parse(&property->data_value, &lite_item);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	return SUCCESS_RETURN;
}

static int _kk_tsl_properties_parse(_IN_ kk_tsl_t *shadow, _IN_ lite_cjson_t *root)
{
	int res = 0, index = 0;
	lite_cjson_t lite_properties, lite_property;

	memset(&lite_properties, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_PROPERTIES, strlen(KK_TSL_KEY_PROPERTIES), &lite_properties);
	if (res == SUCCESS_RETURN) {
		if (!lite_cjson_is_array(&lite_properties)) {
			return JSON_PARSE_FAILED;
		}
	} else {
		return SUCCESS_RETURN;
	}

	INFO_PRINT("property number: %d\n", lite_properties.size);
	if (lite_properties.size == 0) {
		return SUCCESS_RETURN;
	}

	//Allocate Memory For TSL Properties Struct
	shadow->property_number = lite_properties.size;
	shadow->properties = malloc(sizeof(kk_tsl_data_t) * (lite_properties.size));
	if (shadow->properties == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(shadow->properties, 0, sizeof(kk_tsl_data_t) * (lite_properties.size));

	for (index = 0; index < lite_properties.size; index++) {
		memset(&lite_property, 0, sizeof(lite_cjson_t));
		res = lite_cjson_array_item(&lite_properties, index, &lite_property);
		if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_property)) {
			return FAIL_RETURN;
		}

		//printf("Index: %d\n", index);
		_kk_tsl_property_parse(shadow->properties + index, &lite_property);
	}

	return SUCCESS_RETURN;
}
/*********************event parse*********************************/
static int _kk_tsl_event_outputdata_parse(_IN_ kk_tsl_t *shadow, _IN_ kk_tsl_data_t *event_data,
		_IN_ lite_cjson_t *root)
{
	int res = 0;
	lite_cjson_t lite_item;

	//Parse Identifier (Madantory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_IDENTIFIER, strlen(KK_TSL_KEY_IDENTIFIER), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	res = kk_utils_copy(lite_item.value, lite_item.value_length, (void **) & (event_data->identifier),
						lite_item.value_length + 1);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	//printf("Identifier: %s\n", event_data->identifier);

	//Parse DataType
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_DATATYPE, strlen(KK_TSL_KEY_DATATYPE), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	/* dm_log_debug("TSL Output Event Data Type: %.*s",lite_item.value_length,lite_item.value); */
	res = _kk_tsl_data_parse(&event_data->data_value, &lite_item);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	return SUCCESS_RETURN;
}

static int _kk_tsl_event_outputdatas_parse(_IN_ kk_tsl_t *shadow, _IN_ kk_tsl_event_t *event, _IN_ lite_cjson_t *root)
{
	int res = 0, index = 0;
	lite_cjson_t lite_item;
	kk_tsl_data_t *output_data = NULL;

	//printf("event outputdata Number: %d\n", event->output_data_number);
	if (event->output_data_number == 0) {
		return SUCCESS_RETURN;
	}

	//Allocate Memory For Output Datas
	event->output_datas = malloc((event->output_data_number) * (sizeof(kk_tsl_data_t)));
	if (event->output_datas == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(event->output_datas, 0, (event->output_data_number) * (sizeof(kk_tsl_data_t)));

	for (index = 0; index < event->output_data_number; index++) {
		memset(&lite_item, 0, sizeof(lite_cjson_t));
		output_data = event->output_datas + index;

		res = lite_cjson_array_item(root, index, &lite_item);
		if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
			return FAIL_RETURN;
		}

		//printf("Index: %d\n", index);
		_kk_tsl_event_outputdata_parse(shadow, output_data, &lite_item);
	}

	return SUCCESS_RETURN;
}

static int _dm_shw_event_parse(_IN_ kk_tsl_t *shadow, _IN_ kk_tsl_event_t *event, _IN_ lite_cjson_t *root)
{
	int res = 0;
	lite_cjson_t lite_item;

	//Parse Identifier (Mandatory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_IDENTIFIER, strlen(KK_TSL_KEY_IDENTIFIER), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	res = kk_utils_copy(lite_item.value, lite_item.value_length, (void **)(&event->identifier), lite_item.value_length + 1);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	//printf("Identifier: %s\n", event->identifier);

	/* Check If Current Event Id Is Post */
	if (((strlen(event->identifier) == strlen(KK_TSL_SPECIAL_EVENT_POST_IDENTIFIER)) &&
		(memcmp(event->identifier, KK_TSL_SPECIAL_EVENT_POST_IDENTIFIER, strlen(KK_TSL_SPECIAL_EVENT_POST_IDENTIFIER)) == 0))) {
		/* dm_log_info("TSL Special Event Identifier: %s, Ignore It",event->identifier); */
		return SUCCESS_RETURN;
	}

	//Parse Output Data (Madantory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_OUTPUTDATA, strlen(KK_TSL_KEY_OUTPUTDATA), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_array(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	//INFO_PRINT("event output number: %d\n", lite_item.size);
	event->output_data_number = lite_item.size;
	res = _kk_tsl_event_outputdatas_parse(shadow, event, &lite_item);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	return SUCCESS_RETURN;
}

static int _kk_tsl_events_parse(_IN_ kk_tsl_t *shadow, _IN_ lite_cjson_t *root)
{
	int res = 0, index = 0;
	lite_cjson_t lite_events, lite_event;

	memset(&lite_events, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_EVENTS, strlen(KK_TSL_KEY_EVENTS), &lite_events);
	if (res == SUCCESS_RETURN) {
		if (!lite_cjson_is_array(&lite_events)) {
			return JSON_PARSE_FAILED;
		}
	} else {
		return SUCCESS_RETURN;
	}
	if (lite_events.size == 0) {
		return SUCCESS_RETURN;
	}

	//Allocate Memory For TSL Events Struct
	shadow->event_number = lite_events.size;
	shadow->events = malloc(sizeof(kk_tsl_event_t) * (lite_events.size));
	if (shadow->events == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(shadow->events, 0, sizeof(kk_tsl_event_t) * (lite_events.size));

	for (index = 0; index < lite_events.size; index++) {
		memset(&lite_event, 0, sizeof(lite_cjson_t));
		res = lite_cjson_array_item(&lite_events, index, &lite_event);
		if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_event)) {
			return FAIL_RETURN;
		}

		//printf("Index: %d\n", index);
		_dm_shw_event_parse(shadow, shadow->events + index, &lite_event);
	}
	return SUCCESS_RETURN;
}

/**********************service parse**********************************/
static int _kk_tsl_service_outputdata_parse(_IN_ kk_tsl_t *shadow, _IN_ kk_tsl_data_t *service_data,
		_IN_ lite_cjson_t *root)
{
	int res = 0;
	lite_cjson_t lite_item;

	//Parse Identifier (Madantory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_IDENTIFIER, strlen(KK_TSL_KEY_IDENTIFIER), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	res = kk_utils_copy(lite_item.value, lite_item.value_length, (void **) & (service_data->identifier),
						lite_item.value_length + 1);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	//printf("Identifier: %s", service_data->identifier);

	//Parse DataType
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_DATATYPE, strlen(KK_TSL_KEY_DATATYPE), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	/* dm_log_debug("TSL Output Service Data Type: %.*s",lite_item.value_length,lite_item.value); */
	res = _kk_tsl_data_parse(&service_data->data_value, &lite_item);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	return SUCCESS_RETURN;
}

static int _kk_tsl_service_outputdatas_parse(_IN_ kk_tsl_t *shadow, _IN_ kk_tsl_service_t *service,
		_IN_ lite_cjson_t *root)
{
	int res = 0, index = 0;
	lite_cjson_t lite_item;
	kk_tsl_data_t *output_data = NULL;

	printf("Number: %d", service->output_data_number);
	if (service->output_data_number == 0) {
		return SUCCESS_RETURN;
	}

	//Allocate Memory For Output Datas
	service->output_datas = malloc((service->output_data_number) * (sizeof(kk_tsl_data_t)));
	if (service->output_datas == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(service->output_datas, 0, (service->output_data_number) * (sizeof(kk_tsl_data_t)));

	for (index = 0; index < service->output_data_number; index++) {
		memset(&lite_item, 0, sizeof(lite_cjson_t));
		output_data = service->output_datas + index;

		res = lite_cjson_array_item(root, index, &lite_item);
		if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
			return FAIL_RETURN;
		}

		//printf("Index: %d", index);
		_kk_tsl_service_outputdata_parse(shadow, output_data, &lite_item);
	}

	return SUCCESS_RETURN;
}
static int _kk_tsl_service_inputdata_parse(_IN_ kk_tsl_t *shadow, _IN_ kk_tsl_data_t *input_data,
		_IN_ lite_cjson_t *root)
{
	int res = 0;
	lite_cjson_t lite_item;

	if (!lite_cjson_is_object(root)) {
		return INVALID_PARAMETER;
	}

	//Parse Identifier (Madantory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_IDENTIFIER, strlen(KK_TSL_KEY_IDENTIFIER), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	res = kk_utils_copy(lite_item.value, lite_item.value_length, (void **) & (input_data->identifier),
						lite_item.value_length + 1);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	//printf("Identifier: %s", input_data->identifier);

	//Parse DataType
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_DATATYPE, strlen(KK_TSL_KEY_DATATYPE), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	/* dm_log_debug("TSL Input Service Data Type: %.*s",lite_item.value_length,lite_item.value); */
	res = _kk_tsl_data_parse(&input_data->data_value, &lite_item);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	return SUCCESS_RETURN;
}

static int _kk_tsl_service_parse_get_input_identifier(char *str,int count,kk_tsl_data_t *input_datas)
{
	char *pstr = str;
	char *start = NULL;
	char *end = NULL;
	int i = 0;
	int len = 0;
	char *identifier = NULL;
	kk_tsl_data_t *input_data = NULL;
	if(input_datas == NULL){
		return -1;
	}
	for(i = 0; i < count; i++){
		input_data = input_datas + i;
		start = strchr(pstr,'"') ;
		end = strchr(start+1,'"');
		len = end-start-1;
		identifier = malloc(len+1);
		if(identifier == NULL) 
			return -1;
		memset(identifier,0x0,len);
		strncpy(identifier,start+1,len);
		identifier[len] = '\0';
		input_data->identifier = identifier;
		pstr = end + 1;
	}
	return 0;
}

static int _kk_tsl_service_inputdatas_get_parse(_IN_ kk_tsl_t *shadow, _IN_ kk_tsl_service_t *service,
		_IN_ lite_cjson_t *root)
{
	//printf("input Number: %d\n", service->input_data_number);
	if (service->input_data_number == 0) {
		return SUCCESS_RETURN;
	}

	//Allocate Memory For Output Datas
	service->input_datas = malloc((service->input_data_number) * (sizeof(kk_tsl_data_t)));
	if (service->input_datas == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(service->input_datas, 0, (service->input_data_number) * (sizeof(kk_tsl_data_t)));
	_kk_tsl_service_parse_get_input_identifier( root->value,service->input_data_number,service->input_datas);
	return SUCCESS_RETURN;
}

static int _kk_tsl_service_inputdatas_parse(_IN_ kk_tsl_t *shadow, _IN_ kk_tsl_service_t *service,
		_IN_ lite_cjson_t *root)
{
	int res = 0, index = 0;
	lite_cjson_t lite_item;
	kk_tsl_data_t *input_data = NULL;

	//printf("input Number: %d\n", service->input_data_number);
	if (service->input_data_number == 0) {
		return SUCCESS_RETURN;
	}

	//Allocate Memory For Output Datas
	service->input_datas = malloc((service->input_data_number) * (sizeof(kk_tsl_data_t)));
	if (service->input_datas == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(service->input_datas, 0, (service->input_data_number) * (sizeof(kk_tsl_data_t)));

	for (index = 0; index < service->input_data_number; index++) {
		memset(&lite_item, 0, sizeof(lite_cjson_t));
		input_data = service->input_datas + index;

		res = lite_cjson_array_item(root, index, &lite_item);
		if (res != SUCCESS_RETURN) {
			return FAIL_RETURN;
		}

		//printf("Index: %d", index);
		_kk_tsl_service_inputdata_parse(shadow, input_data, &lite_item);
	}

	return SUCCESS_RETURN;
}

static int _kk_tsl_service_parse(_IN_ kk_tsl_t *shadow, _IN_ kk_tsl_service_t *service, _IN_ lite_cjson_t *root)
{
	int res = 0;
	lite_cjson_t lite_item;
	int isGetService = 0;

	//Parse Identifier (Mandatory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_IDENTIFIER, strlen(KK_TSL_KEY_IDENTIFIER), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	res = kk_utils_copy(lite_item.value, lite_item.value_length, (void **)(&service->identifier),
						lite_item.value_length + 1);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	//printf("Identifier: %s", service->identifier);

	/* Check If Current Service Id Is Set */
	if ((strlen(service->identifier) == strlen(KK_TSL_SPECIAL_SERVICE_SET_IDENTIFIER)) &&
		(memcmp(service->identifier, KK_TSL_SPECIAL_SERVICE_SET_IDENTIFIER,
			strlen(KK_TSL_SPECIAL_SERVICE_SET_IDENTIFIER)) == 0)) {
		/* dm_log_info("TSL Special Service Identifier: %s, Ignore It",service->identifier); */
		return SUCCESS_RETURN;
	}
	if((strlen(service->identifier) == strlen(KK_TSL_SPECIAL_SERVICE_GET_IDENTIFIER)) &&
		(memcmp(service->identifier, KK_TSL_SPECIAL_SERVICE_GET_IDENTIFIER,
			strlen(KK_TSL_SPECIAL_SERVICE_GET_IDENTIFIER)) == 0))
	{
		isGetService = 1;
	}
	//Parse Output Data (Optional)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_OUTPUTDATA, strlen(KK_TSL_KEY_OUTPUTDATA), &lite_item);
	if (res == SUCCESS_RETURN && lite_cjson_is_array(&lite_item)) {
		//INFO_PRINT("services output Number: %d\n", lite_item.size);
		service->output_data_number = lite_item.size;
		res = _kk_tsl_service_outputdatas_parse(shadow, service, &lite_item);
		if (res != SUCCESS_RETURN) {
			return FAIL_RETURN;
		}
	}

	//Parse Input Data (Optional)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_INPUTDATA, strlen(KK_TSL_KEY_INPUTDATA), &lite_item);
	if (res == SUCCESS_RETURN && lite_cjson_is_array(&lite_item)) {
		service->input_data_number = lite_item.size;
		//INFO_PRINT("services input Number: %d\n", lite_item.size);
		if(isGetService && service->input_data_number > 0){
			res = _kk_tsl_service_inputdatas_get_parse(shadow, service, &lite_item);
		}else
		{
			res = _kk_tsl_service_inputdatas_parse(shadow, service, &lite_item);
		}
	}

	return res;
}

static int _kk_tsl_services_parse(_IN_ kk_tsl_t *shadow, _IN_ lite_cjson_t *root)
{
	int res = 0, index = 0;
	lite_cjson_t lite_services, lite_service;
	kk_tsl_service_t *service = NULL;

	memset(&lite_services, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_SERVICES, strlen(KK_TSL_KEY_SERVICES), &lite_services);
	if (res == SUCCESS_RETURN) {
		if (!lite_cjson_is_array(&lite_services)) {
			return JSON_PARSE_FAILED;
		}
	} else {
		return SUCCESS_RETURN;
	}

	INFO_PRINT("services Number: %d\n", lite_services.size);
	if (lite_services.size == 0) {
		return SUCCESS_RETURN;
	}

	//Allocate Memory For TSL Services Struct
	shadow->service_number = lite_services.size;
	shadow->services = malloc(sizeof(kk_tsl_service_t) * (lite_services.size));
	if (shadow->services == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(shadow->services, 0, sizeof(kk_tsl_service_t) * (lite_services.size));

	for (index = 0; index < lite_services.size; index++) {
		memset(&lite_service, 0, sizeof(lite_cjson_t));
		service = shadow->services + index;

		res = lite_cjson_array_item(&lite_services, index, &lite_service);
		if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_service)) {
			return FAIL_RETURN;
		}

		//printf(" Index: %d\n", index);
		_kk_tsl_service_parse(shadow, service, &lite_service);
	}

	return SUCCESS_RETURN;
}

static int _kk_tsl_data_struct_search(_IN_ kk_tsl_data_t *input, _IN_ char *key,
		_IN_ int key_len, _OU_ kk_tsl_data_t **output, _OU_ int *index)
{
	int res = 0, item_index = 0, deli_offset = 0, partial_offset = 0;
	int partial_input_len = 0, array_input_len = 0, array_index = 0;
	kk_tsl_data_t *data_item = NULL;

	/* dm_log_debug("Current Key: %.*s",key_len,key); */

	kk_tsl_data_value_complex_t *complex_struct = (kk_tsl_data_value_complex_t *)input->data_value.value;

	res = kk_utils_memtok(key, key_len, KK_MSG_KEY_DELIMITER, 1, &deli_offset);
	if (res != SUCCESS_RETURN) {
		deli_offset = key_len;
	}

	partial_offset = deli_offset;
	res = kk_utils_strarr_index(key, deli_offset, &partial_input_len, &array_input_len, &array_index);
	if (res == SUCCESS_RETURN) {
		/* dm_log_debug("Current Index: %d",array_index); */
		partial_offset = partial_input_len;
	}

	for (item_index = 0; item_index < complex_struct->size; item_index++) {
		data_item = (kk_tsl_data_t *)complex_struct->value + item_index;
		if (strlen(data_item->identifier) != partial_offset ||
			memcmp(data_item->identifier, key, partial_offset) != 0) {
			continue;
		}

		switch (data_item->data_value.type) {
			case KK_TSL_DATA_TYPE_INT:
			case KK_TSL_DATA_TYPE_FLOAT:
			case KK_TSL_DATA_TYPE_DOUBLE:
			case KK_TSL_DATA_TYPE_TEXT:
			case KK_TSL_DATA_TYPE_ENUM:
			case KK_TSL_DATA_TYPE_DATE:
			case KK_TSL_DATA_TYPE_BOOL: {
				if (partial_input_len != 0 || deli_offset != key_len) {
					return FAIL_RETURN;
				}
				if (output) {
					*output = data_item;
				}
				return SUCCESS_RETURN;
			}
			break;
			case KK_TSL_DATA_TYPE_ARRAY: {
				int key_offset = (deli_offset == key_len) ? (deli_offset - 1) : (deli_offset + 1);
				int key_len_offset = (deli_offset == key_len) ? (key_len) : (deli_offset + 1);
				if ((partial_input_len == 0) && (deli_offset == key_len)) {
					if (output) {
						*output = data_item;
					}
					return SUCCESS_RETURN;
				}
				if (partial_input_len == 0) {
					return FAIL_RETURN;
				}
				return _kk_tsl_data_array_search(data_item, array_index, key + key_offset, key_len - key_len_offset, output, index);
			}
			case KK_TSL_DATA_TYPE_STRUCT: {
				if (deli_offset == key_len) {
					if (output) {
						*output = data_item;
					}
					return SUCCESS_RETURN;
				}
				if (partial_input_len != 0) {
					return FAIL_RETURN;
				}
				return _kk_tsl_data_struct_search(data_item, key + deli_offset + 1, key_len - deli_offset - 1, output, index);
			}
			default:
				printf("Unknown Data Type");
				break;
		}
	}

	return FAIL_RETURN;
}

static int _kk_tsl_data_array_search(_IN_ kk_tsl_data_t *input, _IN_ int input_index, _IN_ char *key,
		_IN_ int key_len, _OU_ kk_tsl_data_t **output, _OU_ int *output_index)
{
	int res = 0, deli_offset = 0;

	kk_tsl_data_value_complex_t *complex_struct = (kk_tsl_data_value_complex_t *)input->data_value.value;
	/* dm_log_debug("Current Key: %s, Len: %d",key,key_len);
	dm_log_debug("Current Item Identifier: %s",input->identifier); */
	res = kk_utils_memtok(key, key_len, KK_MSG_KEY_DELIMITER, 1, &deli_offset);
	if (res != SUCCESS_RETURN) {
		deli_offset = key_len;
	}

	switch (complex_struct->type) {
		case KK_TSL_DATA_TYPE_INT:
		case KK_TSL_DATA_TYPE_FLOAT:
		case KK_TSL_DATA_TYPE_DOUBLE:
		case KK_TSL_DATA_TYPE_TEXT:
		case KK_TSL_DATA_TYPE_ENUM:
		case KK_TSL_DATA_TYPE_DATE:
		case KK_TSL_DATA_TYPE_BOOL: {
			if (deli_offset != key_len) {
				return FAIL_RETURN;
			}
			if (output) {
				*output = input;
			}
			if (output_index) {
				*output_index = input_index;
			}
			return SUCCESS_RETURN;
		}
		break;
		case KK_TSL_DATA_TYPE_STRUCT: {
			kk_tsl_data_t *search_data = NULL;
			if (complex_struct->value == NULL) {
				return FAIL_RETURN;
			}
			search_data = (kk_tsl_data_t *)complex_struct->value + input_index;
			return _kk_tsl_data_struct_search(search_data, key, deli_offset, output, output_index);
		}
		break;
		default:
			printf("Unknown Data Type: %d", complex_struct->type);
			break;
	}

	return FAIL_RETURN;
}

int _kk_tsl_property_search(_IN_ kk_tsl_t *shadow, _IN_ char *key, _IN_ int key_len,
									_OU_ kk_tsl_data_t **property, _OU_ int *index)
{
	int res = 0, item_index = 0;
	kk_tsl_data_t *property_item = NULL;

	if (shadow == NULL || key == NULL || key_len <= 0) {
		return INVALID_PARAMETER;
	}

	if (shadow->property_number == 0 || shadow->properties == NULL) {
		return TSL_PROPERTY_NOT_EXIST;
	}

	for (item_index = 0; item_index < shadow->property_number; item_index++) {
		property_item = shadow->properties + item_index;
		res = kk_tsl_data_search(property_item, key, key_len, property, index);
		if (res == SUCCESS_RETURN) {
			return SUCCESS_RETURN;
		}
	}

	return FAIL_RETURN;
}

int kk_tsl_get_property_data(_IN_ kk_tsl_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **data)
{
	int res = 0;

	if (shadow == NULL || key == NULL || key_len <= 0 || data == NULL || *data != NULL) {
		return INVALID_PARAMETER;
	}

	res = _kk_tsl_property_search(shadow, key, key_len, (kk_tsl_data_t **)data, NULL);
	if (res != SUCCESS_RETURN) {
		return TSL_PROPERTY_NOT_EXIST;
	}

	return SUCCESS_RETURN;
}


int kk_tsl_data_search(_IN_ kk_tsl_data_t *input, _IN_ char *key,
								_IN_ int key_len, _OU_ kk_tsl_data_t **output, _OU_ int *index)
{
	int res = 0, deli_offset = 0, partial_offset = 0;
	int partial_input_len = 0, array_input_len = 0, array_index = 0;

	if (input == NULL || key == NULL || key_len <= 0) {
		return INVALID_PARAMETER;
	}
	res = kk_utils_memtok(key, key_len, KK_MSG_KEY_DELIMITER, 1, &deli_offset);
	if (res != SUCCESS_RETURN) {
		deli_offset = key_len;
	}

	partial_offset = deli_offset;
	res = kk_utils_strarr_index(key, deli_offset, &partial_input_len, &array_input_len, &array_index);
	if (res == SUCCESS_RETURN) {
		/* dm_log_debug("Current Index: %d",array_index); */
		partial_offset = partial_input_len;
	}

	/* dm_log_debug("Current Input Identifier: %s",input->identifier);
	dm_log_debug("Current Compare Key: %.*s",partial_offset,key); */

	if (strlen(input->identifier) != partial_offset ||
		memcmp(input->identifier, key, partial_offset) != 0) {
		return FAIL_RETURN;
	}
	switch (input->data_value.type) {
		case KK_TSL_DATA_TYPE_INT:
		case KK_TSL_DATA_TYPE_FLOAT:
		case KK_TSL_DATA_TYPE_DOUBLE:
		case KK_TSL_DATA_TYPE_TEXT:
		case KK_TSL_DATA_TYPE_ENUM:
		case KK_TSL_DATA_TYPE_DATE:
		case KK_TSL_DATA_TYPE_BOOL: {
			if (output) {
				*output = input;
			}
			return SUCCESS_RETURN;
		}
		break;
		case KK_TSL_DATA_TYPE_ARRAY: {
			int key_offset = (deli_offset == key_len) ? (deli_offset - 1) : (deli_offset + 1);
			int key_len_offset = (deli_offset == key_len) ? (key_len) : (deli_offset + 1);
            if ((partial_input_len == 0) && (deli_offset == key_len)) {
                if (output) {
                    *output = input;
                }
                return SUCCESS_RETURN;
            }
            if (partial_input_len == 0) {
                return FAIL_RETURN;
            }
            return _kk_tsl_data_array_search(input, array_index, key + key_offset, key_len - key_len_offset, output, index);
		}
		break;
        case KK_TSL_DATA_TYPE_STRUCT: {
            if (deli_offset == key_len) {
                if (output) {
                    *output = input;
                }
                return SUCCESS_RETURN;
            }
            if (partial_input_len != 0) {
                return FAIL_RETURN;
            }
            return _kk_tsl_data_struct_search(input, key + deli_offset + 1, key_len - deli_offset - 1, output, index);
		}
		break;
		default:
			printf("Unknow Data Type");
			break;
	}

	return FAIL_RETURN;
}

static int _kk_tsl_int_insert_json_item(_IN_ kk_tsl_data_t *data, _IN_ lite_cjson_item_t *lite)
{
	lite_cjson_add_number_to_object(lite, data->identifier, data->data_value.value_int);

	return SUCCESS_RETURN;
}
static int _kk_tsl_float_insert_json_item(_IN_ kk_tsl_data_t *data, _IN_ lite_cjson_item_t *lite)
{
	lite_cjson_add_number_to_object(lite, data->identifier, data->data_value.value_float);

	return SUCCESS_RETURN;
}
static int _kk_tsl_double_insert_json_item(_IN_ kk_tsl_data_t *data, _IN_ lite_cjson_item_t *lite)
{
	lite_cjson_add_number_to_object(lite, data->identifier, data->data_value.value_double);

	return SUCCESS_RETURN;
}
static int _kk_tsl_string_insert_json_item(_IN_ kk_tsl_data_t *data, _IN_ lite_cjson_item_t *lite)
{
	char *value = (data->data_value.value == NULL) ? ("") : (data->data_value.value);
	lite_cjson_add_string_to_object(lite, data->identifier, value);

	return SUCCESS_RETURN;
}
static int _kk_tsl_array_insert_json_item(_IN_ kk_tsl_data_t *data, _IN_ lite_cjson_item_t *lite);
static int _kk_tsl_struct_insert_json_item(_IN_ kk_tsl_data_t *data, _IN_ lite_cjson_item_t *lite);
static int _kk_tsl_data_insert_json_item(_IN_ kk_tsl_data_t *data, _IN_ lite_cjson_item_t *lite);
static int _kk_check_data(_IN_ kk_tsl_data_t *data)
{
	int index = 0;
	kk_tsl_data_t *current_data = NULL;	
	kk_tsl_data_value_complex_t *complex_struct = NULL;
	int is_valid = 0;

	if(data == NULL){
		return INVALID_PARAMETER;
	}

	complex_struct = data->data_value.value;

	for (index = 0; index < complex_struct->size; index++) {
		current_data = (kk_tsl_data_t *)complex_struct->value + index;
		if(current_data->data_value.type == KK_TSL_DATA_TYPE_TEXT)
		{
			if(current_data->data_value.value != NULL){
				is_valid = 1;
			}
		}
		else{
			is_valid = 1;
		}
	}
	if(is_valid){
		return SUCCESS_RETURN;
	}
	return FAIL_RETURN;
}
static int _kk_tsl_array_insert_json_item(_IN_ kk_tsl_data_t *data, _IN_ lite_cjson_item_t *lite)
{
	int res = SUCCESS_RETURN, index = 0;
	lite_cjson_item_t *array = NULL, *array_item = NULL;
	kk_tsl_data_value_complex_t *complex_array = NULL;

	if (data == NULL || lite == NULL) {
		return INVALID_PARAMETER;
	}

	complex_array = data->data_value.value;

	if (lite->type == cJSON_Array) {
		array = lite_cjson_create_object();
		if (array == NULL) {
			return MEMORY_NOT_ENOUGH;
		}
	}

	array_item = lite_cjson_create_array();
	if (array_item == NULL) {
		if (array) {
			lite_cjson_delete(array);
		}
		return MEMORY_NOT_ENOUGH;
	}

	switch (complex_array->type) {
		case KK_TSL_DATA_TYPE_INT:
		case KK_TSL_DATA_TYPE_BOOL:
		case KK_TSL_DATA_TYPE_ENUM: {
			int value = 0;
			for (index = 0; index < complex_array->size; index++) {
				value = *((int *)(complex_array->value) + index);
				lite_cjson_add_item_to_array(array_item, lite_cjson_create_number((double)value));
			}
			if (lite->type == cJSON_Array) {
				lite_cjson_add_item_to_object(array, data->identifier, array_item);
				lite_cjson_add_item_to_array(lite, array);
			} else {
				lite_cjson_add_item_to_object(lite, data->identifier, array_item);
				lite_cjson_delete(array);
			}
		}
		break;
		case KK_TSL_DATA_TYPE_FLOAT: {
			float value = 0;
			for (index = 0; index < complex_array->size; index++) {
				value = *((float *)(complex_array->value) + index);
				lite_cjson_add_item_to_array(array_item, lite_cjson_create_number((double)value));
			}
			if (lite->type == cJSON_Array) {
				lite_cjson_add_item_to_object(array, data->identifier, array_item);
				lite_cjson_add_item_to_array(lite, array);
			} else {
				lite_cjson_add_item_to_object(lite, data->identifier, array_item);
				lite_cjson_delete(array);
			}
		}
		break;
		case KK_TSL_DATA_TYPE_DOUBLE: {
			double value = 0;
			for (index = 0; index < complex_array->size; index++) {
				value = *((double *)(complex_array->value) + index);
				lite_cjson_add_item_to_array(array_item, lite_cjson_create_number(value));
			}
			if (lite->type == cJSON_Array) {
				lite_cjson_add_item_to_object(array, data->identifier, array_item);
				lite_cjson_add_item_to_array(lite, array);
			} else {
				lite_cjson_add_item_to_object(lite, data->identifier, array_item);
				lite_cjson_delete(array);
			}
		}
		break;
		case KK_TSL_DATA_TYPE_TEXT:
		case KK_TSL_DATA_TYPE_DATE: {
			char *value = NULL;
			for (index = 0; index < complex_array->size; index++) {
				value = *((char **)(complex_array->value) + index);
				value = (value == NULL) ? ("") : (value);
				lite_cjson_add_item_to_array(array_item, lite_cjson_create_string((const char *)value));
			}
			if (lite->type == cJSON_Array) {
				lite_cjson_add_item_to_object(array, data->identifier, array_item);
				lite_cjson_add_item_to_array(lite, array);
			} else {
				lite_cjson_add_item_to_object(lite, data->identifier, array_item);
				lite_cjson_delete(array);
			}
		}
		break;
		case KK_TSL_DATA_TYPE_STRUCT: {
			kk_tsl_data_t *array_data = NULL;
			for (index = 0; index < complex_array->size; index++) {
				array_data = (kk_tsl_data_t *)(complex_array->value) + index;
				if (array_data && (_kk_check_data(array_data) == 0)) {
					_kk_tsl_struct_insert_json_item(array_data, array_item);
				}
			}

			if (lite->type == cJSON_Array) {
				lite_cjson_add_item_to_object(array, data->identifier, array_item);
				lite_cjson_add_item_to_array(lite, array);
			} else {
				lite_cjson_add_item_to_object(lite, data->identifier, array_item);
				lite_cjson_delete(array);
			}
		}
		break;
		default: {
			lite_cjson_delete(array_item);
			lite_cjson_delete(array);
		}
		break;
	}

	return res;
}

static int _kk_tsl_struct_insert_json_item(_IN_ kk_tsl_data_t *data, _IN_ lite_cjson_item_t *lite)
{
	int res = 0, index = 0;
	lite_cjson_item_t *lite_object = NULL, *lite_item = NULL;
	kk_tsl_data_t *current_data = NULL;
	kk_tsl_data_value_complex_t *complex_struct = NULL;

	if (data == NULL || lite == NULL) {
		return INVALID_PARAMETER;
	}

	if (lite->type == cJSON_Array) {
		lite_object = lite_cjson_create_object();
		if (lite_object == NULL) {
		return MEMORY_NOT_ENOUGH;
		}
	}

	lite_item = lite_cjson_create_object();
	if (lite_item == NULL) {
		lite_cjson_delete(lite_object);
		return MEMORY_NOT_ENOUGH;
	}

	complex_struct = data->data_value.value;

	for (index = 0; index < complex_struct->size; index++) {
		current_data = (kk_tsl_data_t *)complex_struct->value + index;
		_kk_tsl_data_insert_json_item(current_data, lite_item);
	}
	if (lite->type == cJSON_Array) {
		if (data->identifier) {
			lite_cjson_add_item_to_object(lite_object, data->identifier, lite_item);
			lite_cjson_add_item_to_array(lite, lite_object);
		} else {
			lite_cjson_add_item_to_array(lite, lite_item);
			lite_cjson_delete(lite_object);
		}
	} else {
		if (data->identifier) {
			lite_cjson_add_item_to_object(lite, data->identifier, lite_item);
			lite_cjson_delete(lite_object);
		} else {
			res = FAIL_RETURN;
			lite_cjson_delete(lite_item);
			lite_cjson_delete(lite_object);
		}
	}

	return res;
}

static int _kk_tsl_data_insert_json_item(_IN_ kk_tsl_data_t *data, _IN_ lite_cjson_item_t *lite)
{
	int res = 0;
	lite_cjson_item_t *data_object = NULL;
	if (data == NULL || lite == NULL) {
		return INVALID_PARAMETER;
	}

	if (lite->type == cJSON_Array) {
		data_object = lite_cjson_create_object();
		if (data_object == NULL) {
			return MEMORY_NOT_ENOUGH;
		}
	}

	switch (data->data_value.type) {
		case KK_TSL_DATA_TYPE_INT:
		case KK_TSL_DATA_TYPE_BOOL:
		case KK_TSL_DATA_TYPE_ENUM: {
			if (lite->type == cJSON_Array) {
				res = _kk_tsl_int_insert_json_item(data, data_object);
				if (res == SUCCESS_RETURN) {
					lite_cjson_add_item_to_array(lite, data_object);
				}
			} else {
				res = _kk_tsl_int_insert_json_item(data, lite);
				lite_cjson_delete(data_object);
			}
		}
		break;
		case KK_TSL_DATA_TYPE_FLOAT: {
			if (lite->type == cJSON_Array) {
				res = _kk_tsl_float_insert_json_item(data, data_object);
				if (res == SUCCESS_RETURN) {
					lite_cjson_add_item_to_array(lite, data_object);
				}
			} else {
				res = _kk_tsl_float_insert_json_item(data, lite);
				lite_cjson_delete(data_object);
			}
		}
		break;
		case KK_TSL_DATA_TYPE_DOUBLE: {
			if (lite->type == cJSON_Array) {
				res = _kk_tsl_double_insert_json_item(data, data_object);
				if (res == SUCCESS_RETURN) {
					lite_cjson_add_item_to_array(lite, data_object);
				}
			} else {
				res = _kk_tsl_double_insert_json_item(data, lite);
				lite_cjson_delete(data_object);
			}
		}
		break;
		case KK_TSL_DATA_TYPE_TEXT:
		case KK_TSL_DATA_TYPE_DATE: {
			if (lite->type == cJSON_Array) {
				res = _kk_tsl_string_insert_json_item(data, data_object);
				if (res == SUCCESS_RETURN) {
					lite_cjson_add_item_to_array(lite, data_object);
				}
			} else {
				res = _kk_tsl_string_insert_json_item(data, lite);
				lite_cjson_delete(data_object);
			}
		}
		break;
		case KK_TSL_DATA_TYPE_ARRAY: {
			/* dm_log_debug("DM_SHW_DATA_TYPE_ARRAY"); */
			if (lite->type == cJSON_Array) {
				res = _kk_tsl_array_insert_json_item(data, data_object);
				if (res == SUCCESS_RETURN) {
					lite_cjson_add_item_to_array(lite, data_object);
				}
			} else {
				res = _kk_tsl_array_insert_json_item(data, lite);
				lite_cjson_delete(data_object);
			}
		}
		break;
		case KK_TSL_DATA_TYPE_STRUCT: {
			/* dm_log_debug("DM_SHW_DATA_TYPE_STRUCT"); */
			if (lite->type == cJSON_Array) {
				res = _kk_tsl_struct_insert_json_item(data, data_object);
				if (res == SUCCESS_RETURN) {
					lite_cjson_add_item_to_array(lite, data_object);
				}
			} else {
				res = _kk_tsl_struct_insert_json_item(data, lite);
				lite_cjson_delete(data_object);
			}
		}
		break;
		default:
			lite_cjson_delete(data_object);
			res = FAIL_RETURN;
			break;
	}

	return res;
}

int kk_tsl_assemble_property(_IN_ kk_tsl_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
		_IN_ lite_cjson_item_t *lite)
{
	int res = 0, index = 0,indexE = 0;
	kk_tsl_event_t *property = NULL;
	kk_tsl_data_t *output_data = NULL;

	if (shadow == NULL || identifier == NULL || identifier_len <= 0 || lite == NULL || lite->type != cJSON_Object) {
		return INVALID_PARAMETER;
	}

	for (index = 0; index < shadow->event_number; index++) {
		property = shadow->events + index;
		if(strcmp(property->identifier,"property") == 0 ||
			strcmp(property->identifier,"post") == 0)
		{
			for(indexE = 0; indexE < property->output_data_number;indexE++){
				output_data = property->output_datas + indexE;
				if ((strlen(output_data->identifier) == identifier_len) &&
					(memcmp(output_data->identifier, identifier, identifier_len) == 0)) {
					/* dm_log_debug("Property Found: %.*s",identifier_len,identifier); */
					break;
				}
				if (indexE == property->output_data_number) {
					printf("Property Not Found: %.*s\n", identifier_len, identifier);
					return FAIL_RETURN;
				}
			}
		}
	}

	res = _kk_tsl_data_insert_json_item(output_data, lite);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	return SUCCESS_RETURN;
}
int kk_tsl_assemble_event_output(_IN_ kk_tsl_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
		_IN_ lite_cjson_item_t *lite)
{
	int res = 0, index = 0;
	kk_tsl_data_t *event_outputdata = NULL;
	kk_tsl_event_t *event = NULL;

	if (shadow == NULL || identifier == NULL || identifier_len <= 0 || lite == NULL || lite->type != cJSON_Object) {
		return INVALID_PARAMETER;
	}

	for (index = 0; index < shadow->event_number; index++) {
		event = shadow->events + index;
		if ((strlen(event->identifier) == identifier_len) &&
			(memcmp(event->identifier, identifier, identifier_len) == 0)) {
			/* dm_log_debug("Event Found: %.*s",identifier_len,identifier); */
			break;
		}
	}

	if (index == shadow->event_number) {
		printf("Event Not Found: %.*s\n", identifier_len, identifier);
		return FAIL_RETURN;
	}

	for (index = 0; index < event->output_data_number; index++) {
		event_outputdata = event->output_datas + index;

		res = _kk_tsl_data_insert_json_item(event_outputdata, lite);
		if (res != SUCCESS_RETURN) {
			return FAIL_RETURN;
		}
	}

	return SUCCESS_RETURN;
}

int kk_tsl_assemble_service_output(_IN_ kk_tsl_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
		_IN_ lite_cjson_item_t *lite)
{
	int res = 0, index = 0;
	kk_tsl_data_t *service_outputdata = NULL;
	kk_tsl_service_t *service = NULL;

	if (shadow == NULL || identifier == NULL || identifier_len <= 0 || lite == NULL || lite->type != cJSON_Object) {
		return INVALID_PARAMETER;
	}

	for (index = 0; index < shadow->service_number; index++) {
		service = shadow->services + index;
		if ((strlen(service->identifier) == identifier_len) &&
			(memcmp(service->identifier, identifier, identifier_len) == 0)) {
			/* dm_log_debug("Service Found: %.*s",identifier_len,identifier); */
			break;
		}
	}

	if (index == shadow->service_number) {
		printf("Service Not Found: %.*s", identifier_len, identifier);
		return FAIL_RETURN;
	}

	for (index = 0; index < service->output_data_number; index++) {
		service_outputdata = service->output_datas + index;

		res = _kk_tsl_data_insert_json_item(service_outputdata, lite);
		if (res != SUCCESS_RETURN) {
			return FAIL_RETURN;
		}
	}

	return SUCCESS_RETURN;
}

/******************************************************************************/
/* 函 数 名:	_kk_tsl_sleeptime_parse													    */
/* 描   述:  解析是否是休眠设备																	*/							   
/* 输入参数:    root:  物模型字串									   								*/
/* 返 回 值:	返回0表示否，1表示是						 											*/
/******************************************************************************/
static int _kk_tsl_sleeptime_parse(_IN_ lite_cjson_t *root)
{
	int res = 0;
	lite_cjson_t lite_item;
	lite_cjson_t lite_item_sleeptime;

	//Parse Identifier (Mandatory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_PROFILE, strlen(KK_TSL_KEY_PROFILE), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
		return 0;
	}
	res = lite_cjson_object_item(&lite_item, KK_TSL_KEY_SLEEPTIME, strlen(KK_TSL_KEY_SLEEPTIME), &lite_item_sleeptime);
	if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item_sleeptime)) {
		return 0;
	}
	return 1;
}
/******************************************************************************/
/* 函 数 名:	_kk_tsl_heartbeat_parse													    */
/* 描	 述:  解析心跳时间																	*/							   
/* 输入参数:    root:  物模型字串									   								*/
/* 输出参数:    heartbeat:  心跳时间									   								*/
/* 返 回 值:	返回0表示成功，其他表示失败					 											*/
/******************************************************************************/   
static int _kk_tsl_heartbeat_parse(_OU_ int *heartbeat, _IN_ lite_cjson_t *root)
{
	int res = 0;
	lite_cjson_t lite_item;
	lite_cjson_t lite_item_heartbeat;

	//Parse Identifier (Mandatory)
	memset(&lite_item, 0, sizeof(lite_cjson_t));
	res = lite_cjson_object_item(root, KK_TSL_KEY_PROFILE, strlen(KK_TSL_KEY_PROFILE), &lite_item);
	if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_item)) {
		return JSON_PARSE_FAILED;
	}
	res = lite_cjson_object_item(&lite_item, KK_TSL_KEY_HEARTBEAT, strlen(KK_TSL_KEY_HEARTBEAT), &lite_item_heartbeat);
	if (res != SUCCESS_RETURN || !lite_cjson_is_string(&lite_item_heartbeat)) {
		return JSON_PARSE_FAILED;
	}
	*heartbeat = atoi(lite_item_heartbeat.value)*2+120;//一般是心跳时间的2倍再加两分钟
	return SUCCESS_RETURN;
}
int kk_tsl_create(_IN_ const char *tsl, _IN_ int tsl_len, _OU_ kk_tsl_t **shadow,_OU_ int *heartbeat,_OU_ int *isDormancyDev)
{
	int res = 0;
	lite_cjson_t lite_root;

	INFO_PRINT("kk_tsl_create start!!\n");
	if (shadow == NULL || *shadow != NULL || tsl == NULL || tsl_len <= 0) {
		return INVALID_PARAMETER;
	}

	*shadow = malloc(sizeof(kk_tsl_t));
	if (*shadow == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(*shadow, 0, sizeof(kk_tsl_t));

	//Parse Root
	memset(&lite_root, 0, sizeof(lite_root));
	res = lite_cjson_parse(tsl, tsl_len, &lite_root);
	if (res != SUCCESS_RETURN || !lite_cjson_is_object(&lite_root)) {
		free(*shadow);
		return JSON_PARSE_FAILED;
	}
	*isDormancyDev = _kk_tsl_sleeptime_parse(&lite_root);

	// Parse heartbeat time
	_kk_tsl_heartbeat_parse(heartbeat,&lite_root);
	
	//Parse Properties (Mandatory)
	res = _kk_tsl_properties_parse(*shadow, &lite_root);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	//Parse Events (Mandatory)
	res = _kk_tsl_events_parse(*shadow, &lite_root);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}

	//Parse Services (Mandatory)
	res = _kk_tsl_services_parse(*shadow, &lite_root);
	if (res != SUCCESS_RETURN) {
		return FAIL_RETURN;
	}
	INFO_PRINT("kk_tsl_create successful!!\n");

	return SUCCESS_RETURN;
}



