#include <pthread.h>
#include "kk_utils.h"



int kk_utils_copy(_IN_ void *input, _IN_ int input_len, _OU_ void **output, _IN_ int output_len)
{
	if (input == NULL || output == NULL || *output != NULL) {
		return INVALID_PARAMETER;
	}

	*output = malloc(output_len);
	if (*output == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(*output, 0, output_len);
	memcpy(*output, input, input_len);

	return SUCCESS_RETURN;
}
int kk_utils_memtok(_IN_ char *input, _IN_ int input_len, _IN_ char delimiter, _IN_ int index, _OU_ int *offset)
{
	int item_index = 0;
	int count = 0;

	if (input == NULL || input_len <= 0 || offset == NULL) {
		return INVALID_PARAMETER;
	}

	for (item_index = 0; item_index < input_len; item_index++) {
		if (input[item_index] == delimiter && (item_index + 1) < input_len) {
			count++;
			if (count == index) {
				*offset = item_index;
				return SUCCESS_RETURN;
			}
		}
	}

	return FAIL_RETURN;
}
int kk_utils_strarr_index(_IN_ char *input, _IN_ int input_len,
						_OU_ int *partial_input_len, _OU_ int *array_input_len, _OU_ int *array_index)
{
	if (input == NULL || input_len <= 1 || array_index == NULL) {
		return INVALID_PARAMETER;
	}

	int index = 0;
	int deep = 0;
	char *bracket_pre = NULL;
	char *bracket_suf = NULL;
	char array_index_str[10] = {0};

	for (index = 0; index < input_len; index++) {
		switch (input[index]) {
			case '[': {
				if (deep != 0) {
					return FAIL_RETURN;
				}
				deep++;
				if (!bracket_pre) {
					bracket_pre = (char *)&input[index];
				}
			}
			break;
			case ']': {
				if (deep != 1) {
					return FAIL_RETURN;
				}
				deep--;
				if (input[index - 1] == '[') {
					return FAIL_RETURN;
				}
				if (!bracket_suf) {
					bracket_suf = (char *)&input[index];
				}
			}
			break;
			default:
			break;
		}
	}

	if (bracket_pre && bracket_suf && ((bracket_suf - input + 1) == input_len)) {
		if (partial_input_len) {
			*partial_input_len = bracket_pre - input;
		}
		if (array_input_len) {
			*array_input_len = bracket_suf - input + 1;
		}

		//Get Index
		memcpy(array_index_str, bracket_pre + 1, bracket_suf - bracket_pre - 1);
		*array_index = atoi(array_index_str);
		return SUCCESS_RETURN;
	}

	return FAIL_RETURN;
}
int kk_utils_copy_direct(_IN_ void *input, _IN_ int input_len, _OU_ void **output, _IN_ int output_len)
{
	if (input == NULL || output == NULL || *output != NULL) {
		return INVALID_PARAMETER;
	}

	*output = malloc(output_len);
	if (*output == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(*output, 0, output_len);
	memcpy(*output, input, input_len);

	return SUCCESS_RETURN;
}

int kk_utils_itoa(_IN_ int input, _OU_ char **output)
{
	int res = 0;
	char temp_output[10 + 1] = {0};

	if (output == NULL || *output != NULL) {
		return INVALID_PARAMETER;
	}

	res = snprintf(temp_output, 10, "%d", input);
	if (res < 0) {
		return FAIL_RETURN;
	}

	*output = malloc(strlen(temp_output) + 1);
	if (*output == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(*output, 0, strlen(temp_output) + 1);
	memcpy(*output, temp_output, strlen(temp_output));

	return SUCCESS_RETURN;
}
void *kk_MutexCreate(void)
{
	int err_num;
	pthread_mutex_t *mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
	if (NULL == mutex) 
	{
		return NULL;
	}

	if (0 != (err_num = pthread_mutex_init(mutex, NULL))) 
	{
		printf("create mutex failed\n");
		free(mutex);
		return NULL;
	}

	return mutex;
}
void kk_MutexLock(void *mutex)
{
	int err_num;
	if (0 != (err_num = pthread_mutex_lock((pthread_mutex_t *)mutex))) 
	{
		printf("lock mutex failed: - '%s' (%d)\n", strerror(err_num), err_num);
	}
}

void kk_MutexUnLock(void *mutex)
{
	int err_num;
	if (0 != (err_num = pthread_mutex_unlock((pthread_mutex_t *)mutex))) 
	{
		printf("unlock mutex failed - '%s' (%d)\n", strerror(err_num), err_num);
	}
}

void kk_MutexDestroy(void *mutex)
{
	int err_num;

	if (!mutex) 
	{
		printf("mutex want to destroy is NULL!\n");
		return;
	}
	if (0 != (err_num = pthread_mutex_destroy((pthread_mutex_t *)mutex))) 
	{
		printf("destroy mutex failed\n");
	}

	free(mutex);
}
int kk_utils_service_name(_IN_ const char *prefix, _IN_ const char *name, _IN_ char productType[PRODUCT_TYPE_MAXLEN],
		_IN_ char deviceCode[DEVICE_CODE_MAXLEN], _OU_ char **service_name)
{
	int prefix_len = (prefix == NULL) ? (0) : (strlen(prefix));
	int name_len = (name == NULL) ? (0) : (strlen(name));
	int service_name_len = 0;
	if ((prefix == NULL && name == NULL) || productType == NULL || deviceCode == NULL ||
		service_name == NULL || *service_name != NULL) {
		return INVALID_PARAMETER;
	}

	service_name_len = prefix_len + name_len + strlen(productType) + strlen(deviceCode) + 1;
	*service_name = malloc(service_name_len);
	if (*service_name == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(*service_name, 0, service_name_len);

	if (prefix != NULL) {
		snprintf(*service_name, service_name_len, prefix, productType, deviceCode);
	}

	if (name != NULL) {
		memcpy(*service_name + strlen(*service_name), name, name_len);
	}

	return SUCCESS_RETURN;
}

int kk_utils_itoa_direct(_IN_ int input, _OU_ char **output)
{
	int res = 0;
	char temp_output[10 + 1] = {0};

	if (output == NULL || *output != NULL) {
		return INVALID_PARAMETER;
	}

	res = snprintf(temp_output, 10, "%d", input);
	if (res < 0) {
		return FAIL_RETURN;
	}

	*output = malloc(strlen(temp_output) + 1);
	if (*output == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(*output, 0, strlen(temp_output) + 1);
	memcpy(*output, temp_output, strlen(temp_output));

	return SUCCESS_RETURN;
}
int kk_utils_ftoa_direct(_IN_ double input, _OU_ char **output)
{
	int res = 0;
	char temp_output[30 + 1] = {0};

	if (output == NULL || *output != NULL) {
		return INVALID_PARAMETER;
	}

	res = snprintf(temp_output, 30, "%f", input);
	if (res < 0) {
		return FAIL_RETURN;
	}

	*output = malloc(strlen(temp_output) + 1);
	if (*output == NULL) {
		return MEMORY_NOT_ENOUGH;
	}
	memset(*output, 0, strlen(temp_output) + 1);
	memcpy(*output, temp_output, strlen(temp_output));

	return SUCCESS_RETURN;
}

int kk_utils_json_parse(_IN_ const char *payload, _IN_ int payload_len, _IN_ int type, _OU_ lite_cjson_t *lite)
{
	int res = 0;

	if (payload == NULL || payload_len <= 0 || type < 0 || lite == NULL) {
		return INVALID_PARAMETER;
	}
	memset(lite, 0, sizeof(lite_cjson_t));

	res = lite_cjson_parse(payload, payload_len, lite);
	if (res != SUCCESS_RETURN) {
		memset(lite, 0, sizeof(lite_cjson_t));
		return FAIL_RETURN;
	}
	//printf (" lite->type= %d [%d] \n", lite->type, type);
	if (type != cJSON_Invalid && lite->type != type) {
		memset(lite, 0, sizeof(lite_cjson_t));
		return FAIL_RETURN;
	}

	return SUCCESS_RETURN;
}

int kk_utils_json_object_item(_IN_ lite_cjson_t *lite, _IN_ const char *key, _IN_ int key_len, _IN_ int type,
	_OU_ lite_cjson_t *lite_item)
{
	int res = 0;

	if (lite == NULL || lite->type != cJSON_Object || key == NULL || key_len <= 0 || type < 0 || lite_item == NULL) {
		return INVALID_PARAMETER;
	}

	if (lite->type != cJSON_Object) {
		printf("lite->type != cJSON_Object, %d", lite->type);
	}

	memset(lite_item, 0, sizeof(lite_cjson_t));

	res = lite_cjson_object_item(lite, key, key_len, lite_item);
	if (res != SUCCESS_RETURN) {
		/* dm_log_err(DM_UTILS_LOG_JSON_PARSE_FAILED, lite->value_length, lite->value); */
		memset(lite_item, 0, sizeof(lite_cjson_t));
		return FAIL_RETURN;
	}

	if (type != cJSON_Invalid && lite_item->type != type) {
		memset(lite_item, 0, sizeof(lite_cjson_t));
		return FAIL_RETURN;
	}

	return SUCCESS_RETURN;
}
