#include "em_common.h"

int em_get_from_extension(const char *type, uint16_t mode, em_parsed_token *parsed_token, ext_type_header *head_data,
			  char *type_data)
{
	int ret;

	em_modb_data *mode_database = NULL;
	em_modb_attr *mode_attrbutes = NULL;
	ext_type_header *ext_head_data = NULL;

	char decoded_ext[EM_EXT_EXTENSION_DATA_MAX] = {0, };
	char trimed_ext[EM_EXT_EXTENSION_DATA_MAX] = {0, };
	int decode_str_len = 0;
	int valid_mode = 0;

	char *token = NULL;
	char **ext_type_data = NULL;
	int num_of_type = 0;

	char *header = NULL;
	char *header_item = NULL;
	char tmp[512] = {0,};

	int i = 0;

	EM_CHECK_NULL(__func__, EM_ERR_EM_GET_FROM_EXTENSION, type, parsed_token, head_data, type_data);

	if (EM_LEN_MAX_MODE <= mode) {
		LOGE("Requested mode(0x%02x) isn't supported(%u)\n", mode, EM_LEN_MAX_MODE);
		ret = EM_ERR_EM_GET_FROM_EXTENSION;
		goto out;
	}

	for (i = 0; i < parsed_token->mode.num_of_modes; i++) {
		if (mode == parsed_token->mode.mode[i]) {
			valid_mode = 1;
			break;
		}
	}

	if (!valid_mode) {
		LOGE("mode#%u doesn't exist\n", mode);
		ret = EM_ERR_EM_GET_FROM_EXTENSION_NOT_EXIST;
		goto out;
	}

	mode_database = &parsed_token->modedb.data[mode];
	mode_attrbutes = &mode_database->attributes;

	if (mode_attrbutes->len_ext < EM_LEN_EXTENSION_DATA_MIN) {
		LOGE("Mode(%u)'s extension is empty\n", mode);
		ret = EM_ERR_EM_GET_FROM_EXTENSION_NO_EXT_DATA;
		goto out;
	}

	LOGD("ext - %s\n", mode_attrbutes->ext);

	em_base64_decode(mode_attrbutes->ext, decoded_ext, &decode_str_len);
	remove_spaces(decoded_ext, trimed_ext);

	if (memcmp(trimed_ext, "EXT", 3)) {
		LOGE("Mode%u doesn't use extension\n", mode);
		ret = EM_ERR_EM_GET_FROM_EXTENSION_THIS_IS_NOT_EXT;
		goto out;
	}

	LOGD("decoded data (%u)\n", (uint32_t)strlen(trimed_ext));
	LOGD("%s", trimed_ext);

	token = em_strtok(&trimed_ext[4], EM_EXT_DELIMITER_TYPE);
	if (token == NULL) {
		LOGE("Extension isn't exist\n");
		ret = EM_ERR_EM_GET_FROM_EXTENSION_TYPE_IS_NULL;
		goto out;
	}

	num_of_type = em_atoi(token);
	LOGD("num_of_type : %u\n", num_of_type);
	if (num_of_type <= 0) {
		LOGE("Invaild extension\n");
		ret = EM_ERR_EM_GET_FROM_EXTENSION_TYPE;
		goto out;
	}

	ext_type_data = em_calloc(sizeof(char *), num_of_type);
	if (ext_type_data == NULL) {
		LOGE("Failed to allocate ext_type_data\n");
		ret = EM_ERR_EM_GET_FROM_EXTENSION_ALLOC_TYPE_DATA;
		goto out;
	}

	for (i = 0; i < num_of_type; i++) {
		ext_type_data[i] = em_strtok(NULL, EM_EXT_DELIMITER_TYPE);
		if (ext_type_data[i] == NULL) {
			LOGE("Num%d typs is null\n", i);
			ret = EM_ERR_EM_GET_FROM_EXTENSION_TYPE_DATA_IS_NULL;
			goto out;
		}
		LOGD("Type#%u : %s\n", i, ext_type_data[i]);
	}

	ext_head_data = em_calloc(sizeof(ext_type_header), num_of_type);
	if (ext_head_data == NULL) {
		LOGE("Failed to allocate ext_head_data\n");
		ret = EM_ERR_EM_GET_FROM_EXTENSION_ALLOC_HEAD_DATA;
		goto out;
	}

	ret = EM_ERR_EM_GET_FROM_EXTENSION_NO_PERMISSION;
	for (i = 0; i < num_of_type; i++) {
		header = NULL;
		header_item = NULL;
		memset(tmp, 0, 512);

		memcpy(tmp, ext_type_data[i], strlen(ext_type_data[i]));

		header = em_strtok(tmp, EM_EXT_DELIMITER_ITEM);
		if (header == NULL) {
			LOGE("header is null\n");
			ret = EM_ERR_EM_GET_FROM_EXTENSION_HEADER_IS_NULL;
			goto out;
		}
		LOGD("Header#%u : %s\n", i, header);

		header_item = em_strtok(header, EM_EXT_DELIMITER_DATA);
		if (header_item == NULL) {
			LOGE("magic is null\n");
			ret = EM_ERR_EM_GET_FROM_EXTENSION_MAGIC_IS_NULL;
			goto out;
		}
		memcpy(ext_head_data[i].magic, header_item, strlen(header_item));
		LOGD("magic : %s\n", ext_head_data[i].magic);

		header_item = em_strtok(NULL, EM_EXT_DELIMITER_DATA);
		if (header_item == NULL) {
			LOGE("version is null\n");
			ret = EM_ERR_EM_GET_FROM_EXTENSION_VERSION_IS_NULL;
			goto out;
		}
		memcpy(ext_head_data[i].version, header_item, strlen(header_item));
		LOGD("version : %s\n", ext_head_data[i].version);

		header_item = em_strtok(NULL, EM_EXT_DELIMITER_DATA);
		if (header_item == NULL) {
			LOGE("num is null\n");
			ret = EM_ERR_EM_GET_FROM_EXTENSION_NUM_IS_NULL;
			goto out;
		}
		ext_head_data[i].num_of_data = em_atoi(header_item);
		LOGD("num of data : %u\n", ext_head_data[i].num_of_data);

		if (!memcmp(ext_head_data[i].magic, EM_EXT_TYPE_CLIENT, strlen(EM_EXT_TYPE_CLIENT)) &&
		    !memcmp(type, EM_EXT_TYPE_CLIENT, strlen(EM_EXT_TYPE_CLIENT))) {
			memcpy(head_data, &ext_head_data[i], sizeof(ext_type_header));
			memcpy(type_data, ext_type_data[i], strlen(ext_type_data[i]));
			ret = EM_SUCCESS;
			break;
		}
	}

out:
	if (ext_head_data)
		em_free(ext_head_data);

	if (ext_type_data)
		em_free(ext_type_data);

	return ret;
}
