/*
 * Copyright (C) 2020-2020 ikonke
 */



#include "kk_dm_api.h"
#include "kk_tsl_common.h"
#include "kk_dm_mng.h"
#include "com_api.h"
#include "dm_ota.h"
#include "kk_log.h"


static dm_api_ctx_t g_dm_api_ctx;

static dm_api_ctx_t *_dm_api_get_ctx(void)
{
    return &g_dm_api_ctx;
}

static void _dm_api_lock(void)
{
    dm_api_ctx_t *ctx = _dm_api_get_ctx();
    if (ctx->mutex) {
        HAL_MutexLock(ctx->mutex);
    }
}

static void _dm_api_unlock(void)
{
    dm_api_ctx_t *ctx = _dm_api_get_ctx();
    if (ctx->mutex) {
        HAL_MutexUnlock(ctx->mutex);
    }
}

int kk_dm_subdev_register(_IN_ int devid)
{
    int res = 0;
    //dm_mgr_dev_node_t *search_node = NULL;

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    _dm_api_lock();
    //res = dm_mgr_search_dev_by_devid(devid, (void **)&search_node);
    //if (res != SUCCESS_RETURN) {
       // _dm_api_unlock();
       //return FAIL_RETURN;
    //}

    res = dm_mgr_upstream_thing_sub_register(devid);

    _dm_api_unlock();
    return res;
}

int kk_dm_subdev_unregister(_IN_ int devid)
{
    int res = 0;

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    _dm_api_lock();

    res = dm_mgr_upstream_thing_sub_unregister(devid);

    _dm_api_unlock();
    return res;
}

int kk_dm_subdev_topo_add(_IN_ int devid)
{
    int res = 0;

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    _dm_api_lock();

    res = dm_mgr_upstream_thing_topo_add(devid);

    _dm_api_unlock();
    return res;
}

int iotx_dm_subdev_topo_del(_IN_ int devid)
{
    int res = 0;

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    _dm_api_lock();

    res = dm_mgr_upstream_thing_topo_delete(devid);

    _dm_api_unlock();
    return res;
}
int iotx_dm_ccu_cloud_check(void)
{
    int res = 0;

    _dm_api_lock();
    res = dm_mgr_ccu_status_cloud(0);
    _dm_api_unlock();
    return res;
}

int iotx_dm_dev_online(_IN_ int devid)
{
    int res = 0;

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    _dm_api_lock();

    res = dm_mgr_upstream_status_online(devid);

    _dm_api_unlock();
    return res;
}

int iotx_dm_dev_offline(_IN_ int devid)
{
    int res = 0;

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    _dm_api_lock();

    res = dm_mgr_upstream_status_offline(devid);

    _dm_api_unlock();
    return res;
}

int iotx_dm_subdev_login(_IN_ int devid)
{
    int res = 0;

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    _dm_api_lock();

    res = dm_mgr_upstream_combine_login(devid);

    _dm_api_unlock();
    return res;
}

int iotx_dm_subdev_logout(_IN_ int devid)
{
    int res = 0;

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    _dm_api_lock();

    res = dm_mgr_upstream_combine_logout(devid);

    _dm_api_unlock();
    return res;
}


void iotx_dm_dispatch(void)
{
    int count = 0;
    void *data = NULL;
    dm_api_ctx_t *ctx = _dm_api_get_ctx();

#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
    dm_cota_status_check();
    dm_fota_status_check();
#endif
    while (CONFIG_DISPATCH_QUEUE_MAXLEN == 0 || count++ < CONFIG_DISPATCH_QUEUE_MAXLEN) {
        //printf("iotx_dm_dispatch time=%d \n", HAL_UptimeMs());
        if (dm_queue_msg_next(&data) == SUCCESS_RETURN) {
            //dm_queue_msg_t *msg = (dm_queue_msg_t *)data;
            INFO_PRINT("dm_queue_msg_next call \n");
            if (ctx->event_callback) {
                ctx->event_callback(1, data);
            }
            free(data);
            data = NULL;
        }else if(kk_get_cloudstatus()&&dm_queue_msg_next4(&data) == SUCCESS_RETURN){
			kk_ipc_send(IPC_MID2APP, data, strlen(data)+1);
            free(data);
            data = NULL;
		}
		else {
            break;
        }
    }
}

int iotx_dm_connect(_IN_ iotx_dm_event_callback cb)
{
    int res = 0;
    dm_api_ctx_t *ctx = _dm_api_get_ctx();

    if (cb == NULL) {
        return INVALID_PARAMETER;
    }

    /* DM Event Callback */

    ctx->event_callback = cb;


    /*res = dm_client_connect(IOTX_DM_CLIENT_CONNECT_TIMEOUT_MS);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

#ifdef ALCS_ENABLED

    res = dm_server_connect();
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
#endif*/

    return SUCCESS_RETURN;
}

int iotx_dm_open(void)
{
    int res = 0;
    dm_api_ctx_t *ctx = _dm_api_get_ctx();

    memset(ctx, 0, sizeof(dm_api_ctx_t));

    /* DM Mutex Create*/
    ctx->mutex = HAL_MutexCreate();
    if (ctx->mutex == NULL) {
        return MEMORY_NOT_ENOUGH;
    }


    /* DM OTA Module Init */
    res = dm_ota_init();
    if (res != SUCCESS_RETURN) {
        goto ERROR;
    }


    /* DM Cloud Message Parse And Assemble Module Init */
    //res = dm_msg_init();
    //if (res != SUCCESS_RETURN) {
    //    goto ERROR;
    //}

    
    /* DM QUEUE Module Init */
    res = dm_queue_init(CONFIG_DISPATCH_QUEUE_MAXLEN);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* DM Manager Module Init */
    res = dm_mgr_init();
    if (res != SUCCESS_RETURN) {
        goto ERROR;
    }


    /* DM OTA Module Init */
    res = dm_ota_sub();
    if (res == SUCCESS_RETURN) {
        /* DM Config OTA Module Init */
        //dm_cota_init();

        /* DM Firmware OTA Mudule Init */
        dm_fota_init();
    }


    return SUCCESS_RETURN;

ERROR:

    dm_mgr_deinit();
    dm_queue_deinit();
    //dm_msg_deinit();


    dm_ota_deinit();


    if (ctx->mutex) {
        HAL_MutexDestroy(ctx->mutex);
    }
    return FAIL_RETURN;
}


int iotx_dm_subscribe(_IN_ int devid)
{
    int res = 0, dev_type = 0;

    if (devid < 0) {
        return INVALID_PARAMETER;
    }

    dm_mgr_dev_node_t *node = NULL;
    _dm_api_lock();
    res = dm_mgr_search_dev_by_devid(devid, &node);
    if (res != SUCCESS_RETURN) {
        _dm_api_unlock();
        return FAIL_RETURN;
    }
    _dm_api_unlock();
    
    //send app to subscribe mqtt
    const char subscribe_cmd[]  =
            "{\"cmd\":\"subscribe\",\"data\":{\"productCode\":\"%s\",\"deviceCode\":\"%s\"}}";
    int len = strlen(subscribe_cmd) +strlen(node->productCode)+ strlen(node->deviceCode) + 1;
    void* buf = malloc(len);
    
    if (buf){
        HAL_Snprintf(buf, len, subscribe_cmd, node->productCode,node->deviceCode);
		#if 0
        kk_ipc_send(IPC_MID2APP, buf, len);
        free(buf);
		#else
		dm_queue_msg_insert4(buf);
		#endif
    }else{
        
        ERROR_PRINT("\n [%d][%s] malloc faild kk_ipc_send \n", __LINE__, __FUNCTION__);
        return FAIL_RETURN;
    }
    INFO_PRINT("\n [%d][%s] [%d] send app to subscribe mqtt  \n", __LINE__, __FUNCTION__, HAL_UptimeMs());


   

    return SUCCESS_RETURN;
}

void kk_dm_ota_report_version(_IN_ int devid, char *version){
    dm_mgr_ota_report_version(devid, version);
}

void kk_dm_ota_send(void *data, int len){
    dm_queue_msg_insert3(data);
    if (data != NULL){
		void* buf = malloc(len);
        memcpy(buf, data, len);
        int res = dm_queue_msg_insert3((void *)buf);
        if (res != SUCCESS_RETURN) {
            free(buf);
            return ;
        }
		
	}
}

int kk_dm_get_property_type(const char* deviceCode,const char *key)
{
	int res = 0;
    dm_mgr_dev_node_t *node = NULL;
	
	if(deviceCode == NULL){
		return FAIL_RETURN;
	}
    res = dm_mgr_get_device_by_devicecode(deviceCode, &node);
    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }
	return kk_tsl_get_property_type(node->dev_shadow,key);
}
