/*
 * 
 */
#include "iotx_ota_internal.h"
#include "dm_ota.h"
#include "cJSON.h"
#include "kk_dm_api.h"
#include "kk_dm_msg.h"

#include "com_api.h"


static dm_ota_ctx_t g_dm_ota_ctx;

static dm_ota_ctx_t *_dm_ota_get_ctx(void)
{
    return &g_dm_ota_ctx;
}

int dm_ota_init(void)
{
    dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
    memset(ctx, 0, sizeof(dm_ota_ctx_t));

    HAL_GetProduct_Type(ctx->productType);
    HAL_GetProduct_Code(ctx->deviceCode);

    return SUCCESS_RETURN;
}

int dm_ota_sub(void)
{
    dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
    void *handle = NULL;

    /* Init OTA Handle */
    handle = IOT_OTA_Init(ctx->productType, ctx->deviceCode, NULL);
    if (handle == NULL) {
        return FAIL_RETURN;
    }

    ctx->ota_handle = handle;

    return SUCCESS_RETURN;
}

int ota_uri_parse_pkdn(_IN_ char *uri, _IN_ int uri_len, _IN_ int start_deli, _IN_ int end_deli,
                          _OU_ char productType[PRODUCT_TYPE_MAXLEN], _OU_ char deviceCode[DEVICE_CODE_MAXLEN])
{
    int res = 0, start = 0, end = 0, slice = 0;
    int item_index = 0;
    int count = 0;

    if (uri == NULL || uri_len <= 0 || productType == NULL || deviceCode == NULL ||
        (strlen(productType) >= PRODUCT_TYPE_MAXLEN) || (strlen(deviceCode) >= DEVICE_CODE_MAXLEN)) {
        return INVALID_PARAMETER;
    }


    for (item_index = 0; item_index < uri_len; item_index++) {
        if (uri[item_index] == '/' && (item_index + 1) < uri_len) {
            count++;
            if (count == start_deli) {
                start = item_index;
            }else if (count == start_deli + 1){
                slice = item_index;
            }else if (count == end_deli){
                end = item_index;
            }
        }
    }

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

    memcpy(productType, uri + start + 1, slice - start - 1);
    memcpy(deviceCode, uri + slice + 1, end - slice - 1);

    return SUCCESS_RETURN;
}


int dm_ota_setPKN(char productType[PRODUCT_TYPE_MAXLEN],char deviceCode[DEVICE_CODE_MAXLEN])
{
    dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
    int res = 0;                     
    memset(ctx->productType, 0, PRODUCT_TYPE_MAXLEN);
    memset(ctx->deviceCode, 0, DEVICE_CODE_MAXLEN);
    memcpy(ctx->productType, productType, PRODUCT_TYPE_MAXLEN);
    memcpy(ctx->deviceCode, deviceCode, DEVICE_CODE_MAXLEN);

    return SUCCESS_RETURN;
}


int dm_ota_deinit(void)
{
    dm_ota_ctx_t *ctx = _dm_ota_get_ctx();

    if (ctx->ota_handle) {
        IOT_OTA_Deinit(ctx->ota_handle);
        ctx->ota_handle = NULL;
    }

    return SUCCESS_RETURN;
}

#if 0
int dm_ota_switch_device(int devid)
{
    char pk[PRODUCT_KEY_MAXLEN] = {0};
    char dn[DEVICE_NAME_MAXLEN] = {0};
    char ds[DEVICE_SECRET_MAXLEN] = {0};
    int ret = dm_mgr_search_device_by_devid(devid, pk, dn, ds);
    void *ota_handle = NULL;
    int res = -1;
    dm_ota_ctx_t *ctx = NULL;

    if (SUCCESS_RETURN != ret) {
        dm_log_err("could not find device by id, ret is %d", ret);
        return FAIL_RETURN;
    }
    dm_log_info("do subdevice ota, pk, dn is %s, %s", pk, dn);

    ota_handle = NULL;
    res = dm_ota_get_ota_handle(&ota_handle);

    if (res != SUCCESS_RETURN) {
        return FAIL_RETURN;
    }

    /* if currently a device is doing OTA, do not interrupt */
    if (IOT_OTA_IsFetching(ota_handle)) {
        dm_log_info("OTA is processing, can not switch to another device");
        return FAIL_RETURN;
    }

    dm_ota_deinit();
    ctx = _dm_ota_get_ctx();
    memset(ctx, 0, sizeof(dm_ota_ctx_t));

    memcpy(ctx->product_key, pk, strlen(pk) + 1);
    memcpy(ctx->device_name, dn, strlen(dn) + 1);
    ret = dm_ota_sub();
    if (ret < 0) {
        dm_log_err("dm_ota_sub ret is %d, %s, %s\n", ret, pk, dn);
    }
    return ret;
}
#endif

int dm_ota_get_ota_handle(void **handle)
{
    dm_ota_ctx_t *ctx = _dm_ota_get_ctx();

    if (handle == NULL || *handle != NULL) {
        return FAIL_RETURN;
    }

    if (ctx->ota_handle == NULL) {
        return FAIL_RETURN;
    }

    *handle = ctx->ota_handle;

    return SUCCESS_RETURN;
}

void dm_ota_handle(void *data){

    printf("dm_ota_handle ================== [%s]\n",data);
    char *out;
    int res = 0;
    cJSON *json,*info_root,*info;
    cJSON *topic,*typeJson;
    cJSON *payload;
    cJSON *product_type,*device_code;
    json=cJSON_Parse(data);
	if (json == NULL) {
        printf("Error before: [%s]\n","cJSON_Parse");
		return;
    }
	
    info_root = cJSON_GetObjectItem(json, MSG_INFO_STR);
	info = cJSON_Parse(info_root->valuestring);
	typeJson = cJSON_GetObjectItem(info, MSG_TYPE_STR);	
	product_type = cJSON_GetObjectItem(info, MSG_PRODUCT_TYPE_STR);
	device_code = cJSON_GetObjectItem(info, MSG_DEVICE_CODE_STR);
    payload = cJSON_GetObjectItem(json, MSG_PAYLOAD_STR);

    printf(" payload= %s  \n",payload->valuestring );
    if (strstr(typeJson->valuestring,KK_THING_OTA_DEVICE_UPGRADE)){
        char buf[128] = {0};
        int len = 128;
        if (dm_ota_check(payload->valuestring, strlen(payload->valuestring)+1, IOTX_OTA_TOPIC_TYPE_DEVICE_UPGRATE) == 0){
            dm_ota_setPKN(product_type->valuestring,device_code->valuestring);
            dm_fota_perform_sync(buf, len);
        }else{
            printf("parse params error !!  \n");
        }
        
        
    }else {
        printf("invaild ota type: [%d]\n", atoi(typeJson->valuestring));
    }
    cJSON_Delete(json);
	cJSON_Delete(info);	
  
}

int  dm_ota_check(void* payload, int len, iotx_ota_topic_types_t type){
    void *ota_handle = NULL;

    void* otaHandle = NULL;
    
    dm_ota_get_ota_handle(&otaHandle);

    return ota_callback(otaHandle, payload, len,type);
   
}

int dm_ota_yield(int timeout_ms)
{
    void *data = NULL;
    int count = 0;
    
    if (timeout_ms <= 0) {
        return INVALID_PARAMETER;
    }

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

        if (dm_queue_msg_next3(&data) == SUCCESS_RETURN) {
            //dm_queue_msg_t *msg = (dm_queue_msg_t *)data;
            printf("dm_ota_yield call \n");
            dm_ota_handle(data);

            
            free(data);
            data = NULL;
        } else {
            break;
        }
    }
    usleep(timeout_ms*1000);

    return SUCCESS_RETURN;
}

