#include "kk_tsl_common.h"

typedef int (*kk_tsl_data_set)(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
typedef int (*kk_tsl_array_set)(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                _IN_ int index);
typedef int (*kk_tsl_data_get)(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value);
typedef int (*kk_tsl_array_get)(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index);
typedef void (*kk_tsl_data_free)(_IN_ kk_tsl_data_value_t *data_value);
typedef void (*kk_tsl_array_free)(_IN_ kk_tsl_data_value_t *data_value);
typedef void (*kk_tsl_data_print)(_IN_ kk_tsl_data_value_t *data_value);


typedef struct {
    kk_tsl_data_type_e type;
    const char *name;
    kk_tsl_data_set    func_set;
    kk_tsl_array_set   func_array_set;
    kk_tsl_data_get    func_get;
    kk_tsl_array_get   func_array_get;
    kk_tsl_data_free   func_free;
    kk_tsl_array_free  func_array_free;
} kk_tsl_data_type_mapping_t;
//Data Set
static int _kk_tsl_int_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
static int _kk_tsl_float_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
static int _kk_tsl_double_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
static int _kk_tsl_text_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
static int _kk_tsl_enum_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
static int _kk_tsl_date_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);
static int _kk_tsl_bool_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len);

//Array Data Set
static int _kk_tsl_array_int_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                 _IN_ int index);
static int _kk_tsl_array_float_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                   _IN_ int index);
static int _kk_tsl_array_double_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                    _IN_ int index);
static int _kk_tsl_array_text_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                  _IN_ int index);
static int _kk_tsl_array_enum_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                  _IN_ int index);
static int _kk_tsl_array_date_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                  _IN_ int index);
static int _kk_tsl_array_bool_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                  _IN_ int index);

//Data Get
static int _kk_tsl_int_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value);
static int _kk_tsl_float_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value);
static int _kk_tsl_double_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value);
static int _kk_tsl_text_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value);
static int _kk_tsl_enum_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value);
static int _kk_tsl_date_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value);
static int _kk_tsl_bool_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value);

//Array Data Get
static int _kk_tsl_array_int_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index);
static int _kk_tsl_array_float_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index);
static int _kk_tsl_array_double_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index);
static int _kk_tsl_array_text_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index);
static int _kk_tsl_array_enum_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index);
static int _kk_tsl_array_date_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index);
static int _kk_tsl_array_bool_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index);

//Data Free
static void _kk_tsl_int_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_float_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_double_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_text_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_enum_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_date_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_bool_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_array_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_struct_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_property_free(_IN_ kk_tsl_data_t *property);

//Array Data Free
static void _kk_tsl_array_int_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_array_float_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_array_double_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_array_text_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_array_enum_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_array_date_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_array_bool_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_array_array_free(_IN_ kk_tsl_data_value_t *data_value);
static void _kk_tsl_array_struct_free(_IN_ kk_tsl_data_value_t *data_value);

static kk_tsl_data_type_mapping_t g_iotx_data_type_mapping[] = {
    {KK_TSL_DATA_TYPE_NONE,     "none",     NULL,                   NULL,                        NULL,                    NULL,                         NULL,                    NULL             },
    {KK_TSL_DATA_TYPE_INT,      "int",      _kk_tsl_int_set,      _kk_tsl_array_int_set,      _kk_tsl_int_get,      _kk_tsl_array_int_get,      _kk_tsl_int_free,      _kk_tsl_array_int_free     },
    {KK_TSL_DATA_TYPE_FLOAT,    "float",    _kk_tsl_float_set,    _kk_tsl_array_float_set,    _kk_tsl_float_get,    _kk_tsl_array_float_get,    _kk_tsl_float_free,    _kk_tsl_array_float_free,  },
    {KK_TSL_DATA_TYPE_DOUBLE,   "double",   _kk_tsl_double_set,   _kk_tsl_array_double_set,   _kk_tsl_double_get,   _kk_tsl_array_double_get,   _kk_tsl_double_free,   _kk_tsl_array_double_free, },
    {KK_TSL_DATA_TYPE_TEXT,     "text",     _kk_tsl_text_set,     _kk_tsl_array_text_set,     _kk_tsl_text_get,     _kk_tsl_array_text_get,     _kk_tsl_text_free,     _kk_tsl_array_text_free,   },
    {KK_TSL_DATA_TYPE_ENUM,     "enum",     _kk_tsl_enum_set,     _kk_tsl_array_enum_set,     _kk_tsl_enum_get,     _kk_tsl_array_enum_get,     _kk_tsl_enum_free,     _kk_tsl_array_enum_free,   },
    {KK_TSL_DATA_TYPE_DATE,     "date",     _kk_tsl_date_set,     _kk_tsl_array_date_set,     _kk_tsl_date_get,     _kk_tsl_array_date_get,     _kk_tsl_date_free,     _kk_tsl_array_date_free,   },
    {KK_TSL_DATA_TYPE_BOOL,     "bool",     _kk_tsl_bool_set,     _kk_tsl_array_bool_set,     _kk_tsl_bool_get,     _kk_tsl_array_bool_get,     _kk_tsl_bool_free,     _kk_tsl_array_bool_free,   },
    {KK_TSL_DATA_TYPE_ARRAY,    "array",    NULL,                 NULL,                       NULL,                 NULL,                       _kk_tsl_array_free,    _kk_tsl_array_array_free,  },
    {KK_TSL_DATA_TYPE_STRUCT,   "struct",   NULL,                 NULL,                       NULL,                 NULL,                       _kk_tsl_struct_free,   _kk_tsl_array_struct_free, }
};

static int _kk_tsl_float_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
{
    float float_set = (value == NULL) ? (0) : (*(float *)value);

    data_value->value_float = float_set;
    //printf("Current Float Value Be Set(Float): %f\n", data_value->value_float);

    return SUCCESS_RETURN;
}

static int _kk_tsl_double_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
{
    double double_set = (value == NULL) ? (0) : (*(double *)value);

    data_value->value_double = double_set;
    //printf("Current Double Value Be Set(Double): %f\n", data_value->value_double);

    return SUCCESS_RETURN;
}

static int _kk_tsl_text_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
{
    int res = 0;
    char *value_set = (value == NULL) ? ("NULL") : ((char *)value);
    int value_set_len = (value == NULL) ? (strlen("NULL")) : (value_len);

    if (data_value->value) {
        free(data_value->value);
        data_value->value = NULL;
    }
    res = kk_utils_copy(value_set, value_set_len, &data_value->value, value_set_len + 1);
    if (res != SUCCESS_RETURN) {
        return MEMORY_NOT_ENOUGH;
    }
    //printf("Current Text Value Be Set(String): %s\n", data_value->value);

    return SUCCESS_RETURN;
}

static int _kk_tsl_enum_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
{
    int enum_set = (value == NULL) ? (0) : (*(int *)value);

    enum_set = (enum_set < 0) ? (0) : (enum_set);

    data_value->value_int = enum_set;
    //printf("Current Enum Value Be Set(Enum): %d\n", data_value->value_int);

    return SUCCESS_RETURN;
}

static int _kk_tsl_date_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
{
    int res = 0;
    char *value_set = (value == NULL) ? ("NULL") : ((char *)value);
    int value_set_len = (value == NULL) ? (strlen("NULL")) : (value_len);

    if (data_value->value) {
        free(data_value->value);
        data_value->value = NULL;
    }
    res = kk_utils_copy(value_set, value_set_len, &data_value->value, value_set_len + 1);
    if (res != SUCCESS_RETURN) {
        return MEMORY_NOT_ENOUGH;
    }
    //printf("Current Date Value Be Set(String): %s\n", data_value->value);

    return SUCCESS_RETURN;
}

static int _kk_tsl_bool_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
{
    int int_set = (value == NULL) ? (0) : (*(int *)value);

    int_set = (int_set == 0) ? (int_set) : ((int_set == 1) ? (int_set) : (0));

    data_value->value_int = int_set;
    //printf("Current Bool Value Be Set(Bool): %d\n", data_value->value_int);

    return SUCCESS_RETURN;
}
static int _kk_tsl_int_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
{
    int int_set = (value == NULL) ? (0) : (*(int *)value);

    data_value->value_int = int_set;
    //printf("Current Int Value Be Set(Int): %d\n", data_value->value_int);

    return SUCCESS_RETURN;
}
static int _kk_tsl_array_text_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                  _IN_ int index)
{
    int res = 0;
    kk_tsl_data_value_complex_t *complex_array = data_value->value;
    char *text_set = (value == NULL) ? ("NULL") : ((char *)value);
    int value_set_len = (value == NULL) ? (strlen("NULL")) : (value_len);

    if (*((char **)(complex_array->value) + index)) {
        free(*((char **)(complex_array->value) + index));
        *((char **)(complex_array->value) + index) = NULL;
    }

    res = kk_utils_copy(text_set, value_set_len, (void **)((char **)(complex_array->value) + index), value_set_len + 1);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
    //printf("Current Array Value Be Set(Text String), Index: %d, Value: %s\n", index,
                 //*((char **)(complex_array->value) + index));

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_enum_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                  _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;
    int int_set = (value == NULL) ? (0) : (*(int *)value);

    *((int *)(complex_array->value) + index) = int_set;
    //printf("Current Array Value Be Set(Enum), Index: %d, Value: %d\n", index, *((int *)(complex_array->value) + index));

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_date_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                  _IN_ int index)
{
    int res = 0;
    kk_tsl_data_value_complex_t *complex_array = data_value->value;
    char *text_set = (value == NULL) ? ("NULL") : ((char *)value);
    int value_set_len = (value == NULL) ? (strlen("NULL")) : (value_len);

    if (*((char **)(complex_array->value) + index)) {
        free(*((char **)(complex_array->value) + index));
        *((char **)(complex_array->value) + index) = NULL;
    }

    res = kk_utils_copy(text_set, value_set_len, (void **)((char **)(complex_array->value) + index), value_set_len + 1);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
    //printf("Current Array Value Be Set(Date String), Index: %d, Value: %s\n", index,
                 //*((char **)(complex_array->value) + index));

    return SUCCESS_RETURN;
}

static int _kk_tsl_float_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value)
{
    *(float *)(value) = data_value->value_float;
    return SUCCESS_RETURN;
}

static int _kk_tsl_double_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value)
{
    *(double *)(value) = data_value->value_double;
    return SUCCESS_RETURN;
}

static int _kk_tsl_text_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value)
{
    int res = 0;

    if (*(char **)value != NULL || data_value->value == NULL) {
        return FAIL_RETURN;
    }

    res = kk_utils_copy_direct(data_value->value, strlen(data_value->value), (void **)value, strlen(data_value->value) + 1);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    return SUCCESS_RETURN;
}

static int _kk_tsl_enum_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value)
{
    *(int *)(value) = data_value->value_int;
    return SUCCESS_RETURN;
}

static int _kk_tsl_date_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value)
{
    int res = 0;

    if (*(char **)value != NULL || data_value->value == NULL) {
        return FAIL_RETURN;
    }

    res = kk_utils_copy_direct(data_value->value, strlen(data_value->value), (void **)value, strlen(data_value->value) + 1);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    return SUCCESS_RETURN;
}

static int _kk_tsl_bool_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value)
{
    *(int *)(value) = data_value->value_int;
    return SUCCESS_RETURN;
}
static int _kk_tsl_array_int_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    if (complex_array->value == NULL || ((int *)(complex_array->value) + index) == NULL) {
        return INVALID_PARAMETER;
    }

    *((int *)value) = *((int *)(complex_array->value) + index);

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_float_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    if (complex_array->value == NULL || ((float *)(complex_array->value) + index) == NULL) {
        return INVALID_PARAMETER;
    }

    *((float *)value) = *((float *)(complex_array->value) + index);

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_double_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    if (complex_array->value == NULL || ((double *)(complex_array->value) + index) == NULL) {
        return INVALID_PARAMETER;
    }

    *((double *)value) = *((double *)(complex_array->value) + index);

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_text_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index)
{
    int res = 0;
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    if (complex_array->value == NULL || *((char **)(complex_array->value) + index) == NULL || *(char **)value != NULL) {
        return INVALID_PARAMETER;
    }

    res = kk_utils_copy_direct(*((char **)(complex_array->value) + index),
                               strlen(*((char **)(complex_array->value) + index)),
                               (void **)value, strlen(*((char **)(complex_array->value) + index)) + 1);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_enum_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    if (complex_array->value == NULL || ((int *)(complex_array->value) + index) == NULL) {
        return INVALID_PARAMETER;
    }

    *((int *)value) = *((int *)(complex_array->value) + index);

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_date_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index)
{
    int res = 0;
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    if (complex_array->value == NULL || *((char **)(complex_array->value) + index) == NULL || *(char **)value != NULL) {
        return INVALID_PARAMETER;
    }

    res = kk_utils_copy_direct(*((char **)(complex_array->value) + index),
                               strlen(*((char **)(complex_array->value) + index)),
                               (void **)value, strlen(*((char **)(complex_array->value) + index)) + 1);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_bool_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    if (complex_array->value == NULL || ((int *)(complex_array->value) + index) == NULL) {
        return INVALID_PARAMETER;
    }

    *((int *)value) = *((int *)(complex_array->value) + index);

    return SUCCESS_RETURN;
}
static void _kk_tsl_int_free(_IN_ kk_tsl_data_value_t *data_value)
{
    //Free Value
    //if (data_value->value) {DM_free(data_value->value);data_value->value = NULL;}
}

static void _kk_tsl_float_free(_IN_ kk_tsl_data_value_t *data_value)
{
    //Free Value
    //if (data_value->value) {DM_free(data_value->value);data_value->value = NULL;}
}

static void _kk_tsl_double_free(_IN_ kk_tsl_data_value_t *data_value)
{
    //Free Value
    //if (data_value->value) {DM_free(data_value->value);data_value->value = NULL;}
}

static void _kk_tsl_text_free(_IN_ kk_tsl_data_value_t *data_value)
{
    //Free Value
    if (data_value->value) {
        free(data_value->value);
        data_value->value = NULL;
    }
}

static void _kk_tsl_enum_free(_IN_ kk_tsl_data_value_t *data_value)
{
    //Free Value
    //if (data_value->value) {DM_free(data_value->value);data_value->value = NULL;}
}

static void _kk_tsl_date_free(_IN_ kk_tsl_data_value_t *data_value)
{
    //Free Value
    if (data_value->value) {
        free(data_value->value);
        data_value->value = NULL;
    }
}

static void _kk_tsl_bool_free(_IN_ kk_tsl_data_value_t *data_value)
{
    //Free Value
    //if (data_value->value) {DM_free(data_value->value);data_value->value = NULL;}
}

static void _kk_tsl_array_int_free(_IN_ kk_tsl_data_value_t *data_value)
{

}

static void _kk_tsl_array_float_free(_IN_ kk_tsl_data_value_t *data_value)
{

}

static void _kk_tsl_array_double_free(_IN_ kk_tsl_data_value_t *data_value)
{

}

static void _kk_tsl_array_text_free(_IN_ kk_tsl_data_value_t *data_value)
{
    int index = 0;
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    //Free Value
    if (complex_array) {
        for (index = 0; index < complex_array->size; index++) {
            if (*((char **)(complex_array->value) + index)) {
                free(*((char **)(complex_array->value) + index));
                *((char **)(complex_array->value) + index) = NULL;
            }
        }
    }
}

static void _kk_tsl_array_enum_free(_IN_ kk_tsl_data_value_t *data_value)
{

}

static void _kk_tsl_array_date_free(_IN_ kk_tsl_data_value_t *data_value)
{
    int index = 0;
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    //Free Value
    if (complex_array) {
        for (index = 0; index < complex_array->size; index++) {
            if (*((char **)(complex_array->value) + index)) {
                free(*((char **)(complex_array->value) + index));
                *((char **)(complex_array->value) + index) = NULL;
            }
        }
    }
}

static void _kk_tsl_array_bool_free(_IN_ kk_tsl_data_value_t *data_value)
{

}

static void _kk_tsl_array_array_free(_IN_ kk_tsl_data_value_t *data_value)
{

}
static void _kk_tsl_data_free(kk_tsl_data_value_t *data_value)
{
    if (g_iotx_data_type_mapping[data_value->type].func_free == NULL) {
        return;
    }
    g_iotx_data_type_mapping[data_value->type].func_free(data_value);
}

static void _kk_tsl_property_free(_IN_ kk_tsl_data_t *property)
{
    if (property->identifier) {
        free(property->identifier);
    }
    _kk_tsl_data_free(&property->data_value);
}

static void _kk_tsl_array_struct_free(_IN_ kk_tsl_data_value_t *data_value)
{
    int index = 0;
    kk_tsl_data_t *data = NULL;

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

    if (complex_struct) {
        for (index = 0; index < complex_struct->size; index++) {
            data = (kk_tsl_data_t *)complex_struct->value + index;
            _kk_tsl_property_free(data);
        }
    }
}

static void _kk_tsl_array_free(_IN_ kk_tsl_data_value_t *data_value)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    //Free Value
    if (complex_array) {
        /* dm_log_err("complex_array->type: %d",complex_array->type); */
        if (g_iotx_data_type_mapping[complex_array->type].func_array_free != NULL) {
            g_iotx_data_type_mapping[complex_array->type].func_array_free(data_value);
        }
        if (complex_array->value) {
            free(complex_array->value);
        }
        free(complex_array);
        data_value->value = NULL;
    }
}
static void _kk_tsl_struct_free(_IN_ kk_tsl_data_value_t *data_value)
{
    int index = 0;
    kk_tsl_data_t *property = NULL;
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    //Free Value
    if (complex_array) {
        for (index = 0; index < complex_array->size; index++) {
            property = (kk_tsl_data_t *)(complex_array->value) + index;
            _kk_tsl_property_free(property);
        }
        if (complex_array->value) {
            free(complex_array->value);
        }
        free(complex_array);
        data_value->value = NULL;
    }
}

static int _kk_tsl_array_bool_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                  _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;
    int int_set = (value == NULL) ? (0) : (*(int *)value);

    *((int *)(complex_array->value) + index) = int_set;
   // printf("Current Array Value Be Set(Bool), Index: %d, Value: %d\n", index, *((int *)(complex_array->value) + index));

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_int_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                 _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;
    int int_set = (value == NULL) ? (0) : (*(int *)value);

    *((int *)(complex_array->value) + index) = int_set;
    //printf("Current Array Value Be Set(Int), Index: %d, Value: %d\n", index, *((int *)(complex_array->value) + index));

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_float_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                   _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;
    float float_set = (value == NULL) ? (0) : (*(float *)value);

    *((float *)(complex_array->value) + index) = float_set;
    //printf("Current Array Value Be Set(Float), Index: %d, Value: %f\n", index,
                // *((float *)(complex_array->value) + index));

    return SUCCESS_RETURN;
}

static int _kk_tsl_array_double_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                    _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;
    double double_set = (value == NULL) ? (0) : (*(double *)value);

    *((double *)(complex_array->value) + index) = double_set;
    //printf("Current Array Value Be Set(Double), Index: %d, Value: %f\n", index,
                // *((double *)(complex_array->value) + index));

    return SUCCESS_RETURN;
}
static int _kk_tsl_int_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value)
{
    *(int *)(value) = data_value->value_int;
    return SUCCESS_RETURN;
}


static int _kk_tsl_data_array_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len,
                                  _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    if (complex_array == NULL || index < 0 || index >= complex_array->size) {
        return INVALID_PARAMETER;
    }

    if (g_iotx_data_type_mapping[complex_array->type].func_array_set == NULL) {
        return FAIL_RETURN;
    }

    return g_iotx_data_type_mapping[complex_array->type].func_array_set(data_value, value, value_len, index);
}
static int _kk_tsl_data_set(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int value_len)
{
    if (g_iotx_data_type_mapping[data_value->type].func_set == NULL) {
        return FAIL_RETURN;
    }

    return g_iotx_data_type_mapping[data_value->type].func_set(data_value, value, value_len);
}

int dm_tsl_set_property_value(_IN_ kk_tsl_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
                              _IN_ int value_len)
{
    int res = 0, array_index = 0;
    kk_tsl_data_t *data = NULL;

    if (shadow == NULL || key == NULL || key_len <= 0) {
        return FAIL_RETURN;
    }
    res = _kk_tsl_property_search(shadow, key, key_len, &data, &array_index);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    if (data->data_value.type == KK_TSL_DATA_TYPE_ARRAY) {
        res = _kk_tsl_data_array_set(&data->data_value, value, value_len, array_index);
        if (res != SUCCESS_RETURN) {
            return TSL_PROPERTY_SET_FAILED;
        }
    } else {
        res = _kk_tsl_data_set(&data->data_value, value, value_len);
        if (res != SUCCESS_RETURN) {
            return TSL_PROPERTY_SET_FAILED;
        }
    }

    return SUCCESS_RETURN;
}
static int _kk_tsl_event_search(_IN_ kk_tsl_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ kk_tsl_event_t **event)
{
    int index = 0;
    kk_tsl_event_t *dtsl_event = NULL;

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

    for (index = 0; index < shadow->event_number; index++) {
        dtsl_event = shadow->events + index;
        if ((strlen(dtsl_event->identifier) == key_len) &&
            (memcmp(dtsl_event->identifier, key, key_len) == 0)) {
            /* dm_log_debug("TSL Event Found: %s",dtsl_event->identifier); */
            if (event) {
                *event = dtsl_event;
            }
            return SUCCESS_RETURN;
        }
    }

    /* dm_log_debug("TSL Event Not Found: %.*s",key_len,key); */

    return FAIL_RETURN;
}
static int _kk_tsl_event_output_search(_IN_ kk_tsl_data_t *outputdatas, _IN_ int number, _IN_ char *key,
                                       _IN_ int key_len, _OU_ kk_tsl_data_t **event_data, _OU_ int *index)
{
    int res = 0, item_index = 0;
    kk_tsl_data_t *outputdata = NULL;

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

    for (item_index = 0; item_index < number; item_index++) {
        outputdata = outputdatas + item_index;
        res = kk_tsl_data_search(outputdata, key, key_len, event_data, index);
        if (res == SUCCESS_RETURN) {
            return SUCCESS_RETURN;
        }
    }

    return SUCCESS_RETURN;
}
int dm_tsl_get_event_output_data(_IN_ kk_tsl_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **data)
{
    int res = 0;
    int offset = 0, array_index = 0;
    char *pos = NULL;
    kk_tsl_event_t *event = NULL;
    kk_tsl_data_t *event_data = NULL;

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

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

    //printf("Key: %.*s\n", key_len, key);

    res = _kk_tsl_event_search(shadow, key, offset, &event);
    if (res != SUCCESS_RETURN) {
        return TSL_EVENT_NOT_EXIST;
    }

    pos = key + offset + 1;
    /* dm_log_debug("TSL Event Output Data Search, Event Data ID: %s",pos); */

    res = _kk_tsl_event_output_search(event->output_datas, event->output_data_number, pos, strlen(pos), &event_data,
                                      &array_index);
    if (res != SUCCESS_RETURN) {
        return TSL_EVENT_NOT_EXIST;
    }

    if (data) {
        *data = (void *)event_data;
    }

    return SUCCESS_RETURN;
}

int dm_tls_set_event_output_value(_IN_ kk_tsl_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
                                  _IN_ int value_len)
{
    int res = 0, array_index = 0;
    int offset = 0;
    char *pos = NULL;
    kk_tsl_event_t *event = NULL;
    kk_tsl_data_t *event_data = NULL;

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

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

    printf("Key: %.*s", key_len, key);

    res = _kk_tsl_event_search(shadow, key, offset, &event);
    if (res != SUCCESS_RETURN) {
        return TSL_EVENT_NOT_EXIST;
    }

    pos = key + offset + 1;
    /* dm_log_debug("TSL Event Output Data Search, Event Data ID: %s",pos); */

    res = _kk_tsl_event_output_search(event->output_datas, event->output_data_number, pos, strlen(pos), &event_data,
                                      &array_index);
    if (res != SUCCESS_RETURN) {
        return TSL_EVENT_NOT_EXIST;
    }

    if (event_data->data_value.type == KK_TSL_DATA_TYPE_ARRAY) {
        res = _kk_tsl_data_array_set(&event_data->data_value, value, value_len, array_index);
        if (res != SUCCESS_RETURN) {
            return TSL_EVENT_SET_FAILED;
        }
    } else {
        res = _kk_tsl_data_set(&event_data->data_value, value, value_len);
        if (res != SUCCESS_RETURN) {
            return TSL_EVENT_SET_FAILED;
        }
    }

    return SUCCESS_RETURN;
}
static int _kk_tsl_service_search(_IN_ kk_tsl_t *shadow, _IN_ char *key, _IN_ int key_len,
                                  _OU_ kk_tsl_service_t **service)
{
    int index = 0;
    kk_tsl_service_t *dtsl_service = NULL;

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

    for (index = 0; index < shadow->service_number; index++) {
        dtsl_service = shadow->services + index;
        if ((strlen(dtsl_service->identifier) == key_len) &&
            (memcmp(dtsl_service->identifier, key, key_len) == 0)) {
            /* dm_log_debug("TSL Service Found: %s",dtsl_service->identifier); */
            if (service) {
                *service = dtsl_service;
            }
            return SUCCESS_RETURN;
        }
    }

    /* dm_log_debug("TSL Service Not Found: %.*s",key_len,key); */

    return FAIL_RETURN;
}
static int _kk_tsl_service_input_output_search(_IN_ kk_tsl_data_target_e type, _IN_ kk_tsl_service_t *service,
        _IN_ char *key, _IN_ int key_len, _OU_ kk_tsl_data_t **service_data, _OU_ int *index)
{
    int res = 0, item_index = 0, datas_number = 0;
    kk_tsl_data_t *datas = NULL;
    kk_tsl_data_t *data = NULL;

    if (type == KK_TSL_DATA_TARGET_SERVICE_INPUT_DATA) {
        datas = service->input_datas;
        datas_number = service->input_data_number;
    } else {
        datas = service->output_datas;
        datas_number = service->output_data_number;
    }

    for (item_index = 0; item_index < datas_number; item_index++) {
        data = datas + item_index;
        res = kk_tsl_data_search(data, key, key_len, service_data, index);
        if (res == SUCCESS_RETURN) {
            return SUCCESS_RETURN;
        }
    }

    return SUCCESS_RETURN;
}
int dm_tsl_get_service_input_output_data(_IN_ kk_tsl_data_target_e type, _IN_ kk_tsl_t *shadow, _IN_ char *key,
        _IN_ int key_len, _OU_ void **data)
{
    int res = 0;
    int offset = 0, array_index = 0;
    char *pos = NULL;
    kk_tsl_service_t *service = NULL;
    kk_tsl_data_t *service_data = NULL;

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

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

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

    res = _kk_tsl_service_search(shadow, key, offset, &service);
    if (res != SUCCESS_RETURN) {
        return TSL_EVENT_NOT_EXIST;
    }

    pos = key + offset + 1;
    //printf("TSL Service input/output Data Search, Event Data ID: %s", pos);

    res = _kk_tsl_service_input_output_search(type, service, pos, strlen(pos), &service_data, &array_index);
    if (res != SUCCESS_RETURN) {
        return TSL_EVENT_NOT_EXIST;
    }

    if (data) {
        *data = (void *)service_data;
    }

    return SUCCESS_RETURN;
}

int dm_tsl_set_service_input_output_value(_IN_ kk_tsl_data_target_e type, _IN_ kk_tsl_t *shadow, _IN_ char *key,
        _IN_ int key_len, _IN_ void *value, _IN_ int value_len)
{
    int res = 0, array_index = 0;
    int offset = 0;
    char *pos = NULL;
    kk_tsl_service_t *service = NULL;
    kk_tsl_data_t *service_data = NULL;

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

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

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

    res = _kk_tsl_service_search(shadow, key, offset, &service);
    if (res != SUCCESS_RETURN) {
        return TSL_SERVICE_NOT_EXIST;
    }

    pos = key + offset + 1;
    //printf("TSL Service Input/Output Data Search, Event Data ID: %s", pos);

    res = _kk_tsl_service_input_output_search(type, service, pos, strlen(pos), &service_data, &array_index);
    if (res != SUCCESS_RETURN) {
        return TSL_SERVICE_NOT_EXIST;
    }

    if (service_data->data_value.type == KK_TSL_DATA_TYPE_ARRAY) {
        res = _kk_tsl_data_array_set(&service_data->data_value, value, value_len, array_index);
        if (res != SUCCESS_RETURN) {
            return TSL_SERVICE_SET_FAILED;
        }
    } else {
        res = _kk_tsl_data_set(&service_data->data_value, value, value_len);
        if (res != SUCCESS_RETURN) {
            return TSL_SERVICE_SET_FAILED;
        }
    }

    return SUCCESS_RETURN;
}

int kk_tsl_get_data_type(_IN_ void *data, _OU_ kk_tsl_data_type_e *type)
{
    kk_tsl_data_t *data_item = (kk_tsl_data_t *)data;

    if (data_item == NULL || type == NULL) {
        return INVALID_PARAMETER;
    }

    if (data_item->data_value.type == KK_TSL_DATA_TYPE_ARRAY) {
        kk_tsl_data_value_complex_t *complex_value = (kk_tsl_data_value_complex_t *)data_item->data_value.value;
        *type = complex_value->type;
    } else {
        *type = data_item->data_value.type;
    }

    return SUCCESS_RETURN;
}
static int _kk_tsl_data_array_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value, _IN_ int index)
{
    kk_tsl_data_value_complex_t *complex_array = data_value->value;

    if (complex_array == NULL || index < 0 || index >= complex_array->size) {
        return FAIL_RETURN;
    }

    if (g_iotx_data_type_mapping[complex_array->type].func_array_get == NULL) {
        return FAIL_RETURN;
    }

    return g_iotx_data_type_mapping[complex_array->type].func_array_get(data_value, value, index);
}
static int _kk_tsl_data_get(_IN_ kk_tsl_data_value_t *data_value, _IN_ void *value)
{
    if (g_iotx_data_type_mapping[data_value->type].func_get == NULL) {
        return FAIL_RETURN;
    }

    return g_iotx_data_type_mapping[data_value->type].func_get(data_value, value);
}


int kk_tsl_get_property_value_ex(_IN_ kk_tsl_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void *value)
{
    int res = 0, array_index = 0;
    kk_tsl_data_t *data = NULL;

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

    res = _kk_tsl_property_search(shadow, key, key_len, &data, &array_index);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
    if (data->data_value.type == KK_TSL_DATA_TYPE_ARRAY) {
        res = _kk_tsl_data_array_get(&data->data_value, value, array_index);
        if (res != SUCCESS_RETURN) {
            return TSL_PROPERTY_GET_FAILED;
        }
    } else {
        res = _kk_tsl_data_get(&data->data_value, value);
        if (res != SUCCESS_RETURN) {
            return TSL_PROPERTY_GET_FAILED;
        }
    }

    return SUCCESS_RETURN;
}
int kk_tsl_get_event_oput_value(_IN_ kk_tsl_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value)
{
    int res = 0;
    int offset = 0, array_index = 0;
    char *pos = NULL;
    kk_tsl_event_t *event = NULL;
    kk_tsl_data_t *event_data = NULL;

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

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

    res = _kk_tsl_event_search(shadow, key, offset, &event);
    if (res != SUCCESS_RETURN) {
        return TSL_EVENT_NOT_EXIST;
    }

    pos = key + offset + 1;

    res = _kk_tsl_event_output_search(event->output_datas, event->output_data_number, pos, strlen(pos), &event_data,
                                      &array_index);
    if (res != SUCCESS_RETURN) {
        return TSL_EVENT_NOT_EXIST;
    }

    if (event_data->data_value.type == KK_TSL_DATA_TYPE_ARRAY) {
        res = _kk_tsl_data_array_get(&event_data->data_value, value, array_index);
        if (res != SUCCESS_RETURN) {
            return TSL_EVENT_GET_FAILED;
        }
    } else {
        res = _kk_tsl_data_get(&event_data->data_value, value);
        if (res != SUCCESS_RETURN) {
            return TSL_EVENT_GET_FAILED;
        }
    }

    return SUCCESS_RETURN;
}
int kk_tsl_get_service_input_output_value(_IN_ kk_tsl_data_target_e type, _IN_ kk_tsl_t *shadow, _IN_ char *key,
        _IN_ int key_len, _IN_ void *value)
{
    int res = 0;
    int offset = 0, array_index = 0;
    char *pos = NULL;
    kk_tsl_service_t *service = NULL;
    kk_tsl_data_t *service_data = NULL;

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

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

    //printf("key: %.*s\n", key_len, key);

    res = _kk_tsl_service_search(shadow, key, offset, &service);
    if (res != SUCCESS_RETURN) {
        return TSL_SERVICE_NOT_EXIST;
    }

    pos = key + offset + 1;
    //printf("TSL Service Input/Output Data Search, Event Data ID: %s", pos);

    res = _kk_tsl_service_input_output_search(type, service, pos, strlen(pos), &service_data, &array_index);
    if (res != SUCCESS_RETURN) {
        return TSL_SERVICE_NOT_EXIST;
    }

    if (service_data->data_value.type == KK_TSL_DATA_TYPE_ARRAY) {
        res = _kk_tsl_data_array_get(&service_data->data_value, value, array_index);
        if (res != SUCCESS_RETURN) {
            return TSL_SERVICE_GET_FAILED;
        }
    } else {
        res = _kk_tsl_data_get(&service_data->data_value, value);
        if (res != SUCCESS_RETURN) {
            return TSL_SERVICE_GET_FAILED;
        }
    }

    return SUCCESS_RETURN;
}
void kk_tsl_datavalue_free(kk_tsl_data_value_t *data_value)
{
	if (g_iotx_data_type_mapping[data_value->type].func_free == NULL) {
		return;
	}
	g_iotx_data_type_mapping[data_value->type].func_free(data_value);
}


