#include<stdio.h>
#include"com_api.h"

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#include "cJSON.h"
#include "kk_product.h"
#include "kk_tsl_common.h"
#include "kk_dm_api.h"



void mid_cb(void* data, int len){
	if (data != NULL){

        char *out;
        cJSON *json;
        cJSON *info_root,*info,*type;
        cJSON*payload;
		cJSON*product_type,*device_name;
        int res;
        void* buf = malloc(len);
        memcpy(buf, data, len);
        res = dm_queue_msg_insert((void *)buf);
        if (res != SUCCESS_RETURN) {
            free(buf);
            //return FAIL_RETURN;
        }

    	json=cJSON_Parse(data);
    	if (!json) {
            printf("Error before: [%s]\n","cJSON_Parse");
        }
    	else
    	{
            info_root = cJSON_GetObjectItem(json, MSG_INFO_STR);
			info = cJSON_Parse(info_root->valuestring);
			product_type = cJSON_GetObjectItem(info, MSG_PRODUCT_TYPE_STR);	
			device_name = cJSON_GetObjectItem(info, MSG_DEVICE_NAME_STR);				
			type = cJSON_GetObjectItem(info, MSG_TYPE_STR);
			switch(atoi(type->valuestring))
			{
				case MSG_REGISTER_REPLY:
			    case MSG_TOPOADD_REPLY:
				case MSG_LOGIN_REPLY:
				case MSG_OTA_UPGRADE:
				case MSG_OFFLINE_REPLY:
					printf("This topic don't send to platform \r\n");
					cJSON_Delete(info);
					return;
				default:
					break;
			}
            
            payload = cJSON_GetObjectItem(json, MSG_PAYLOAD_STR);
			
            char mac[DEVICE_MAC_MAXLEN] = {0};
            res =dm_mgr_search_mac_by_pkdn(product_type->valuestring,device_name->valuestring, mac);
            if (res != SUCCESS_RETURN) {
				cJSON_Delete(json);
				cJSON_Delete(info);
                return;
            }
            cJSON * jsonplay=cJSON_Parse(payload->valuestring);
            cJSON_AddStringToObject(jsonplay, "mac", mac);
            void* out =  cJSON_Print(jsonplay);
            printf("dm_mgr_search_mac_by_topic out: %s  \r\n", out);
            kk_ipc_send(IPC_MID2PLAT, out, strlen(out));
            free(out);
            cJSON_Delete(jsonplay);
            cJSON_Delete(json);
			cJSON_Delete(info);
            
	    }
	}
}

void mid2p_cb(void* data, int len){
	if (data != NULL){
		//printf("mid2plat_cb: %s RECEIVED \r\n", data);
		void* buf = malloc(len);
        memcpy(buf, data, len);
        int res = dm_queue_msg_insert2((void *)buf);
        if (res != SUCCESS_RETURN) {
            free(buf);
            return ;
        }
		
        //kk_ipc_send(IPC_MID2APP, data, len);
	}
}

void kk_platMsg_handle(void* data){
    
    char *out;
    int res = 0;
    cJSON *json;
    cJSON *method;
    cJSON *params;
    cJSON *jsonPay;
    cJSON *proType;
    cJSON *proCode;
    cJSON *mac;
    
    json=cJSON_Parse(data);
	if (!json) {
        printf("Error before: [%s]\n","cJSON_Parse");
    }
	else{
        method = cJSON_GetObjectItem(json, "method");
        mac = cJSON_GetObjectItem(json, "mac");
        if (method != NULL && strcmp(method->valuestring, "thing.topo.add")==0){

                jsonPay = cJSON_GetObjectItem(json, "params");
                proType = cJSON_GetObjectItem(jsonPay, "productType");
                proCode = cJSON_GetObjectItem(jsonPay, "productCode");
                
                printf("productType productCode mac: [%s][%s] [%s] \n",proType->valuestring, proCode->valuestring, mac->valuestring);
                kk_mid_subdev_add(proType->valuestring,proCode->valuestring,"", mac->valuestring);
                
        }else if (method != NULL && mac != NULL){
            printf("save property and send to cloud \n");
            kk_tsl_property_set_byMac(mac->valuestring, data, strlen(data)+1);
            
        }else{
            printf("kk_platMsg_handle data: don't handle it [%s]\n",data);
        
            //kk_tsl_service_property_set(topic->valuestring, payload->valuestring, strlen(payload->valuestring), NULL);
        }
        cJSON_Delete(json);
   }
}

void kk_platMsg_dispatch(void)
{
    int count = 0;
    void *data = NULL;

    while (CONFIG_DISPATCH_QUEUE_MAXLEN == 0 || count++ < CONFIG_DISPATCH_QUEUE_MAXLEN) {

        if (dm_queue_msg_next2(&data) == SUCCESS_RETURN) {
            //dm_queue_msg_t *msg = (dm_queue_msg_t *)data;
            printf("kk_handle_platMsg_dispatch get call \n");
            if (kk_platMsg_handle) {
                kk_platMsg_handle( data);
            }

            
            free(data);
            data = NULL;
        } else {
            break;
        }
    }
}


time_t getSysTime(){
    time_t t;  
    t = time(NULL);  
    return t;

}

typedef struct {
    int auto_add_subdev;
    int master_devid;
    int cloud_connected;
    int master_initialized;
    int subdev_index;
    int permit_join;
    void *g_mid_dispatch_thread;
    void *g_ota_dispatch_thread;
    int g_mid_dispatch_thread_running;
    int g_ota_dispatch_thread_running;
} mid_ctx_t;
#define MID_YIELD_TIMEOUT_MS (200)


static mid_ctx_t g_mid_ctx;

static mid_ctx_t *kk_mid_get_ctx(void)
{
    return &g_mid_ctx;
}

extern void IOT_Linkkit_Yield(int timeout_ms);
void *mid_dispatch_yield(void *args)
{
    mid_ctx_t *mid_ctx = kk_mid_get_ctx();

    while (mid_ctx->g_mid_dispatch_thread_running) {
        IOT_Linkkit_Yield(MID_YIELD_TIMEOUT_MS);
    }

    return NULL;
}

void *ota_dispatch_yield(void *args)
{
    mid_ctx_t *mid_ctx = kk_mid_get_ctx();

    while (mid_ctx->g_ota_dispatch_thread_running) {
        dm_ota_yield(MID_YIELD_TIMEOUT_MS);
    }

    return NULL;
}




static int kk_set_product_info(void)
{
	HAL_SetProduct_Type(PRODUCT_TPYE);
	HAL_SetProduct_Code(PRODUCT_CODE);	
	return 0;
}

int main(const int argc, const char **argv)
{
		
        int res = 0;
        mid_ctx_t *mid_ctx = kk_mid_get_ctx();

        
        memset(mid_ctx, 0, sizeof(mid_ctx_t));
		
		kk_set_product_info();
        kk_tsl_api_init();

        kk_ipc_init(IPC_MID2APP, mid_cb);
        kk_ipc_init(IPC_MID2PLAT, mid2p_cb);
		


        //DB_Init();
        //test_tcp();
        /* when Connect to app and platfrom */
        /*do {
            res = IOT_Linkkit_Connect(user_example_ctx->master_devid);
            if (res < 0) {
                EXAMPLE_TRACE("IOT_Linkkit_Connect failed, retry after 5s...\n");
                HAL_SleepMs(5000);
            }
        } while (res < 0);*/
        kk_init_dmproc();
		kk_subDb_init();
        mid_ctx->g_mid_dispatch_thread_running = 1;
        res = pthread_create(&mid_ctx->g_mid_dispatch_thread, NULL, mid_dispatch_yield, NULL);
        if (res < 0) {
            printf("HAL_ThreadCreate Failed\n");
            IOT_Linkkit_Close(mid_ctx->master_devid);
            return -1;
        }
        mid_ctx->g_ota_dispatch_thread_running = 1;
        res = pthread_create(&mid_ctx->g_ota_dispatch_thread, NULL, ota_dispatch_yield, NULL);
        if (res < 0) {
            printf("HAL_ThreadCreate Failed\n");
            IOT_Linkkit_Close(mid_ctx->master_devid);
            return -1;
        }

        int ct = 0;
		for (;;) {
                usleep(200000);
                kk_platMsg_dispatch();
                if (ct == 0){
                    ct =1;
                    void* buf = "{        \"msgId\":        \"7\", \"version\":      \"1.0\", \"mac\":  \"588E81FFFED3834A\", \"method\":       \"thing.topo.add\",    \"params\":       {          \"AppVersion\":   \"10\",  \"deviceType\":   \"1\",  \"deviceCode\":   \"2\",   \"productType\":  \"3\",   \"productCode\":  \"4\"  }}";
                    kk_platMsg_handle(buf);
                    //kk_set_tsl_by_productKey("a1OYuSallan","model.json");
                    //kk_mid_subdev_add("a1OYuSallan","allanWno8yDdsjCX15iq","","aabbccddeeff1122");
                }

        }
}

