#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>
/*获取设备信息*/

/*获取设备信息*/
void getDeviceInfo(Webs *wp){
    uint16_t    wRet = LIBIPMI_E_SUCCESS;
    GetDevIDRes_T   DeviceID;
    struct ifreq ifreq;
    int sock;
    struct sockaddr_in *myaddr;
    IPMI20_UDS_SESSION_T    UDSSession;

    char BuildTime[30] = {0};
    char FwVersion[10] = {0};
    char MacAddr[18] = {0};
    char IpAddr[16] = {0};

    //Create session
    LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);

    //get build time
    sprintf(BuildTime, "%s %s", __DATE__, __TIME__);

    //get firmware version
    wRet = IPMICMD_GetDeviceID( &UDSSession, &DeviceID, DEFAULT_TIMEOUT);
    if (wRet == LIBIPMI_E_SUCCESS)
    {
        sprintf(FwVersion, "%d.%d", DeviceID.FirmwareRevision1, DeviceID.FirmwareRevision2);
    }

    //Close session
    LIBIPMI_CloseSession(&UDSSession );

    //get mac adn ip address
    if((sock=socket(AF_INET,SOCK_STREAM,0))<0)
    {
        printf("Get mac address socket fail!\n");
    }
    else
    {
        strcpy(ifreq.ifr_name,"eth0");

        //MAC
        if(ioctl(sock,SIOCGIFHWADDR,&ifreq)<0)
        {
            printf("Get mac address ioctl fail!\n");
        }
        else
        {
            sprintf(MacAddr, "%02x:%02x:%02x:%02x:%02x:%02x",
                    (unsigned char)ifreq.ifr_hwaddr.sa_data[0],
                    (unsigned char)ifreq.ifr_hwaddr.sa_data[1],
                    (unsigned char)ifreq.ifr_hwaddr.sa_data[2],
                    (unsigned char)ifreq.ifr_hwaddr.sa_data[3],
                    (unsigned char)ifreq.ifr_hwaddr.sa_data[4],
                    (unsigned char)ifreq.ifr_hwaddr.sa_data[5]);
        }

        //IP
        if(ioctl(sock, SIOCGIFADDR, &ifreq) < 0)
        {
            printf("Get ip address ioctl fail!\n");
        }
        else
        {
            myaddr = (struct sockaddr_in *)&(ifreq.ifr_addr);
            strcpy(IpAddr, inet_ntoa(myaddr->sin_addr));   
        }
    }
    close(sock);    
    
    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);

}


/*获取系统信息*/
void getSysInfo(Webs *wp){
    int wRet;
    SysInfo_T sysInfo;
    IPMI20_UDS_SESSION_T    UDSSession;


    sysInfo.title = walloc(MAX_TITLE_LEN);
    if(sysInfo.title == NULL)
    {
        printf("---> title malloc error!\n");
        goto sys_info_end;
    }
    else
        memset(sysInfo.title, 0, MAX_TITLE_LEN);
    
    sysInfo.text = walloc(MAX_TEXT_LEN);
    if(sysInfo.text == NULL)
    {
        printf("---> text malloc error!\n");
        goto sys_info_end;
    }
    else
        memset(sysInfo.text, 0, MAX_TEXT_LEN);

    //Create session
    LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);
    
    LIBIPMI_HL_GetSysInfo(&UDSSession, &sysInfo, DEFAULT_TIMEOUT);

    //Close session
    LIBIPMI_CloseSession(&UDSSession );

    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, "title", sysInfo.title);
    cJSON_AddStringToObject(data, "text", sysInfo.text);

    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);

sys_info_end: 
    if(sysInfo.title)
        wfree(sysInfo.title);
    if(sysInfo.text)
        wfree(sysInfo.text);
    if(pStr)
        wfree(pStr);
    if(root)
        cJSON_Delete(root);
}


/*获取刀片信息*/
void getCardInfo(Webs *wp){

}

void getSensorInfo(Webs *wp){
    int         wRet;
    int         nSensors = 0;
    uint8_t     SensorNumber;
    char        SensorName[MAX_ID_STR_LEN];
    uint8_t     OwnerID;
    uint8_t     OwnerLUN;
    uint8_t     SensorType;
    uint8_t     SensorUnit1;
    uint8_t     SensorUnit2;
    uint8_t     SensorUnit3;
    int         SensorReading;
    uint8_t     RawReading;
    uint16_t    SensorState;
    uint8_t     DiscreteState;
    int         LowNRThresh;
    int         LowCTThresh;
    int         LowNCThresh;
    int         HighNCThresh;
    int         HighCTThresh;
    int         HighNRThresh;
    int         SensorAccessibleFlags;
    struct sensor_data *pSensorBuff = NULL;
    char reading[10], lownr[10],lowct[10],lownc[10],highnc[10],highct[10],highnr[10];
    unsigned char *pStartBuff = NULL;
    IPMI20_UDS_SESSION_T    UDSSession;
    
    //Create session
    LIBIPMI_CreateSession(&UDSSession, 10000);
   
    /* Get number of SEL records in the system at this time */
    wRet = LIBIPMI_HL_GetSensorCount(&UDSSession,&nSensors,DEFAULT_TIMEOUT);
    if( wRet != 0 )
    {
        printf("Error getting num of sensors\n");
        goto error_out;
    }
    else
    {
        //printf("success getting num of sensors: %d\n",nSensors);  //this is all sensor count
        /* Now get all sensors records */
        if(!nSensors)
        {
            /* There are no sensors present at this time */
            goto error_out;
        }

        /* Allocate the buffer to hold sensors records */
        pSensorBuff = (struct sensor_data *) walloc(nSensors * sizeof(struct sensor_data));
        if(pSensorBuff == NULL)
        {
            printf("Error alloc memory!\n");
            goto error_out;
        }
        memset(pSensorBuff, 0, nSensors * sizeof(struct sensor_data));
        pStartBuff = (unsigned char *)pSensorBuff;

        printf("sensorcount = %d\n", nSensors);
        nSensors -= 1;  //remove first sdr
        wRet = LIBIPMI_HL_GetAllSensorReadings(&UDSSession,pSensorBuff, nSensors,DEFAULT_TIMEOUT);
        
        //Close session
        LIBIPMI_CloseSession(&UDSSession );

        if(wRet != 0)
        {
            printf("Error reading All Sensors\n");
            goto error_out;
        }
        else
        {

            char *pStr;
            int code = 200;
            cJSON * root =  cJSON_CreateObject();
            cJSON  *pJsonArry,*pJsonsub;
            pJsonArry=cJSON_CreateArray();   /*创建数组*/
            logmsg(2, "-----------------------sensor----------------------");
            while(nSensors)
            {
                sprintf(reading, "%.3f", pSensorBuff->sensor_reading);
                sprintf(lownr, "%.3f", pSensorBuff->low_non_recov_thresh);
                sprintf(lowct, "%.3f", pSensorBuff->low_crit_thresh);
                sprintf(lownc, "%.3f", pSensorBuff->low_non_crit_thresh);
                sprintf(highnc, "%.3f", pSensorBuff->high_non_crit_thresh);
                sprintf(highct, "%.3f", pSensorBuff->high_crit_thresh);
                sprintf(highnr, "%.3f", pSensorBuff->high_non_recov_thresh);

                cJSON_AddItemToArray(pJsonArry,pJsonsub=cJSON_CreateObject()); /* 给创建的数组增加对对象*/
                cJSON_AddNumberToObject(pJsonsub, "sensorNum", pSensorBuff->sensor_num); 
                cJSON_AddStringToObject(pJsonsub, "sensorName", pSensorBuff->sensor_name);

                //cJSON_AddNumberToObject(pJsonsub, "ownerId",    pSensorBuff->owner_id);
                //cJSON_AddNumberToObject(pJsonsub, "ownerNun",   pSensorBuff->owner_lun);
                //cJSON_AddNumberToObject(pJsonsub, "sensorType", pSensorBuff->sensor_type);
                // cJSON_AddNumberToObject(pJsonsub, "sensorUnits1", pSensorBuff->sensor_units[0]);
                // cJSON_AddNumberToObject(pJsonsub, "sensorUnits2", pSensorBuff->sensor_units[1]);
                // cJSON_AddNumberToObject(pJsonsub, "sensorUnits3", pSensorBuff->sensor_units[2]);

                //cJSON_AddNumberToObject(pJsonsub, "rawReading", pSensorBuff->raw_reading);
                //cJSON_AddNumberToObject(pJsonsub, "sensorState", pSensorBuff->sensor_state);
                //cJSON_AddNumberToObject(pJsonsub, "discreteState", pSensorBuff->discrete_state);
                //cJSON_AddNumberToObject(pJsonsub, "SensorAccessibleFlags", pSensorBuff->SensorAccessibleFlags); 
                cJSON_AddStringToObject(pJsonsub, "reading", reading);      /* 给对象增加内容 */    
                cJSON_AddStringToObject(pJsonsub, "lownr", lownr);                                        
                cJSON_AddStringToObject(pJsonsub, "lowct", lowct);   
                cJSON_AddStringToObject(pJsonsub, "lownc", lownc);                                                       
                cJSON_AddStringToObject(pJsonsub, "highnc", highnc);                 
                cJSON_AddStringToObject(pJsonsub, "highct", highct);   
                cJSON_AddStringToObject(pJsonsub, "highnr", highnr);  

                switch(pSensorBuff->sensor_units[1])    //sensorUinits2
                {
                case 0: cJSON_AddStringToObject(pJsonsub, "unit", "unspecified"); break;                    
                case 1: cJSON_AddStringToObject(pJsonsub, "unit", "degree C"); break;
                case 2: cJSON_AddStringToObject(pJsonsub, "unit", "degree F"); break;
                case 3: cJSON_AddStringToObject(pJsonsub, "unit", "degree K"); break;
                case 4: cJSON_AddStringToObject(pJsonsub, "unit", "Volts"); break;
                case 5: cJSON_AddStringToObject(pJsonsub, "unit", "Amps"); break;
                case 6: cJSON_AddStringToObject(pJsonsub, "unit", "Watts"); break;
                case 18: cJSON_AddStringToObject(pJsonsub, "unit", "RPM"); break;
                default: cJSON_AddStringToObject(pJsonsub, "unit", "unknown"); break;
                }

                switch(pSensorBuff->sensor_state)
                {
                case 0x1:  cJSON_AddStringToObject(pJsonsub, "state", "ok"); break;
                case 0x2:  cJSON_AddStringToObject(pJsonsub, "state", "Upper Non-Critical"); break;    
                case 0x4:  cJSON_AddStringToObject(pJsonsub, "state", "Upper Critical Threshold"); break;    
                case 0x8:  cJSON_AddStringToObject(pJsonsub, "state", "Lower Non-Critical"); break;    
                case 0x10:  cJSON_AddStringToObject(pJsonsub, "state", "Lower Critical"); break;    
                case 0x20:  cJSON_AddStringToObject(pJsonsub, "state", "Access failed"); break;    
                case 0x40:  cJSON_AddStringToObject(pJsonsub, "state", "Upper Non-Recoverable"); break;    
                case 0x80:  cJSON_AddStringToObject(pJsonsub, "state", "Lower Non-Recoverable"); break;    
                default:  cJSON_AddNumberToObject(pJsonsub, "state", pSensorBuff->sensor_state); break;      
                }
         
                pSensorBuff++;
                nSensors--;
            }

            // cJSON_AddItemToObject(root, "data", pJsonArry);//根节点下添加
            // cJSON_AddItemToObject(root, "msg", cJSON_CreateString(""));
            // cJSON_AddItemToObject(root, "code", cJSON_CreateString("200"));
            // pStr = cJSON_Print(pJsonArry);
            cJSON_AddItemToObject(root, "data", pJsonArry);
            pStr = cJSON_PrintUnformatted(root);
            // printf("---> pStr %d: %s\n", strlen(pStr), pStr);

            websSetStatus(wp, 200);
            websWriteHeaders(wp, -1, 0);
            websWriteEndHeaders(wp); 
            //websWrite(wp, "[");
            websWrite(wp, pStr);
            //websWrite(wp, "]");
            //websFlush(wp, 0);
            websDone(wp);

            if(root)
                cJSON_Delete(root);
            if(pStr)
                wfree(pStr);          
        }
    }
    //TODO: lusa
error_out:
    if(pStartBuff)
        free(pStartBuff);
    
}

void buy(Webs *wp)
{
    char    *name, *age;
    name = websGetVar(wp, "name", NULL);
    age = websGetVar(wp, "age", NULL);
    logmsg(2, "name value is : %s", name );
     logmsg(2, "age value is : %s", age );
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp);
   
    websWrite(wp, "Name %s", name);
    websWrite(wp, "age %s", age); 
    websFlush(wp, 0);
    websDone(wp);

    if(name)
        wfree(name);
    if(age)
        wfree(age);
}



// /*
//     Implement /action/actionTest. Parse the form variables: name, address and echo back.
//  */
// void actionTest(Webs *wp)
// {

//     printf("sid value is >>>>>>>>>>>>>: %d<<<<<<<<<<<\n", wp->sid);
//     IPMI20_UDS_SESSION_T    UDSSession;
//     GetDevIDRes_T   DeviceID;

//     //Create session
//     printf("actionTest!\n");
//     LIBIPMI_CreateSession(&UDSSession, 10);
//     IPMICMD_GetDeviceID( &UDSSession, &DeviceID, DEFAULT_TIMEOUT);

//     printf("sid value is >>>>>1>>>>>>>>: %d<<<<<<<\n", wp->sid);


//     char *pStr;

//     char *testStr;
//     testStr = malloc(500); 
//     //sprintf(testStr, "{data: {\"Version\": \"%s\", \"MAC\": \"%s\", \"IP\": \"%s\"}, \"msg\":\"\"}", FwVersion, MacAddr, IpAddr);

//     sprintf(testStr, "{\"data\": {\"buildTime\":\"%s\",\"fwVersion\":\"%s\",\"macAddr\":\"%s\",\"ipAddr\":\"%s\"},\"msg\":\"\",\"code\": %d}", \
//         BuildTime, FwVersion, MacAddr, IpAddr, 200);


//     //sprintf(testStr, "jimbo and lusa are very confused, please git me some tips, my god!");

//      pStr = testStr;


//     char name[] = "jimbo";
//     char address[] = "shanghai";
//     printf("name: %s, address: %s\n", name, address);
//     websSetStatus(wp, 200);
//     websWriteHeaders(wp, -1, 0);
//     websWriteEndHeaders(wp);
//     websWrite(wp,  testStr);
//     websFlush(wp, 0);
//     websDone(wp);
//     // LIBIPMI_CloseSession(&UDSSession );
// }


void actionTest(Webs *wp)
{
    IPMI20_UDS_SESSION_T    UDSSession;
    GetDevIDRes_T   DeviceID;
    char BuildTime[30] = "2020-3-17";
    char FwVersion[10] = "5.555";
    char MacAddr[18] = "22.22.22.22.22.22";
    char IpAddr[16] = "192.168.255.255";

    printf("---> actionTest\n");

    // //Create session

    // LIBIPMI_CreateSession(&UDSSession, 10);
    // IPMICMD_GetDeviceID( &UDSSession, &DeviceID, DEFAULT_TIMEOUT);
    // LIBIPMI_CloseSession(&UDSSession );

    int client_sock;
    struct sockaddr_un serv_addr;
    uint8_t buf[100] = {0,0, 0, 0, 0x44, 0x3a, 0, 0xc8, 0, 0xd, 0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x25,
         0, 0, 0, 0x25, 0, 0, 0, 0, 0, 0, 0, 0x14, 0 };
    
    int len;
    /* Open the socket */
    client_sock = socket(AF_UNIX, SOCK_STREAM, 0);
    if(client_sock == -1)
    {
        printf("LIBIPMI_UDS_SESSION.C: Unable to create socket \n");
    }

    /*Connect the client to server*/
    memset ((char *) &serv_addr, 0, sizeof (serv_addr));
    serv_addr.sun_family = AF_UNIX;
    strcpy(serv_addr.sun_path,UDS_SOCKET_PATH);

     if ( connect (client_sock, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
    {
        printf("LIBIPMI_UDS_SESSION.C: Unable to connect to Server:\n");
    }

    send (client_sock,buf,0x3a, MSG_NOSIGNAL);

    len = recv(client_sock,buf,100,0);
    int i;
    printf("Dashboard Rec %d: ", i);
    for(i=0;i<len;i++)
        printf("%#x ", buf[i]);
    printf("\n");
    close(client_sock);





    char *pStr;

    char *testStr;
    testStr = walloc(500); 
    //sprintf(testStr, "{data: {\"Version\": \"%s\", \"MAC\": \"%s\", \"IP\": \"%s\"}, \"msg\":\"\"}", FwVersion, MacAddr, IpAddr);

    sprintf(testStr, "{\n\t\"data\": {\n\t\t\"buildTime\":\"%s\",\n\t\t\"fwVersion\":\"%s\",\n\t\t\"macAddr\":\"%s\",\n\t\t\"ipAddr\":\"%s\"\n\t},\n\t\"msg\":\"\",\n\t\"code\": %d\n}", \
        BuildTime, FwVersion, MacAddr, IpAddr, 200);
     pStr = testStr;

    // cJSON * root =  cJSON_CreateObject();
    // cJSON * data =  cJSON_CreateObject();
    printf("log1\n");
    // cJSON_AddItemToObject(root, "data", data);//根节点下添加
    // cJSON_AddItemToObject(root, "msg", cJSON_CreateString(""));
    // cJSON_AddItemToObject(root, "code", cJSON_CreateString("200"));
    // cJSON_AddStringToObject(data, "buildTime", BuildTime);
    // cJSON_AddStringToObject(data, "fwVersion", FwVersion);
    // cJSON_AddStringToObject(data, "macAddr", MacAddr);
    // cJSON_AddStringToObject(data, "ipAddr", IpAddr);
    // pStr = cJSON_Print(root);     //include malloc
 //    cJSON_AddItemToObject(root, "data", data);//根节点下添加
 //    cJSON_AddStringToObject(root, "msg", NULL);
 //    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);
 //    pStr = cJSON_Print(root);     //include malloc
    
    printf("%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);

    // cJSON_Delete(root);
    // cJSON_Delete(data);

    
}