#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);
		}

	}


	
	

	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 Or Get */
    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;
}



