#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mqtt_api.h"
#include "com_api.h"
#include "cJSON.h"
#include "kk_product.h"

#define KK_FILTER_ADD_TOPIC 		           "/thing/topo/add"
#define KK_FILTER_ADD_TOPIC_REPLY              "/thing/topo/add_reply"
#define KK_FILTER_DELETE_TOPIC                 "/thing/topo/delete"
#define KK_FILTER_DELETE_TOPIC_REPLY           "/thing/topo/delete_reply"
#define KK_FILTER_REGISTER_TOPIC               "/thing/sub/register"
#define KK_FILTER_REGISTER_TOPIC_REPLY         "/thing/sub/register_reply"
#define KK_FILTER_LOGIN_TOPIC                  "/thing/combine/login"
#define KK_FILTER_LOGIN_TOPIC_REPLY            "/thing/combine/login_reply"
#define KK_FILTER_SET_TOPIC                  "/thing/service/property/set"
#define KK_FILTER_SET_TOPIC_REPLY            "/thing/service/property/set_reply"
#define KK_FILTER_EVENT_POST_TOPIC            "/thing/event/property/post"
#define KK_FILTER_EVENT_POST_REPLY            "/thing/event/property/post_reply"
const char DM_MSG_TO_MIDDWARE[] = "{\"msgtype\":\"%d\",\"product_type\":\"%s\",\"device_name\":\"%s\"}";
#define KK_TOPIC_SERVICE_DELIMITER 			  '/'

typedef struct{
  char *str;
  kk_msg_type_t type;
}kk_topic_type_map_t;

kk_topic_type_map_t g_type_map[] = {
	{"register_reply",MSG_REGISTER_REPLY},
	{"add_reply",MSG_TOPOADD_REPLY},
	{"login_reply",MSG_LOGIN_REPLY},
	{"offline_reply",MSG_OFFLINE_REPLY},	
	{"/ota/device/upgrade",MSG_OTA_UPGRADE},
	{"thing/service/property/set",MSG_PROPERTYSET},
};


int _kk_sendto_cloud(cJSON *root)
{
	cJSON *info,*pData;
	char *topic = NULL;
	char *payload = NULL;
	info = cJSON_GetObjectItem(root, MSG_INFO_STR);
	if(info == NULL){
		return -1;
	}
	topic = KK_Make_Topic(info);
	if(topic == NULL){
		return -1;
	}
	pData = cJSON_GetObjectItem(root, MSG_PAYLOAD_STR);
	if(pData == NULL){
		return -1;
	}
	printf("[%s][%d] payload:%s\n",__FUNCTION__,__LINE__,pData->valuestring);	
	KK_MQTT_SendMsg(topic,(const char*)pData->valuestring);	
	free(topic);
	return 0;
}


void KK_Data_FromDev(void* str,int len)
{
	cJSON *root,*cmd;
	if(str == NULL){
		return;
	}
	root=cJSON_Parse((char*)str);
	if(root == NULL){
	    printf("[%s][%d] root is null \n",__FUNCTION__,__LINE__);
		return;
	}
	cmd = cJSON_GetObjectItem(root, "cmd");
	if(cmd == NULL){
		_kk_sendto_cloud(root);
	}
	else{
		KK_Subdev_Subscribe(root);
	}
	cJSON_Delete(root);

}
static int _check_invalid_topic(const char* topic)
{
	if(strstr(topic, KK_FILTER_ADD_TOPIC) != NULL && \
		strstr(topic,KK_FILTER_ADD_TOPIC_REPLY) == NULL){
		return 1;
	}
	else if(strstr(topic, KK_FILTER_DELETE_TOPIC) != NULL && \
		strstr(topic,KK_FILTER_DELETE_TOPIC_REPLY) == NULL){
		return 1;
	}
	else if(strstr(topic, KK_FILTER_REGISTER_TOPIC) != NULL && \
		strstr(topic,KK_FILTER_REGISTER_TOPIC_REPLY) == NULL){
		return 1;
	}		
	else if(strstr(topic, KK_FILTER_LOGIN_TOPIC) != NULL && \
		strstr(topic,KK_FILTER_LOGIN_TOPIC_REPLY) == NULL){
		return 1;
	}	
		else if(strstr(topic, KK_FILTER_SET_TOPIC_REPLY) != NULL){
		return 1;
	}		
	else if(strstr(topic, KK_FILTER_EVENT_POST_TOPIC) != NULL && \
		strstr(topic,KK_FILTER_LOGIN_TOPIC_REPLY) == NULL){
		return 1;
	}
	return 0;
}
static kk_msg_type_t _kk_parse_type(const char *topic)
{
	int num = 0,idx = 0;
	if(topic == NULL){
		return MSG_INVALID;
	}
	num = sizeof(g_type_map)/sizeof(kk_topic_type_map_t);	
	for(idx = 0; idx < num; idx++){
		if(strstr(topic,g_type_map[idx].str) != NULL){
			return g_type_map[idx].type;
		}
	}
	return MSG_INVALID;
}

static int _kk_topic_parse_pkdn(_IN_ char *topic, _IN_ int start_deli, _IN_ int end_deli,
                          _OU_ char product_key[PRODUCT_TYPE_LEN], _OU_ char device_name[DEVICE_CODE_LEN])
{
    int res = 0, start = 0, end = 0, slice = 0;

    if (topic == NULL || product_key == NULL || device_name == NULL) {
        return -1;
    }
    res = kk_utils_memtok(topic, strlen(topic), KK_TOPIC_SERVICE_DELIMITER, start_deli, &start);
    if (res != 0) {
        return -1;
    }
    res = kk_utils_memtok(topic, strlen(topic), KK_TOPIC_SERVICE_DELIMITER, start_deli + 1, &slice);
    if (res != 0) {
        return -1;
    }
    res = kk_utils_memtok(topic, strlen(topic), KK_TOPIC_SERVICE_DELIMITER, end_deli, &end);
    if (res != 0) {
        return -1;
    }

    /* dm_log_debug("URI Product Key: %.*s, Device Name: %.*s", slice - start - 1, uri + start + 1, end - slice - 1,
                 uri + slice + 1); */

    memcpy(product_key, topic + start + 1, slice - start - 1);
    memcpy(device_name, topic + slice + 1, end - slice - 1);

    return 0;
}

static char * _kk_data_create(const char *topic,const char *data)
{
	cJSON *root;
	char *out;
	char *infoStr = NULL;
	int infoStr_len = 0;
	int res = 0;
    char product_key[PRODUCT_TYPE_LEN] = {0};
    char device_name[DEVICE_CODE_LEN] = {0};	
	kk_msg_type_t type;
	type = _kk_parse_type(topic);
	if(type == MSG_INVALID){
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);
		return NULL;
	}
	res =_kk_topic_parse_pkdn((char *)topic,2,4, product_key,device_name);

	infoStr_len = strlen(DM_MSG_TO_MIDDWARE)+strlen(product_key)+strlen(device_name)+10;
	infoStr = malloc(infoStr_len);
	if(infoStr == NULL){
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);
		return NULL;
	}
	memset(infoStr,0x0,infoStr_len);
	snprintf(infoStr,infoStr_len,DM_MSG_TO_MIDDWARE,type,product_key,device_name);

	root=cJSON_CreateObject();
	cJSON_AddStringToObject(root,MSG_INFO_STR,infoStr);
	cJSON_AddStringToObject(root,MSG_PAYLOAD_STR,data);
	out=cJSON_Print(root);	
	cJSON_Delete(root);
	free(infoStr);
	printf("[%s][%d]%s\n",__FUNCTION__,__LINE__,out);	
	return out;
	//free(out);	/* Print to text, Delete the cJSON, print it, release the string. */
}

void KK_Sendto_DevData(const char *topic,const char *data)
{
	if(_check_invalid_topic(topic))
	{
		return;//ingore the message
	}
	printf("[%s][%d]receive from cloud,topic:%s\n",__FUNCTION__,__LINE__,topic);	
	char *send_data = _kk_data_create(topic,data);
	if(send_data == NULL){
		return;
	}
	kk_ipc_send(IPC_APP2MID, send_data, strlen(send_data)+1);
	free(send_data);
}
