
#include "em_common.h"
#include <stdarg.h>

int em_tolower(int chr) { return (chr >= 'A' && chr <= 'Z') ? (chr + 32) : (chr); }

int em_get_digit_count(int num)
{
	int count = 0;

	while (num >= 0) {
		count++;
		if ((num /= 10) == 0)
			break;
	}

	return count;
}

int em_is_string_int(const char *val)
{
	int i = 0, size = 0;
	int ret;

	EM_CHECK_NULL(__func__, EM_ERR_EM_IS_STRING_INT, val);

	size = strlen(val);
	for (i = 0; i < size; i++) {
		if (val[i] < '0' || val[i] > '9') {
			LOGI("%s isn't string int\n", val);
			ret = EM_ERR_EM_IS_STRING_INT_FALSE;
			goto out;
		}
	}

	ret = EM_SUCCESS;
out:
	return ret;
}

static int em_is_digit(const char chr)
{
	if ('0' <= chr && chr <= '9')
		return 1;

	return 0;
}

void em_hex_to_byte(const char *str, int size, uint8_t *byteArray)
{
	int i = 0;
	const char *pos = str;
	char pC = '\0';
	int dig1 = 0, dig2 = 0;
	int offset = 0;

	for (i = 0; i < size; i += 2) {
		dig1 = dig2 = 0;

		pC = pos[i];
		if (em_is_digit((const char)pC))
			dig1 = pC - '0';
		else if ('A' <= pC && pC <= 'F')
			dig1 = pC - 'A' + 10;
		else if ('a' <= pC && pC <= 'f')
			dig1 = pC - 'a' + 10;

		pC = pos[i + 1];
		if (em_is_digit((const char)pC))
			dig2 = pC - '0';
		else if ('A' <= pC && pC <= 'F')
			dig2 = pC - 'A' + 10;
		else if ('a' <= pC && pC <= 'f')
			dig2 = pC - 'a' + 10;

		byteArray[offset] = dig1 * 16 + dig2;
		offset++;
	}
}

int em_is_all_zero(unsigned char *buf, unsigned int size)
{
	int ret = EM_ERR_EM_IS_ALL_ZERO_NOT_ZERO;
	unsigned int i;

	EM_CHECK_NULL(__func__, EM_ERR_EM_IS_ALL_ZERO, buf);

	for (i = 0; i < size; i++) {
		if (buf[i] != 0x00)
			goto out;
	}

	ret = EM_SUCCESS;
out:
	return ret;
}

void em_add_string(uint8_t *buf, uint32_t buf_size, uint32_t *offset, uint8_t *str, uint32_t size)
{
	if (*offset + size > buf_size) {
		LOGE("cannot add string (buf size(%u), offset+string size (%u) [(%u) + (%u)] \n", buf_size, *offset + size, *offset, size);
	} else {
		memcpy(buf + *offset, str, size);
		*offset += size;
	}
}

void em_set_data_to_raw(uint8_t *data, uint32_t data_max, uint8_t *raw, uint32_t raw_size, uint32_t *raw_offset,
			uint32_t data_size)
{
	if (data_size > data_max) {
		LOGE("cannot set data (data size(%u), data max(%u)\n", data_size, *raw_offset + data_size);
		return;
	}

	em_add_string(raw, raw_size, raw_offset, data, data_size);
}

void em_get_data_from_raw(uint8_t *data, uint32_t data_max, uint8_t *raw, uint32_t raw_size, uint32_t *raw_offset,
			  uint32_t data_size)
{
	if (*raw_offset + data_size > raw_size) {
		LOGE("cannot get data (offset(%u), raw size(%u)\n", *raw_offset, raw_size);
		return;
	}

	if (data_size > data_max) {
		LOGE("cannot get data (data size(%u), data max(%u)\n", data_size, *raw_offset + data_size);
		return;
	}

	memcpy(data, raw + *raw_offset, data_size);
	*raw_offset += data_size;
}

int em_atoi(char const *c)
{

	int value = 0;
	int positive = 1;

	if (*c == '\0')
		return 0;

	if (*c == '-')
		positive = -1;

	while (*c) {
		if (*c >= '0' && *c <= '9')
			value = value * 10 + *c - '0';
		c++;
	}

	return value * positive;
}

/* We make own strpbrk because teegris can't use strpbrk */
char *em_strtok_with_null(char *str, const char *delim)
{
	static int index, len_origin;
	static char *origin;
	static char *ret;

	int i = 0, len_item = 0;

	if (delim == NULL)
		return NULL;

	if (str == NULL) { // Find next element
		if (origin == NULL)
			return NULL;
	} else { // New element
		index = 0;
		origin = str;
		len_origin = strlen(origin);
	}

	if (ret != NULL) {
		em_free(ret);
		ret = NULL;
	}

	for (i = index; i < len_origin; i++) {
		if (origin[i] == delim[0])
			break;
	}

	if (i == len_origin) // Finish
		return NULL;

	len_item = i - index;
	ret = (char *)em_calloc(len_item + 1, sizeof(char));
	if (ret == NULL) {
		LOGE("Failed to allocate return value\n");
		return NULL;
	}

	if (len_item == 0) {
		*ret = 0;
		index++;
	} else {
		if (index + len_item > len_origin) {
			LOGE("index isn't normal\n");
			em_free(ret);
			ret = NULL;
			return NULL;
		}
		memcpy(ret, origin + index, len_item);
		index += len_item + 1; // 1 is delim size, ex) ':'
	}

	return ret;

	/*
	static char *src = NULL;
	char *p, *ret = 0;

	if (str != NULL)
		src = str;

	if (src == NULL)
		return NULL;

	if ((p = strpbrk(src, delim)) != NULL) {
		*p = 0;
		ret = src;
		src = ++p;

	} else if (*src) {
		ret = src;
		src = NULL;
	}

	return ret;*/
}

int em_strncasecmp(const char *s1, const char *s2, size_t n)
{
	int CompareVal;
	int ret;

	EM_CHECK_NULL(__func__, EM_ERR_EM_STRNCASECMP, s1, s2);

	if (n != 0) {
		do {
			CompareVal = em_tolower(*s1) - em_tolower(*s2);
			if (CompareVal != 0) {
				return CompareVal;
			}
			++s1;
			++s2;
			if (*s1 == '\0') {
				break;
			}
		} while (--n != 0);
	}

	ret = EM_SUCCESS;
out:
	return ret;
}

void print_msg_hex(char *TAG, uint8_t *buf, uint32_t size)
{
	int count = 0, string_count = 0;
	char msg[33] = {0,};
	char msg_string[17] = {0,};

	uint32_t i = 0;

	for (i = 0; i < size; i++) {
		if (i % 16 == 0) {
			if (i != 0) {
				LOGE("%s : %s\n", TAG, msg_string);
			} else {
				em_snprintf(msg, 2, "%02x", buf[i]);
				msg_string[string_count] = buf[i];
				count += 2;
				string_count++;
				continue;
			}
			memset(msg, 0, 33);
			memset(msg_string, 0, 17);
			count = string_count = 0;
		} else {
			em_snprintf(msg + count, 2, "%02x", buf[i]);
			msg_string[string_count] = buf[i];
			count += 2;
			string_count++;
		}
	}

	if (count != 0)
		LOGE("%s : %s\n", TAG, msg_string);
}

void em_itoa_for_mode(int val, char *buf)
{
	if (buf == NULL) {
		LOGE("buf is null\n");
		return;
	}

	em_snprintf(buf, EM_LEN_MODE_STRING_SIZE, "%u", val);
}

static int isthisspace(const char c)
{
	if (c == ' ' || c == '\t' || c == '\v' || c == '\f' || c == '\n' || c == '\r') {
		return 1;
	}

	return 0;
}

void remove_spaces(const char *input, char *result)
{
	int i, j = 0;

	if (input == NULL || result == NULL)
		return;

	for (i = 0; input[i] != '\0'; i++) {
		if (!isthisspace((unsigned char) input[i])) {
			result[j++] = input[i];
		}
	}
	result[j] = '\0';
}

#ifdef EMAS
void em_snprintf(char *buf, int size, char *rgx, ...)
{
	va_list ap;

	if (buf == NULL) {
		LOGE("buf is null\n");
		return;
	}

	if (rgx == NULL) {
		LOGE("rgx is null\n");
		return;
	}

	va_start(ap, rgx);
	vsnprintf(buf, size, rgx, ap);
	va_end(ap);
}

char *em_strtok(char *__restrict s1, const char *__restrict s2) { return strtok(s1, s2); }

void em_base64_encode(const char *src, char *result, int length)
{
	int i, j = 0;
	BF temp;

	for (i = 0; i < length; i = i + 3, j = j + 4) {
		temp.c3 = src[i];
		if ((i + 1) > length)
			temp.c2 = 0x00;
		else
			temp.c2 = src[i + 1];
		if ((i + 2) > length)
			temp.c1 = 0x00;
		else
			temp.c1 = src[i + 2];

		result[j] = MimeBase64[temp.e4];
		result[j + 1] = MimeBase64[temp.e3];
		result[j + 2] = MimeBase64[temp.e2];
		result[j + 3] = MimeBase64[temp.e1];

		if ((i + 2) > length)
			result[j + 2] = '=';
		if ((i + 3) > length)
			result[j + 3] = '=';
	}
}

void em_base64_decode(const char *src, char *result, int *length)
{
	int i, j = 0, src_length, blank = 0;
	BF temp;

	src_length = strlen(src);

	for (i = 0; i < src_length; i = i + 4, j = j + 3) {
		temp.e4 = DecodeMimeBase64[(int)src[i]];
		temp.e3 = DecodeMimeBase64[(int)src[i + 1]];
		if (src[i + 2] == '=') {
			temp.e2 = 0x00;
			blank++;
		} else
			temp.e2 = DecodeMimeBase64[(int)src[i + 2]];
		if (src[i + 3] == '=') {
			temp.e1 = 0x00;
			blank++;
		} else
			temp.e1 = DecodeMimeBase64[(int)src[i + 3]];

		result[j] = temp.c3;
		result[j + 1] = temp.c2;
		result[j + 2] = temp.c1;
	}
	*length = j - blank;
}
#endif /* EMAS */
