#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "log.h"
#include "smart_sound.h"
#include "libuv_dbus.h"
#include "json_struct.h"
#include "crypto.h"
#include "ota.h"
#include "assistant.h"

typedef const char* (*StructToJsonCb)(void* pStruct);
typedef void* (*JsonToStructCb)(const char* pJsonStr);
typedef void  (*Base64Code)(void *pStruct, int enCode);

typedef struct 
{
    JSON_ENGINE_TYPE    typeId;
    StructToJsonCb      s2jCb;
    JsonToStructCb      j2sCb;
    Base64Code          base64Cb;
} JSON_ENGINE, *PJSON_ENGINE;

static const char* __ping_MSG2Json(void* pData)
{
    PPING_MSG    pReq   = (PPING_MSG)pData;
    const char*     pJsonS;
    
    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, double, PING);
    s2j_json_set_basic_element(jObject, pReq, int, tmSec);
    s2j_json_set_basic_element(jObject, pReq, int, tmMSec);

    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);
    
    return pJsonS;
}

static void* __json2PING_MSG(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, PING_MSG);

    memset(sObject, 0, sizeof(PING_MSG));

    s2j_struct_get_basic_element(sObject, pJson, double, PING);
    s2j_struct_get_basic_element(sObject, pJson, int, tmSec);
    s2j_struct_get_basic_element(sObject, pJson, int, tmMSec);

    cJSON_Delete(pJson);
    
    return sObject;
}

static const char* __cfg_API_REQ2Json(void* pData)
{
    PCFG_API_REQ    pReq   = (PCFG_API_REQ)pData;
    const char*     pJsonS;
    
    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, string, keyName);
    s2j_json_set_basic_element(jObject, pReq, string, keyValue);
    s2j_json_set_basic_element(jObject, pReq, int, keyType);

    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);
    
    return pJsonS;
}

static void* __json2CFG_API_REQ(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, CFG_API_REQ);

    memset(sObject, 0, sizeof(CFG_API_REQ));

    s2j_struct_get_basic_element(sObject, pJson, string, keyName);
    s2j_struct_get_basic_element(sObject, pJson, string, keyValue);
    s2j_struct_get_basic_element(sObject, pJson, int, keyType);

    cJSON_Delete(pJson);
    
    return sObject;
}

static void __cfg_API_REQBase64(void *pData, int enCode)
{
    PCFG_API_REQ    pReq   = (PCFG_API_REQ)pData;

    if(enCode)
    {
        if(strlen(pReq->keyName) > 0)
        {
            char* pBase64 = (char *)EvpBase64Encode(pReq->keyName);
            memset(pReq->keyName, 0, MAX_CFG_KEY_NAME);
            strcpy(pReq->keyName, pBase64);
            free(pBase64);
        }

        if(strlen(pReq->keyValue) > 0)
        {
            char* pBase64 = (char *)EvpBase64Encode(pReq->keyValue);
            memset(pReq->keyValue, 0, MAX_CFG_KEY_VALUE);
            strcpy(pReq->keyValue, pBase64);
            free(pBase64);
        }
    }
    else
    {
        if(strlen(pReq->keyName) > 0)
        {

            char *pBase64 = (char *)EvpBase64Decode(pReq->keyName);
            memset(pReq->keyName, 0, MAX_CFG_KEY_NAME);
            strcpy(pReq->keyName, pBase64);
            free(pBase64);
        }

        if(strlen(pReq->keyValue) > 0)
        {
            char *pBase64 = (char *)EvpBase64Decode(pReq->keyValue);
            memset(pReq->keyValue, 0, MAX_CFG_KEY_VALUE);
            strcpy(pReq->keyValue, pBase64);
            free(pBase64);
        }
    }
}

static const char* __cfg_API_RSP2Json(void* pData)
{
    PCFG_API_RSP    pReq    = (PCFG_API_RSP)pData;
    const char*     pJsonS;
    
    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, string, keyName);
    s2j_json_set_basic_element(jObject, pReq, string, keyValue);
    s2j_json_set_basic_element(jObject, pReq, int, keyType);
    s2j_json_set_basic_element(jObject, pReq, int, errNo);

    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);
	
    return pJsonS;
}

static void* __json2CFG_API_RSP(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, CFG_API_RSP);

    memset(sObject, 0, sizeof(CFG_API_RSP));

    s2j_struct_get_basic_element(sObject, pJson, string, keyName);
    s2j_struct_get_basic_element(sObject, pJson, string, keyValue);
    s2j_struct_get_basic_element(sObject, pJson, int, keyType);
    s2j_struct_get_basic_element(sObject, pJson, int, errNo);

    cJSON_Delete(pJson);
    
    return sObject;
}

static void __cfg_API_RSPBase64(void *pData, int enCode)
{
    PCFG_API_RSP    pReq   = (PCFG_API_RSP)pData;

    if(enCode)
    {
        if(strlen(pReq->keyName) > 0)
        {
            char *pBase64 = (char *)EvpBase64Encode(pReq->keyName);
            memset(pReq->keyName, 0, MAX_CFG_KEY_NAME);
            strcpy(pReq->keyName, pBase64);
            free(pBase64);
        }

        if(strlen(pReq->keyValue) > 0)
        {
            char *pBase64 = (char *)EvpBase64Encode(pReq->keyValue);
            memset(pReq->keyValue, 0, MAX_CFG_KEY_VALUE);
            strcpy(pReq->keyValue, pBase64);
            free(pBase64);
        }
    }
    else
    {
        if(strlen(pReq->keyName) > 0)
        {
            char *pBase64 = (char *)EvpBase64Decode(pReq->keyName);
            memset(pReq->keyName, 0, MAX_CFG_KEY_NAME);
            strcpy(pReq->keyName, pBase64);
            free(pBase64);
        }

        if(strlen(pReq->keyValue) > 0)
        {
            char *pBase64 = (char *)EvpBase64Decode(pReq->keyValue);
            memset(pReq->keyValue, 0, MAX_CFG_KEY_VALUE);
            strcpy(pReq->keyValue, pBase64);
            free(pBase64);
        }
    }
}

static const char* __player_TO_CTRL2Json(void* pData)
{
    PPLAYER_TO_CTRL pP2C    = (PPLAYER_TO_CTRL)pData;
    const char*     pJsonS;
    
    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pP2C, string, musicUuid);
    s2j_json_set_basic_element(jObject, pP2C, int, plySt);
    s2j_json_set_basic_element(jObject, pP2C, int, curPos);
    s2j_json_set_basic_element(jObject, pP2C, int, duration);

    s2j_json_set_basic_element(jObject, pP2C, int, playerId);

    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);
	
    return pJsonS;
}

static void* __json2PLAYER_TO_CTRL(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, PLAYER_TO_CTRL);

    memset(sObject, 0, sizeof(PLAYER_TO_CTRL));

    s2j_struct_get_basic_element(sObject, pJson, string, musicUuid);
    s2j_struct_get_basic_element(sObject, pJson, int, plySt);
    s2j_struct_get_basic_element(sObject, pJson, int, curPos);
    s2j_struct_get_basic_element(sObject, pJson, int, duration);

    cJSON_Delete(pJson);
    
    return sObject;
}

static void __player_TO_CTRLBase64(void *pData, int enCode)
{
    PPLAYER_TO_CTRL    pReq   = (PPLAYER_TO_CTRL)pData;

    if(enCode)
    {
        if(strlen(pReq->musicUuid) > 0)
        {
            char *pBase64 = (char *)EvpBase64Encode(pReq->musicUuid);
            memset(pReq->musicUuid, 0, MAX_MUSIC_UUID);
            strcpy(pReq->musicUuid, pBase64);
            free(pBase64);
        }
    }
    else
    {
        if(strlen(pReq->musicUuid) > 0)
        {
            char *pBase64 = (char *)EvpBase64Decode(pReq->musicUuid);
            memset(pReq->musicUuid, 0, MAX_MUSIC_UUID);
            strcpy(pReq->musicUuid, pBase64);
            free(pBase64);
        }
    }
}

static const char* __ctrl_TO_PLAYER2Json(void* pData)
{
    PCTRL_TO_PLAYER     pC2P        = (PCTRL_TO_PLAYER)pData;
    const char*         pJsonS;

    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pC2P, string, src);
    s2j_json_set_basic_element(jObject, pC2P, string, srcUuid);
	s2j_json_set_basic_element(jObject, pC2P, string, ttsText);
    s2j_json_set_basic_element(jObject, pC2P, int, skTime);
    s2j_json_set_basic_element(jObject, pC2P, int, plyMode);
    s2j_json_set_basic_element(jObject, pC2P, int, plyListType);
    s2j_json_set_basic_element(jObject, pC2P, int, adSrcType);

    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);

    return pJsonS;
}

static void* __json2CTRL_TO_PLAYER(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, CTRL_TO_PLAYER);

    memset(sObject, 0, sizeof(CTRL_TO_PLAYER));

    s2j_struct_get_basic_element(sObject, pJson, string, src);
    s2j_struct_get_basic_element(sObject, pJson, string, srcUuid);
	s2j_struct_get_basic_element(sObject, pJson, string, ttsText);
    s2j_struct_get_basic_element(sObject, pJson, int, skTime);
    s2j_struct_get_basic_element(sObject, pJson, int, plyMode);
    s2j_struct_get_basic_element(sObject, pJson, int, plyListType);
    s2j_struct_get_basic_element(sObject, pJson, int, adSrcType);
	s2j_struct_get_basic_element(sObject, pJson, int, duration);
    s2j_struct_get_basic_element(sObject, pJson, int, volRestoreTime);
    s2j_struct_get_basic_element(sObject, pJson, int, volBegin);
    s2j_struct_get_basic_element(sObject, pJson, string, fifo);
    s2j_struct_get_basic_element(sObject, pJson, int, channel);
    s2j_struct_get_basic_element(sObject, pJson, int, bytes);
    s2j_struct_get_basic_element(sObject, pJson, int, sampleRate);
    s2j_struct_get_basic_element(sObject, pJson, int, playerId);
	s2j_struct_get_basic_element(sObject, pJson, double, gain);
	s2j_struct_get_basic_element(sObject, pJson, string, backGroundUrl);
	
    cJSON_Delete(pJson);

    return sObject;
}

static void __ctrl_TO_PLAYERBase64(void *pData, int enCode)
{
    PCTRL_TO_PLAYER    pReq   = (PCTRL_TO_PLAYER)pData;

    if(enCode)
    {
        if(strlen(pReq->src) > 0)
        {
            char *pBase64 = (char *)EvpBase64Encode(pReq->src);
            memset(pReq->src, 0, MAX_MUSIC_UUID);
            strcpy(pReq->src, pBase64);
            free(pBase64);
        }

        if(strlen(pReq->srcUuid) > 0)
        {
            char *pBase64 = (char *)EvpBase64Encode(pReq->srcUuid);
            memset(pReq->srcUuid, 0, MAX_MUSIC_UUID);
            strcpy(pReq->srcUuid, pBase64);
            free(pBase64);
        }
    }
    else
    {
        if(strlen(pReq->src) > 0)
        {
            char *pBase64 = (char *)EvpBase64Decode(pReq->src);
            memset(pReq->src, 0, MAX_MUSIC_UUID);
            strcpy(pReq->src, pBase64);
            free(pBase64);
        }

        if(strlen(pReq->srcUuid) > 0)
        {
            char *pBase64 = (char *)EvpBase64Decode(pReq->srcUuid);
            memset(pReq->srcUuid, 0, MAX_MUSIC_UUID);
            strcpy(pReq->srcUuid, pBase64);
            free(pBase64);
        }
    }
}

#if 0
const char* __ota_Notify_REQ2Json(void* pData)
{
    int i;
    POTA_DATA_INFO  pReq        = (POTA_DATA_INFO)pData;
    cJSON*          pRoot       = NULL;
    cJSON*          pSubArray   = NULL;
    const char*     pJsonS;

    pRoot = cJSON_CreateObject();

    cJSON_AddNumberToObject(pRoot, "version", pReq->version);
    cJSON_AddNumberToObject(pRoot, "otaMode", pReq->otaMode);

    pSubArray = cJSON_CreateArray();
    cJSON_AddItemToObject(pRoot, "otaFile", pSubArray);

    for(i = 0; i < sizeof(pReq->otaFile) / sizeof(pReq->otaFile[0]); i++)
    {
        cJSON *pItem = cJSON_CreateObject();

        cJSON_AddItemToObject(pSubArray, "", pItem);
        

        cJSON_AddStringToObject(pItem, "url", pReq->otaFile[i].url);
        cJSON_AddStringToObject(pItem, "md5", pReq->otaFile[i].md5);
        cJSON_AddNumberToObject(pItem, "size", pReq->otaFile[i].size);
    }
    
    pJsonS  = cJSON_Print(pRoot);
    cJSON_Delete(pRoot);
	
    return pJsonS;
}

void* __json2OTA_Notify_REQ(const char* pJsonS)
{
    POTA_DATA_INFO  pInfo;
    cJSON*  pSubArray = NULL;
    cJSON*  pItem = NULL;
	
    cJSON*  pRoot = cJSON_Parse(pJsonS);
    if(pRoot == NULL)
    {
        return (NULL);
    }

    pSubArray   = cJSON_GetObjectItem(pRoot, "otaFile");
    
    pInfo = (POTA_DATA_INFO)malloc(sizeof(OTA_DATA_INFO));
    memset(pInfo, 0, sizeof(OTA_DATA_INFO));

    pItem = cJSON_GetObjectItem(pRoot, "version");
    pInfo->version = pItem->valueint;

    pItem = cJSON_GetObjectItem(pRoot, "otaMode");
    pInfo->otaMode = pItem->valueint;

    if(pSubArray)
    {
        int i;
        cJSON *pList = pSubArray->child;

        for(i = 0; i < cJSON_GetArraySize(pSubArray); i++)
        {
            strcpy(pInfo->otaFile[i].url, cJSON_GetObjectItem(pList, "url")->valuestring);
            strcpy(pInfo->otaFile[i].md5, cJSON_GetObjectItem(pList, "md5")->valuestring);
            pInfo->otaFile[i].size = cJSON_GetObjectItem(pList, "size")->valueint;

            pList = pList->next;
        }
    }
    
    cJSON_Delete(pRoot);
    
    return pInfo;
}
#else
const char* __ota_Notify_REQ2Json(void* pData)
{
    POTA_DATA_INFO      pReq        = (POTA_DATA_INFO)pData;
    const char*         pJsonS;
    
    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, int, version);
    s2j_json_set_basic_element(jObject, pReq, int, otaCmd);
    s2j_json_set_basic_element(jObject, pReq, int, otaMode);

    s2j_json_set_struct_element(json_otaRes, jObject, struct_otaRes, pReq, OTA_FILE_INFO, otaFileInfo);
    s2j_json_set_basic_element(json_otaRes, struct_otaRes, string, url);
    s2j_json_set_basic_element(json_otaRes, struct_otaRes, string, md5);
    s2j_json_set_basic_element(json_otaRes, struct_otaRes, int, size);

    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);
    
    return pJsonS;
}

void* __json2OTA_Notify_REQ(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, OTA_DATA_INFO);

    memset(sObject, 0, sizeof(OTA_DATA_INFO));

    s2j_struct_get_basic_element(sObject, pJson, int, version);
    s2j_struct_get_basic_element(sObject, pJson, int, otaCmd);
    s2j_struct_get_basic_element(sObject, pJson, int, otaMode);

    s2j_struct_get_struct_element(struct_otaRes, sObject, json_otaRes, pJson, OTA_FILE_INFO, otaFileInfo);
    s2j_struct_get_basic_element(struct_otaRes, json_otaRes, string, url);
    s2j_struct_get_basic_element(struct_otaRes, json_otaRes, string, md5);
    s2j_struct_get_basic_element(struct_otaRes, json_otaRes, int, size);

    cJSON_Delete(pJson);

    return sObject;
}
#endif
static void __ota_NotifyBase64(void *pData, int enCode)
{
    POTA_DATA_INFO  pReq        = (POTA_DATA_INFO)pData;

    if(enCode)
    {
        if(strlen(pReq->otaFileInfo.url) > 0)
        {
            char *pBase64 = (char *)EvpBase64EncodeNoAlign(pReq->otaFileInfo.url);
            memset(pReq->otaFileInfo.url, 0, SIZE_1K);
            strcpy(pReq->otaFileInfo.url, pBase64);
            free(pBase64);
        }
    }
    else
    {
        if(strlen(pReq->otaFileInfo.url) > 0)
        {
            char *pBase64 = (char *)EvpBase64DecodeNoAlign(pReq->otaFileInfo.url);
            memset(pReq->otaFileInfo.url, 0, SIZE_1K);
            strcpy(pReq->otaFileInfo.url, pBase64);
            free(pBase64);
        }
    }
}

const char* __ota_Status_RSP2Json(void* pData)
{
    POTA_RSP_STATUS     pReq        = (POTA_RSP_STATUS)pData;
    const char*         pJsonS;

    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, int, status);
    s2j_json_set_basic_element(jObject, pReq, int, val);
   
    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);

    return pJsonS;
}

void* __json2OTA_Status_RSP(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, OTA_RSP_STATUS);

    memset(sObject, 0, sizeof(OTA_RSP_STATUS));

    s2j_struct_get_basic_element(sObject, pJson, int, status);
    s2j_struct_get_basic_element(sObject, pJson, int, val);
    
    cJSON_Delete(pJson);

    return sObject;
}

const char* __alarm_Run_Event_RSP2Json(void* pData)
{
    const char*         pJsonS;
    PASSISTANT_ITEM_INFO	pReq        = (PASSISTANT_ITEM_INFO)pData;
    cJSON*              	pRoot       = cJSON_CreateObject();
    cJSON*              	pSubArray   = cJSON_CreateArray();
    
    cJSON_AddItemToObject(pRoot, "data", pSubArray);

    cJSON *pItem = cJSON_CreateObject();

    cJSON_AddItemToObject(pSubArray, "", pItem);

    cJSON_AddNumberToObject(pItem, "alarmId",       pReq->itemId);
    cJSON_AddNumberToObject(pItem, "itemType",      pReq->itemType);
    cJSON_AddNumberToObject(pItem, "priority",      pReq->priority);
    cJSON_AddNumberToObject(pItem, "repeatMode",    pReq->repeatMode);

    cJSON_AddNumberToObject(pItem, "year",          pReq->year);
    cJSON_AddNumberToObject(pItem, "month",         pReq->month);
    cJSON_AddNumberToObject(pItem, "day",           pReq->day);
    cJSON_AddNumberToObject(pItem, "hour",          pReq->hour);
    cJSON_AddNumberToObject(pItem, "minute",        pReq->minute);
    cJSON_AddNumberToObject(pItem, "second",        pReq->second);
    cJSON_AddNumberToObject(pItem, "weekDay",       pReq->weekDay);

    cJSON_AddNumberToObject(pItem, "voiceId",       pReq->voiceId);
    cJSON_AddStringToObject(pItem, "strTips",       pReq->strTips);
    cJSON_AddStringToObject(pItem, "resUrl",        pReq->resUrl);

    cJSON_AddStringToObject(pItem, "voiceResType",  pReq->voiceResType);
    cJSON_AddStringToObject(pItem, "voiceRes",      pReq->voiceRes);
    
    pJsonS  = cJSON_Print(pRoot);
    cJSON_Delete(pRoot);

    return pJsonS;
}

static void __getAlarmDateTimeInfo(cJSON* pJson, PASSISTANT_ITEM_INFO pAlarmInfo)
{
    struct  tm      tmNow;
    time_t timep;

    const char *pStrYear    = cJSON_GetObjectItem(pJson, "year")->valuestring;
    const char *pStrMonth   = cJSON_GetObjectItem(pJson, "month")->valuestring;
    const char *pStrDay     = cJSON_GetObjectItem(pJson, "dayofMonth")->valuestring;
    const char *pStrHour    = cJSON_GetObjectItem(pJson, "hour")->valuestring;
    const char *pStrMinute  = cJSON_GetObjectItem(pJson, "minute")->valuestring;
    const char *pStrSecond  = cJSON_GetObjectItem(pJson, "second")->valuestring;
    const char *pStrWeekDay = cJSON_GetObjectItem(pJson, "dayofWeek")->valuestring;

    time(&timep);
    localtime_r(&timep, &tmNow);

    if(pStrYear != NULL && strlen(pStrYear) > 0)
    {
        pAlarmInfo->year = strtoul(pStrYear, NULL, 10) - 1900;
    }
    else
    {
        pAlarmInfo->year = -1;//tmNow.tm_year;
    }
    
    if(pStrMonth != NULL && strlen(pStrMonth) > 0)
    {
        pAlarmInfo->month = strtoul(pStrMonth, NULL, 10) - 1;
    }
    else
    {
        pAlarmInfo->month = -1;//tmNow.tm_mon;
    }
    
    if(pStrDay != NULL && strlen(pStrDay) > 0)
    {
        pAlarmInfo->day = strtoul(pStrDay, NULL, 10);
    }
    else
    {
        pAlarmInfo->day = -1; //tmNow.tm_mday;
    }
    
    if(pStrHour != NULL && strlen(pStrHour) > 0)
    {
        pAlarmInfo->hour = strtoul(pStrHour, NULL, 10);
    }
    else
    {
        pAlarmInfo->hour = -1;
    }

    if(pStrMinute != NULL && strlen(pStrMinute) > 0)
    {
        pAlarmInfo->minute = strtoul(pStrMinute, NULL, 10);
    }
    else
    {
        pAlarmInfo->minute = -1;
    }

    if(pStrSecond != NULL && strlen(pStrSecond) > 0)
    {
        pAlarmInfo->second = strtoul(pStrSecond, NULL, 10);
    }
    else
    {
        pAlarmInfo->second = -1;
    }

    if(pStrWeekDay != NULL && strlen(pStrWeekDay) > 0)
    {
        if(strchr(pStrWeekDay, '7') != NULL)
        {
            pAlarmInfo->weekDay |= 1;
        }

        if(strchr(pStrWeekDay, '1') != NULL)
        {
            pAlarmInfo->weekDay |= 1 << 1;
        }

        if(strchr(pStrWeekDay, '2') != NULL)
        {
            pAlarmInfo->weekDay |= 1 << 2;
        }

        if(strchr(pStrWeekDay, '3') != NULL)
        {
            pAlarmInfo->weekDay |= 1 << 3;
        }

        if(strchr(pStrWeekDay, '4') != NULL)
        {
            pAlarmInfo->weekDay |= 1 << 4;
        }

        if(strchr(pStrWeekDay, '5') != NULL)
        {
            pAlarmInfo->weekDay |= 1 << 5;
        }

        if(strchr(pStrWeekDay, '6') != NULL)
        {
            pAlarmInfo->weekDay |= 1 << 6;
        }
    }
    else
    {
        pAlarmInfo->weekDay = 0;
    }
}

void* __json2Alarm_sync_RSP(const char *pJsonS)
{
    PASSISTANT_SYNC_INFO  pInfo;
    cJSON*  pSubArray = NULL;
    //cJSON*  pItem = NULL;
	
    cJSON*  pRoot = cJSON_Parse(pJsonS);
    if(pRoot == NULL)
    {
        return (NULL);
    }

    pSubArray   = cJSON_GetObjectItem(pRoot, "data");
    
    pInfo = (PASSISTANT_SYNC_INFO)malloc(sizeof(ASSISTANT_SYNC_INFO));
    memset(pInfo, 0, sizeof(ASSISTANT_SYNC_INFO));
    
    pInfo->pAlarmInfo = NULL;

    if(pSubArray)
    {
        cJSON *pList = pSubArray->child;
        int arraySize = cJSON_GetArraySize(pSubArray);

        if(arraySize > 0)
        {
            pInfo->pAlarmInfo = (PASSISTANT_ITEM_INFO)malloc(sizeof(ASSISTANT_ITEM_INFO) * arraySize);

            pInfo->nItems = arraySize;

            for(int i = 0; i < arraySize; i++)
            {
                cJSON* pData = cJSON_GetObjectItem(pList, "vboxDate");

                memset(&pInfo->pAlarmInfo[i], 0, sizeof(ASSISTANT_ITEM_INFO));

                if(pData != NULL)
                {
                    cJSON *pItem;

                    __getAlarmDateTimeInfo(pData, &pInfo->pAlarmInfo[i]);

                    pInfo->pAlarmInfo[i].itemType   = cJSON_GetObjectItem(pList, "label")->valueint;
                    pInfo->pAlarmInfo[i].itemId     = cJSON_GetObjectItem(pList, "id")->valueint;
                    pInfo->pAlarmInfo[i].repeatMode = cJSON_GetObjectItem(pList, "type")->valueint;
                    pInfo->pAlarmInfo[i].voiceId    = cJSON_GetObjectItem(pList, "voiceType")->valueint;

                    pItem = cJSON_GetObjectItem(pList, "remark");

                    if(pInfo->pAlarmInfo[i].itemType != ASSISTANT_TYPE_CLOCK && pItem)
                    {
                        strcpy(pInfo->pAlarmInfo[i].strTips, pItem->valuestring);
                    }

                    pItem = cJSON_GetObjectItem(pList, "resUrl");

                    if(pItem)
                    {
                        strcpy(pInfo->pAlarmInfo[i].resUrl, pItem->valuestring);
                    }

                    pItem = cJSON_GetObjectItem(pList, "voiceRes");

                    if(pItem)
                    {
                        strcpy(pInfo->pAlarmInfo[i].voiceRes, pItem->valuestring);
                    }

                    pItem = cJSON_GetObjectItem(pList, "voiceResType");

                    if(pItem)
                    {
                        strcpy(pInfo->pAlarmInfo[i].voiceResType, pItem->valuestring);
                    }

                    pList = pList->next;
#if 0                        
                    fprintf(stdout, "%04u-%02u-%02u %02u:%02u:%02u %u\n", 
                            pInfo->pAlarmInfo[i].year,
                            pInfo->pAlarmInfo[i].month,
                            pInfo->pAlarmInfo[i].day,
                            pInfo->pAlarmInfo[i].hour,
                            pInfo->pAlarmInfo[i].minute,
                            pInfo->pAlarmInfo[i].second,
                            pInfo->pAlarmInfo[i].weekDay);
#endif
                }
            }
        }
    }
    
    cJSON_Delete(pRoot);
   
    return pInfo;
}

const char* __alarm_Status_RSP2Json(void* pData)
{
    const char*         pJsonS;

    PASSISTANT_RSP_STATUS   pReq        = (PASSISTANT_RSP_STATUS)pData;
    

    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, int, cmd);
    s2j_json_set_basic_element(jObject, pReq, int, val);
   
    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);

    return pJsonS;
}

void* __json2Alarm_Status_RSP(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, ASSISTANT_RSP_STATUS);

    memset(sObject, 0, sizeof(ASSISTANT_RSP_STATUS));

    s2j_struct_get_basic_element(sObject, pJson, int, cmd);
    s2j_struct_get_basic_element(sObject, pJson, int, val);
    
    cJSON_Delete(pJson);

    return sObject;

}

const char* __alarm_change_RSP2Json(void* pData)
{
    const char*         	pJsonS;
    PASSISTANT_NOTIFY_INFO  pReq    = (PASSISTANT_NOTIFY_INFO)pData;

    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, int, cmd);
    s2j_json_set_basic_element(jObject, pReq, int, type);
    s2j_json_set_array_element(jObject, pReq, double, ids, pReq->nItems);
        
    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);

    return pJsonS;
}

void* __json2Alarm_change_RSP(const char* pJsonS)
{
    PASSISTANT_NOTIFY_INFO  pInfo   = NULL;
    cJSON*  pSubArray = NULL;
    cJSON*  pItem = NULL;

	cJSON*  pRoot = cJSON_Parse(pJsonS);
    if(pRoot == NULL)
    {
        return (NULL);
    }

    pSubArray   = cJSON_GetObjectItem(pRoot, "ids");

    pInfo = (PASSISTANT_NOTIFY_INFO)malloc(sizeof(ASSISTANT_NOTIFY_INFO));
    memset(pInfo, 0, sizeof(ASSISTANT_NOTIFY_INFO));

    pItem = cJSON_GetObjectItem(pRoot, "type");
    pInfo->type = pItem->valueint;

#if 0
    pItem = cJSON_GetObjectItem(pRoot, "cmd");
    pInfo->cmd  = pItem->valueint;
#endif

    if(pSubArray)
    {
        int arraySize = cJSON_GetArraySize(pSubArray);

        if(arraySize > 0)
        {
            pInfo->nItems = arraySize;

            for(int i = 0; i < arraySize; i++)
            {
                pInfo->ids[i] = (unsigned long long)(cJSON_GetArrayItem(pSubArray, i)->valuedouble);
            }
        }
    }

    cJSON_Delete(pRoot);

    return pInfo;
}
#if 0
const char* __alarm_change_RSP2Json(void* pData)
{
    int i = 0;
    PALARM_REMOVE_INFO  pReq        = (PALARM_REMOVE_INFO)pData;
    cJSON*              pRoot       = NULL;
    cJSON*              pSubArray   = NULL;
    const char*         pJsonS;

    pRoot = cJSON_CreateObject();

    cJSON_AddNumberToObject(pRoot, "nItems",    pReq->nItems);

    pSubArray = cJSON_CreateArray();
    cJSON_AddItemToObject(pRoot, "data", pSubArray);

    for(i = 0; i < pReq->nItems; i++)
    {
        cJSON *pItem = cJSON_CreateObject();

        cJSON_AddItemToObject(pSubArray, "", pItem);

        cJSON_AddNumberToObject(pItem, "alarmId",       pReq->pItemInfo[i].alarmId);
        cJSON_AddNumberToObject(pItem, "itemType",      pReq->pItemInfo[i].itemType);
    }
   
    pJsonS  = cJSON_Print(pRoot);
    cJSON_Delete(pRoot);
   
    return pJsonS;
}

void* __json2Alarm_change_RSP(const char* pJsonS)
{
    PALARM_REMOVE_INFO  pInfo   = NULL;
    cJSON*  pRoot = cJSON_Parse(pJsonS);
    cJSON*  pSubArray = NULL;
    cJSON*  pItem = NULL;
    int     itemType = 0;

    if(pRoot == NULL)
    {
        return (NULL);
    }

    pSubArray   = cJSON_GetObjectItem(pRoot, "data");

    pInfo = (PALARM_REMOVE_INFO)malloc(sizeof(ALARM_REMOVE_INFO));
    memset(pInfo, 0, sizeof(ALARM_REMOVE_INFO));

    pItem = cJSON_GetObjectItem(pRoot, "type");
    itemType = pItem->valueint;

    pInfo->pItemInfo    = NULL;

    if(pSubArray)
    {
        int i;
        cJSON *pList = pSubArray->child;
        int arraySize = cJSON_GetArraySize(pSubArray);

        if(arraySize > 0)
        {
            pInfo->pItemInfo = (PITEM_INFO)malloc(sizeof(ITEM_INFO) * arraySize);
            pInfo->nItems = arraySize;

            for(i = 0; i < arraySize; i++)
            {
                memset(&pInfo->pItemInfo[i], 0, sizeof(ALARM_ITEM_INFO));

                pInfo->pItemInfo[i].itemType = itemType; 
                pInfo->pItemInfo[i].alarmId = cJSON_GetObjectItem(pList, "id")->valueint;    
                
                pList = pList->next;
            }
        }
    }

    cJSON_Delete(pRoot);

    return pInfo;
}
#endif

const char* __alarm_WorkData_RSP2Json(void* pData)
{
    const char*     pJsonS;
    PWORKDAY_INFO   pReq    = (PWORKDAY_INFO)pData;

    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, int, year);
        
    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);

    return pJsonS;
}

void* __json2Alarm_WorkData_RSP(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, WORKDAY_INFO);

    memset(sObject, 0, sizeof(WORKDAY_INFO));
    
    s2j_struct_get_basic_element(sObject, pJson, int, year);
    s2j_struct_get_array_element(sObject, pJson, int, days);

    cJSON_Delete(pJson);
    
    return sObject;
}


const char* __logCfg_RSP2Json(void* pData)
{
    PLOG_CFG_PROTOCOL   pReq        = (PLOG_CFG_PROTOCOL)pData;
    const char*         pJsonS;

    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, int, cfgCmd);
    s2j_json_set_basic_element(jObject, pReq, int, iParams1);
    s2j_json_set_basic_element(jObject, pReq, int, iParams2);
   
    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);

    return pJsonS;
}

void* __json2LogCfg_RSP(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, LOG_CFG_PROTOCOL);

    memset(sObject, 0, sizeof(LOG_CFG_PROTOCOL));

    s2j_struct_get_basic_element(sObject, pJson, int, cfgCmd);
    s2j_struct_get_basic_element(sObject, pJson, int, iParams1);
    s2j_struct_get_basic_element(sObject, pJson, int, iParams2);
    
    cJSON_Delete(pJson);

    return sObject;
}

const char* __wifiStatus_RSP2Json(void* pData)
{
    PWIFI_STATUS_PRO    pReq        = (PWIFI_STATUS_PRO)pData;
    const char*         pJsonS;

    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, int, wifi_evt);
   
    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);

    return pJsonS;
}

void* __json2WifiStatus_RSP(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, WIFI_STATUS_PRO);

    memset(sObject, 0, sizeof(WIFI_STATUS_PRO));

    s2j_struct_get_basic_element(sObject, pJson, int, wifi_evt);
    
    cJSON_Delete(pJson);

    return sObject;
}

void* __json2McuGuideCmd_RSP(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, MCU_TEST_GUIDE_CMD);

    memset(sObject, 0, sizeof(MCU_TEST_GUIDE_CMD));

    s2j_struct_get_basic_element(sObject, pJson, int, red);
	s2j_struct_get_basic_element(sObject, pJson, int, green);
	s2j_struct_get_basic_element(sObject, pJson, int, blue);
    
    cJSON_Delete(pJson);

    return sObject;
}

void* __json2McuMatrixCmd_RSP(const char* pJsonS)
{
    cJSON*  pJson = cJSON_Parse(pJsonS);

    s2j_create_struct_obj(sObject, MCU_TEST_MATRIX_CMD);

    memset(sObject, 0, sizeof(MCU_TEST_MATRIX_CMD));

    s2j_struct_get_basic_element(sObject, pJson, int, level);
    
    cJSON_Delete(pJson);

    return sObject;
}

const char* __mcuVersion_RSP2Json(void* pData)
{
    PMCU_TEST_VER_CMD    pReq        = (PMCU_TEST_VER_CMD)pData;
    const char*         pJsonS;

    s2j_create_json_obj(jObject);

    s2j_json_set_basic_element(jObject, pReq, string, McuVer);
   
    pJsonS  = cJSON_Print(jObject);
    cJSON_Delete(jObject);

    return pJsonS;
}

static JSON_ENGINE g_jSonEngine[] = 
{
    {JSON_ENGINE_P2C,                   __player_TO_CTRL2Json,      __json2PLAYER_TO_CTRL,      __player_TO_CTRLBase64},
    {JSON_ENGINE_C2P,                   __ctrl_TO_PLAYER2Json,      __json2CTRL_TO_PLAYER,      __ctrl_TO_PLAYERBase64},
    {JSON_ENGINE_CFG_REQ,               __cfg_API_REQ2Json,         __json2CFG_API_REQ,         __cfg_API_REQBase64},
    {JSON_ENGINE_CFG_RSP,               __cfg_API_RSP2Json,         __json2CFG_API_RSP,         __cfg_API_RSPBase64 },
    {JSON_ENGINE_ASSISTANT_SYNC_RSP,    NULL,                       __json2Alarm_sync_RSP,      NULL},
    {JSON_ENGINE_ASSISTANT_NOTIFY,      __alarm_change_RSP2Json,    __json2Alarm_change_RSP,    NULL},
    {JSON_ENGINE_ASSISTANT_STATUS,      __alarm_Status_RSP2Json,    __json2Alarm_Status_RSP,    NULL},
    {JSON_ENGINE_ASSISTANT_RUNNING,     __alarm_Run_Event_RSP2Json, NULL,                       NULL},
    {JSON_ENGINE_WORKDAY_REQ,           __alarm_WorkData_RSP2Json,  __json2Alarm_WorkData_RSP,  NULL},
    {JSON_ENGINE_PING,                  __ping_MSG2Json,            __json2PING_MSG,            NULL},
    {JSON_ENGINE_OTA_REQ,               __ota_Notify_REQ2Json,      __json2OTA_Notify_REQ,      __ota_NotifyBase64},
    {JSON_ENGINE_OTA_RSP,               __ota_Status_RSP2Json,      __json2OTA_Status_RSP,      NULL},
    {JSON_ENGINE_LOG_CFG_CMD,           __logCfg_RSP2Json,          __json2LogCfg_RSP,          NULL},
    {JSON_WIFI_STATUS_NOTIFY,           __wifiStatus_RSP2Json,      __json2WifiStatus_RSP,      NULL},
    {JSON_MCU_GUIDE_TEST_CMD,           NULL,			    __json2McuGuideCmd_RSP,     NULL},
    {JSON_MCU_MATRIX_TEST_CMD,		NULL,			    __json2McuMatrixCmd_RSP,	NULL},
    {JSON_MCU_TEST_GET_VER_CMD,		__mcuVersion_RSP2Json,	    NULL,       		NULL},
};

void* Json2Struct(const char* pJsonStr, JSON_ENGINE_TYPE type, int enBase64, int* pErr)
{
    if(pJsonStr == NULL || pErr == NULL)
    {
        if(pErr)
        {
            *pErr = -ERR_INPUT_PARAMS;
        }
        return NULL;
    }

    if(type < 0 || type >= JSON_ENGINE_MAX)
    {
        *pErr = -ERR_INPUT_PARAMS;
        return NULL;
    }

    *pErr = 0;

    //LOG_EX(LOG_Debug, "Json:\n%s\n", pJsonStr);
    
    if(g_jSonEngine[type].j2sCb)
    {
        void *pStruct = g_jSonEngine[type].j2sCb(pJsonStr);

        if(enBase64 && g_jSonEngine[type].base64Cb)
        {
            g_jSonEngine[type].base64Cb(pStruct, FALSE);
        }

        return (pStruct);
    }
    else
    {
        return (NULL);
    }
}

const char* Struct2Json(void* pStruct, JSON_ENGINE_TYPE type, int enBase64, int* pErr)
{    
    if(pStruct == NULL || pErr == NULL)
    {
        if(pErr)
        {
            *pErr = -ERR_INPUT_PARAMS;
        }
        return NULL;
    }

    if(type < 0 || type >= JSON_ENGINE_MAX)
    {
        *pErr = -ERR_INPUT_PARAMS;
        return NULL;
    }

    *pErr = 0;

    if(enBase64 && g_jSonEngine[type].base64Cb)
    {
        g_jSonEngine[type].base64Cb(pStruct, TRUE);
    }
    
    if(g_jSonEngine[type].s2jCb)
    {
        const char *pJsongStr = g_jSonEngine[type].s2jCb(pStruct);

        //LOG_EX(LOG_Debug, "Json: \n%s\n", pJsongStr);
        return (pJsongStr);
    }
    else
    {
        return NULL;
    }
}
