#include    "goahead.h"
#include    "libipmi_IPM.h"
#include    "com_IPMIDefs.h"
#include    "ResultUtils.h"
#include    "cJSON.h"
#include    "libipmi_storlead_OEM.h"
#include    "libsensor.h"
#include    <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>

static uint8_t progress = 0;
/* 进入固件更新模式
* 杀死所有其它进程
*/
void prepareDevice(Webs *wp)
{
    printf("Update Firmware: Prepare Device...\n");
    uint8_t cmd[50] = {0};
    progress = 0;
    //kill bmc_app
    sprintf(cmd, "killall -9 bmc_app"); 
    system(cmd);
    char *pStr;
    cJSON * root =  cJSON_CreateObject();
    cJSON * data =  cJSON_CreateObject();
    cJSON_AddItemToObject(root, "data", data);//根节点下添加
    cJSON_AddStringToObject(root, "msg", "");
    cJSON_AddNumberToObject(root, "code", 200);
    pStr = cJSON_PrintUnformatted(root);
    printf("---> cJSON Str:\n%s\n", pStr);
   
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp); 
    websWrite(wp,"%s", pStr);
    websFlush(wp, 0);
    // websDone(wp);

    if(pStr)
        wfree(pStr);
    if(root)
        cJSON_Delete(root);
    
    websDone(wp);
    printf("Update Firmware: Prepare Device Ok.\n");
}

/* 
    接收上传的固件
*/

void uploadFirmware(Webs *wp)
{
    WebsKey         *s;
    WebsUpload      *up;
    char            *upfile;
    if (scaselessmatch(wp->method, "POST")) {
        for (s = hashFirst(wp->files); s; s = hashNext(wp->files, s)) {
            up = s->content.value.symbol;
            upfile = sfmt("%s/tmp/%s", websGetDocuments(), "gd32450i-eval.uImage");
            printf("<<<<<<<<<<<%s>>>>>>>>>>\n", upfile);
            if (rename(up->filename, upfile) < 0) {
                error("Cannot rename uploaded file: %s to %s, errno %d", up->filename, upfile, errno);
            }
            wfree(upfile);
        }
      
    }
    char *pStr;
    cJSON * root =  cJSON_CreateObject();
    cJSON * data =  cJSON_CreateObject();
    cJSON_AddItemToObject(root, "data", data);//根节点下添加
    cJSON_AddStringToObject(root, "msg", "");
    cJSON_AddNumberToObject(root, "code", 200);
    pStr = cJSON_PrintUnformatted(root);
    printf("---> cJSON Str:\n%s\n", pStr);
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp); 
    websWrite(wp,"%s", pStr);
    websFlush(wp, 0);
    // websDone(wp);

    if(pStr)
        wfree(pStr);
    if(root)
        cJSON_Delete(root);
    
    websDone(wp);
}

/*
    开始执行固件更新
    擦除Flash，写Flash
*/
void updateFlash(Webs *wp)
{
    printf("Update Firmware: Update Flash...\n");
    //TODO: 
    uint8_t cmd[50] = {0};
    progress = 0;

    //Call updateFW_app
    sprintf(cmd, "/usr/bin/updateFW_app &"); 
    system(cmd);
    char *pStr;
    cJSON * root =  cJSON_CreateObject();
    cJSON * data =  cJSON_CreateObject();
    cJSON_AddItemToObject(root, "data", data);//根节点下添加
    cJSON_AddStringToObject(root, "msg", "");
    cJSON_AddNumberToObject(root, "code", 200);
    pStr = cJSON_PrintUnformatted(root);
    printf("---> cJSON Str:\n%s\n", pStr);
   
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp); 
    websWrite(wp,"%s", pStr);
    websFlush(wp, 0);
    // websDone(wp);

    if(pStr)
        wfree(pStr);
    if(root)
        cJSON_Delete(root);
    
    websDone(wp);
    printf("Update Firmware: Prepare Device Ok.\n");
}


/*
    获取Flash更新的进度
    返回 Flash更新的百分比。
*/
void getUpdateProgress(Webs *wp)
{
    uint8_t progressStr[10] = {0};
    FILE *fp;

    //TODO:
    fp = fopen("/var/www/goahead/tmp/UpdateProgress.log", "r");
    if(NULL == fp)
    {
        printf("Open UpdateProgress.log failed!\n");
        websError(wp, 200, "Open UpdateProgress.log failed！");
        return;
    }

    if(NULL == fgets(progressStr, 10, fp))
    {
        printf("Read UpdateProgress.log failed!\n");
        websError(wp, 200, "Read UpdateProgress.log failed！");
        fclose(fp);
        return;
    }
    
    printf("Update Firmware: %s\n", progressStr);


    char *pStr;
    cJSON * root =  cJSON_CreateObject();
    cJSON_AddStringToObject(root, "progress", progressStr);
    cJSON_AddNumberToObject(root, "code", 200);
    

    pStr = cJSON_PrintUnformatted(root);

    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    //websWriteHeader(wp, "getUpdateProgress");
    websWriteEndHeaders(wp);
    websWrite(wp, "%s", pStr);
    websFlush(wp, 0);
    websDone(wp);

    if(pStr)
        wfree(pStr);
    if(root)
        cJSON_Delete(root);
}


void resetBmc(Webs *wp)
{
#define DEV_NAME "/dev/platform"
#define IOCTL_MAGIC 'x' 
#define MAJOR_PLATFORM  100
#define GENERATE_CMD(__MAGIC__, __MAJOR__, __CMD__) \
    ((0x3<<30) | (__MAJOR__<<16) | (__MAGIC__<<8) | __CMD__)
#define RESET_MCU                       GENERATE_CMD(IOCTL_MAGIC, MAJOR_PLATFORM, 2)

    printf("Update Firmware: Reset BMC...\n");
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    //websWriteHeader(wp, "resetBmc");
    websWriteEndHeaders(wp);
    //websWrite(wp, "%s", pStr);
    //websFlush(wp, 0);
    websDone(wp);

    usleep(1000);  //wait previous code
    int fd = open(DEV_NAME, O_RDWR);
    if(fd == -1)
    {
        printf("Open %s failed!\n", DEV_NAME);
    }

    ioctl(fd, RESET_MCU, NULL);    
    close(fd);
}




// void getDeviceInfo(Webs *wp){
   
//     char *pStr;
//     cJSON * root =  cJSON_CreateObject();
//     cJSON * data =  cJSON_CreateObject();
//     cJSON_AddItemToObject(root, "data", data);//根节点下添加
//     cJSON_AddStringToObject(root, "msg", "");
//     cJSON_AddNumberToObject(root, "code", 200);
//     cJSON_AddStringToObject(data, "buildTime", BuildTime);
//     cJSON_AddStringToObject(data, "fwVersion", FwVersion);
//     cJSON_AddStringToObject(data, "macAddr", MacAddr);
//     cJSON_AddStringToObject(data, "ipAddr", IpAddr);
//     cJSON_AddStringToObject(data, "netMode", "static");

//     pStr = cJSON_PrintUnformatted(root);

//     printf("---> cJSON Str:\n%s\n", pStr);
//     websSetStatus(wp, 200);
//     websWriteHeaders(wp, -1, 0);
//     websWriteEndHeaders(wp);
//     websWrite(wp, "%s", pStr);
//     websFlush(wp, 0);
//     websDone(wp);

//     if(pStr)
//         wfree(pStr);
//     if(root)
//         cJSON_Delete(root);

// }
