#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    "com_BMCCfg.h"
#include    <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
/*
    废弃机箱管理是能按钮。由BMC程序里的g_BMCInfo.isChMC代替。ChMC默认就支持机箱管理，IPMC默认不支持。
    gChassisManageEn、setBladeManage、getBladeManage保留但是用不到。
*/
uint8_t gIPMBAddr[BLADE_NUMBERS] = {0x20, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, 0x90, 0x92, 0x94};
uint8_t gChassisManageEn = 0;
/*获取设备信息*/
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;
    uint8_t target_addr;

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

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

    wp->index = TEST_INDEX;
    target_addr = gIPMBAddr[wp->index];
    if(target_addr == 0x20)
    {
        //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);
        }
        //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);    
    }
    else
    {
        //get build time
        sprintf(BuildTime, "--");
        sprintf(MacAddr, "--");
        sprintf(IpAddr, "--");   
        //get firmware version
        wRet = IPMC_GetDeviceID( &UDSSession, target_addr, &DeviceID, DEFAULT_TIMEOUT);
        if (wRet == LIBIPMI_E_SUCCESS)
        {
            sprintf(FwVersion, "%d.%d", DeviceID.FirmwareRevision1, DeviceID.FirmwareRevision2);
        }
    }

    //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, "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);
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp);
    websWrite(wp, "%s", pStr);
    websFlush(wp, 0);
    websDone(wp);

    printf("---> cJSON Str:\n%s\n", pStr);
    if(pStr)
        wfree(pStr);
    if(root)
        cJSON_Delete(root);

}


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

    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);
    
    wp->index = TEST_INDEX;
    target_addr = gIPMBAddr[wp->index];
    if(target_addr == 0x20)
    {
        LIBIPMI_HL_GetSysInfo(&UDSSession, &sysInfo, DEFAULT_TIMEOUT);
    }
    else
    {
        IPMC_GetSysInfo(&UDSSession, target_addr, &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);
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp); 
    websWrite(wp,"%s", pStr);
    websFlush(wp, 0);
    websDone(wp);
    printf("---> cJSON Str:\n%s\n", pStr);

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];
    char maxReading[10], minReading[10];
    unsigned char *pStartBuff = NULL;
    IPMI20_UDS_SESSION_T    UDSSession;
    uint8_t target_addr;
    
    //Create session
    LIBIPMI_CreateSession(&UDSSession, 10000);
     
    wp->index = TEST_INDEX;
    target_addr = gIPMBAddr[wp->index];
    if(target_addr == 0x20)
    {
        /* 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);
        }
    }
    else
    {
        /* Get number of SEL records in the system at this time */
        wRet = IPMC_GetSensorCount(&UDSSession, target_addr, &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;

            nSensors -= 1;  //remove first sdr
            //printf("sensorcount = %d\n", nSensors);
            wRet = IPMC_GetAllSensorReadings(&UDSSession,target_addr, 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();   /*创建数组*/
        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);
            sprintf(maxReading, "%.3f", pSensorBuff->max_reading);
            sprintf(minReading, "%.3f", pSensorBuff->min_reading);

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

            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);  
            cJSON_AddStringToObject(pJsonsub, "maxReading", maxReading);  
            cJSON_AddStringToObject(pJsonsub, "minReading", minReading);  

            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"); cJSON_AddStringToObject(pJsonsub, "status", "1"); break;
            case 0x2:  cJSON_AddStringToObject(pJsonsub, "state", "Upper Non-Critical"); cJSON_AddStringToObject(pJsonsub, "status", "2"); break;    
            case 0x4:  cJSON_AddStringToObject(pJsonsub, "state", "Upper Critical Threshold");cJSON_AddStringToObject(pJsonsub, "status", "3"); break;    
            case 0x8:  cJSON_AddStringToObject(pJsonsub, "state", "Lower Non-Critical");cJSON_AddStringToObject(pJsonsub, "status", "2"); break;    
            case 0x10:  cJSON_AddStringToObject(pJsonsub, "state", "Lower Critical");cJSON_AddStringToObject(pJsonsub, "status", "3"); break;    
            case 0x20:  cJSON_AddStringToObject(pJsonsub, "state", "Access failed");cJSON_AddStringToObject(pJsonsub, "status", "3"); break;    
            case 0x40:  cJSON_AddStringToObject(pJsonsub, "state", "Upper Non-Recoverable");cJSON_AddStringToObject(pJsonsub, "status", "3"); break;    
            case 0x80:  cJSON_AddStringToObject(pJsonsub, "state", "Lower Non-Recoverable");cJSON_AddStringToObject(pJsonsub, "status", "3"); break;    
            default:  cJSON_AddNumberToObject(pJsonsub, "state", pSensorBuff->sensor_state);cJSON_AddStringToObject(pJsonsub, "status", "3"); break;      
            }
     
            pSensorBuff++;
            nSensors--;
        }

       
        cJSON_AddItemToObject(root, "data", pJsonArry);
        pStr = cJSON_PrintUnformatted(root);

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

        if(root)
            cJSON_Delete(root);
        if(pStr)
            wfree(pStr);          
    }
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);
}




void actionTest(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);

    
}

void getAllBladeInfo(Webs *wp){
    uint16_t    wRet = LIBIPMI_E_SUCCESS;
    
    IPMI20_UDS_SESSION_T    UDSSession;
    BladeStatus_T   *pBladeStatus = walloc(BLADE_NUMBERS*sizeof(BladeStatus_T));
    //Create session
    LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);

    wRet = LIBIPMI_HL_GetAllBladeStatus(&UDSSession, gChassisManageEn, pBladeStatus, DEFAULT_TIMEOUT);
    if(wRet != 0)
    {
        printf("Get Blade status error!\n");
        websError(wp, 404, "Get Blade status error!");
        wfree(pBladeStatus);
        return;
    }
    //Close session
    LIBIPMI_CloseSession(&UDSSession );
    
    char *pStr;
    cJSON * root =  cJSON_CreateObject();
    cJSON  *pJsonArry,*pJsonsub;
    pJsonArry=cJSON_CreateArray();   /*创建数组*/
    cJSON_AddItemToObject(root, "data", pJsonArry);//根节点下添加
    cJSON_AddStringToObject(root, "msg", "");
    cJSON_AddNumberToObject(root, "code", 200);

    int i;
    for(i=0;i<BLADE_NUMBERS;i++)
    {
        cJSON_AddItemToArray(pJsonArry,pJsonsub=cJSON_CreateObject()); /* 给创建的数组增加对对象*/
        cJSON_AddNumberToObject(pJsonsub, "status", pBladeStatus[i].healthStatus); //0：灰色， 1： 绿色 2：红色
        cJSON_AddNumberToObject(pJsonsub, "slot", pBladeStatus[i].slotID); 
        cJSON_AddNumberToObject(pJsonsub, "power", pBladeStatus[i].pwrStatus); 
        cJSON_AddStringToObject(pJsonsub, "name", pBladeStatus[i].bladeName); 
    }
  
    pStr = cJSON_PrintUnformatted(root);

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

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

}

//废弃
void setBladeManage(Webs *wp){
    char *strEnable = websGetVar(wp, "enable", NULL);

    gChassisManageEn = atoi(strEnable);
    
    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);
 
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp);
    websWrite(wp, "%s", pStr);
    websFlush(wp, 0);
    websDone(wp);
    printf("---> cJSON Str:\n%s\n", pStr);

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

}

//废弃
void getBladeManage(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_AddNumberToObject(data, "isEnable", gChassisManageEn);  //机箱管理功能是否已经打开    
    
    pStr = cJSON_PrintUnformatted(root);

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

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

}


void getChassisInfo(Webs *wp){
    uint16_t    wRet = LIBIPMI_E_SUCCESS;
    IPMI20_UDS_SESSION_T    UDSSession;
    OemChassisInfo_T ChassisInfo;

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

    wRet = LIBIPMI_HL_GetChassisInfo(&UDSSession, &ChassisInfo, DEFAULT_TIMEOUT);
    if(wRet != 0)
    {
        websError(wp, 404, "Get Chassis Info Error!");
        LIBIPMI_CloseSession(&UDSSession );
        return;
    }

    //Close session
    LIBIPMI_CloseSession(&UDSSession );

    if(ChassisInfo.isChMC)
    {
        if(ChassisInfo.curIndex < BLADE_NUMBERS)
        {
            gIPMBAddr[ChassisInfo.curIndex] = 0x20;
        }
        else
        {
            printf("\n\n\nWarning: Invalid curIndex %d\n\n\n", ChassisInfo.curIndex);
        }
    }
    else
    {
        gChassisManageEn = 0;
    }


    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_AddNumberToObject(data, "slotNum", ChassisInfo.slotNum);    //机箱内一共有多少个槽位
    cJSON_AddNumberToObject(data, "supportManage", ChassisInfo.isChMC); //是否支持机箱管理功能。 0：不支持， 1：支持
    cJSON_AddNumberToObject(data, "ManageEn", gChassisManageEn);   //是否打开机箱管理功能。0：关闭， 1：打开
    cJSON_AddNumberToObject(data, "curIndex", ChassisInfo.curIndex);   //当前刀片插在第几个槽位。
    
    pStr = cJSON_PrintUnformatted(root);
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp);
    websWrite(wp, "%s", pStr);
    websFlush(wp, 0);
    websDone(wp);
    printf("---> cJSON Str:\n%s\n", pStr);

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

}