#include "kk_tsl_common.h"
#include "kk_utils.h"
#include "kk_tsl_parse.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);
}


