#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"
#define KK_FILTER_STATUS_ONLINE                "/thing/status/online"
#define KK_FILTER_STATUS_ONLINE_REPLY          "/thing/status/online_reply"

#define KK_CLOUDSTATE_MSG                      "/thing/ccu/cloudstate"

const char DM_MSG_TO_MIDDWARE[] = "{\"msgtype\":\"%s\",\"productCode\":\"%s\",\"deviceCode\":\"%s\"}";
#define KK_TOPIC_SERVICE_DELIMITER 			  '/'

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){
		free(topic);
		return -1;
	}
	char* out=cJSON_Print(pData);
	INFO_PRINT("[%s][%d] payload:%s\n",__FUNCTION__,__LINE__,out);	
	KK_MQTT_SendMsg(topic,(const char*)out);	
	free(topic);
	free(out);
	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){
	    ERROR_PRINT("[%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;
	}
	else if(strstr(topic, KK_FILTER_STATUS_ONLINE) != NULL && \
		strstr(topic,KK_FILTER_STATUS_ONLINE_REPLY) == NULL){
		return 1;
	}
	return 0;
}

static int _kk_topic_parse_msgType(_IN_ char *topic, _IN_ int start_deli,_OU_ char **msgTypeStr)
{
    int res = 0, start = 0, len = 0, slice = 0;
	char *msgTypeStr_tmp = NULL;

    if (topic == NULL) {
        return -1;
    }
    res = kk_utils_memtok(topic, strlen(topic), KK_TOPIC_SERVICE_DELIMITER, start_deli, &start);
    if (res != 0) {
        return -1;
    }
	len = strlen(topic) - start + 1;
	msgTypeStr_tmp = (char*)malloc(len+1);
	if(msgTypeStr_tmp == NULL){
		ERROR_PRINT("[%s][%d]malloc fail!!!\n",__FUNCTION__,__LINE__);
		return -1;
	}
	memcpy(msgTypeStr_tmp, topic + start, len);
	*msgTypeStr = msgTypeStr_tmp;
	INFO_PRINT("[%s][%d]%s\n",__FUNCTION__,__LINE__,*msgTypeStr);


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

    return 0;
}

static int _kk_topic_parse_pkdn(_IN_ char *topic, _IN_ int start_deli,
                           _OU_ char productCode[PRODUCT_CODE_LEN],_OU_ char deviceCode[DEVICE_CODE_LEN])
{
    int res = 0, start = 0, end = 0, slice = 0;

    if (topic == NULL || deviceCode == 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, start_deli + 2, &end);
    if (res != 0) {
        return -1;
    }

    memcpy(productCode, topic + start + 1, slice - start - 1);	
    memcpy(deviceCode, 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 productCode[PRODUCT_CODE_LEN] = {0};	
    char deviceCode[DEVICE_CODE_LEN] = {0};	
	char * msgStr = NULL;

	res =_kk_topic_parse_pkdn((char *)topic,3,productCode,deviceCode);
	res|=_kk_topic_parse_msgType((char *)topic,5,&msgStr);
	infoStr_len = strlen(DM_MSG_TO_MIDDWARE)+strlen(productCode)+strlen(deviceCode)+strlen(msgStr)+10;
	infoStr = malloc(infoStr_len);
	if(infoStr == NULL){
		ERROR_PRINT("[%s][%d]\n",__FUNCTION__,__LINE__);
		free(msgStr);
		return NULL;
	}
	memset(infoStr,0x0,infoStr_len);
	snprintf(infoStr,infoStr_len,DM_MSG_TO_MIDDWARE,msgStr,productCode,deviceCode);

	root=cJSON_CreateObject();
    cJSON* infoObj = cJSON_Parse(infoStr);
    cJSON* payloadObj = cJSON_Parse(data);
    cJSON_AddItemToObject(root, MSG_INFO_STR, infoObj);
    cJSON_AddItemToObject(root, MSG_PAYLOAD_STR,payloadObj);		
	out=cJSON_Print(root);	
	cJSON_Delete(root);
	free(msgStr);
	free(infoStr);
	INFO_PRINT("[%s][%d]%s\n",__FUNCTION__,__LINE__,out);	
	return out;
	//free(out);	/* Print to text, Delete the cJSON, print it, release the string. */
}
const char DM_MSG_CLOUDSTATE[] = "{\"msgId\":\"1\",\"version\":\"1.0\",\"params\":{\"IOTCloudState\":\"%d\"},\"method\":\"/thing/ccu/cloudstate\"}";

int KK_Send_CloudState(int state)
{
	char *infoStr = NULL;
	char *payloadStr = NULL;	
	int infoStr_len = 0;
	int payloadStr_len = 0;	
	cJSON *root;
	char *out;

	infoStr_len = strlen(DM_MSG_TO_MIDDWARE)+strlen(KK_CLOUDSTATE_MSG)+10;
	infoStr = malloc(infoStr_len);
	if(infoStr == NULL){
		ERROR_PRINT("[%s][%d]\n",__FUNCTION__,__LINE__);
		return -1;
	}
	memset(infoStr,0x0,infoStr_len);
	snprintf(infoStr,infoStr_len,DM_MSG_TO_MIDDWARE,KK_CLOUDSTATE_MSG,"","");

	payloadStr_len = strlen(DM_MSG_CLOUDSTATE) + 10;
	payloadStr = malloc(payloadStr_len);
	if(payloadStr == NULL){
		ERROR_PRINT("[%s][%d]\n",__FUNCTION__,__LINE__);
		return -1;
	}
	memset(payloadStr,0x0,payloadStr_len);
	snprintf(payloadStr,payloadStr_len,DM_MSG_CLOUDSTATE,state);
	
	root=cJSON_CreateObject();
    cJSON* infoObj = cJSON_Parse(infoStr);
    cJSON* payloadObj = cJSON_Parse(payloadStr);
    cJSON_AddItemToObject(root, MSG_INFO_STR, infoObj);
    cJSON_AddItemToObject(root, MSG_PAYLOAD_STR,payloadObj);			
	out=cJSON_Print(root);	
	kk_ipc_send(IPC_APP2MID, out, strlen(out)+1);
	cJSON_Delete(root);
	free(payloadStr);
	free(infoStr);
	INFO_PRINT("[%s][%d]%s\n",__FUNCTION__,__LINE__,out);	
	free(out);
	return 0;
}
void KK_Sendto_DevData(const char *topic,const char *data)
{
	if(_check_invalid_topic(topic))
	{
		return;//ingore the message
	}
	INFO_PRINT("[%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);
}
