#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 "sel.h"
#include "libipmi_StorDevice.h"

void Web_ClearSEL(Webs *wp)
{
    int wRet = 0;

    IPMI20_UDS_SESSION_T    UDSSession;
    uint8_t target_addr;

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

    target_addr = gIPMBAddr[wp->index];
    if(target_addr == 0x20)
    {
        //get firmware version
        wRet = IPMICMD_ClearSEL( &UDSSession, DEFAULT_TIMEOUT);
    }
    else
    {
        wRet = IPMC_ClearSEL( &UDSSession, target_addr, DEFAULT_TIMEOUT);
    }

    //Close session
    LIBIPMI_CloseSession(&UDSSession );

    cJSON * root =  cJSON_CreateObject();
    cJSON * data =  cJSON_CreateObject();
    cJSON_AddItemToObject(root, "data", data);//根节点下添加
    cJSON_AddStringToObject(root, "msg", "");
    cJSON_AddNumberToObject(root, "code", 200);

    if(wRet != 0)
        cJSON_AddStringToObject(data, "status", "fail");
    else
        cJSON_AddStringToObject(data, "status", "success");

    char *pStr;
    pStr = cJSON_PrintUnformatted(root);

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

typedef struct {
    uint8_t sensor_number;
    uint8_t sensor_name[MAX_ID_STR_LEN+1];
} SensorNumNameTab_T;

void GetAllSELEntriesSorted(Webs *wp)
{
    int wRet = 0;
    unsigned short nEntries = 0;
    SELEventRecordWithSensorName_T *pSELBuff = NULL;
    int i,j;
    IPMI20_UDS_SESSION_T    UDSSession;
    uint8_t         target_addr;
    SensorNumNameTab_T senNumNameTab[MAX_SENSOR_NUMBERS];   //之前获取到的传感器名称暂存在这里，避免反复获取，浪费总线带宽。
    GetSELReq_T     GetSelReq;
    uint16_t        ReserveID;
    ReserveSELRes_T ReserveSelRes;
    uint16_t        RecID = 0;
    uint8_t         Res[50];
    SELEventRecord_T   SELEventData;
    uint8_t         sensorName[MAX_ID_STR_LEN+1];
    int             found_flag = 0;
    
    int code = 200;
    cJSON * root =  cJSON_CreateObject();
    cJSON  *pJsonArry,*pJsonsub;
    pJsonArry=cJSON_CreateArray();   /*创建数组*/
    

    //初始化传感器序号和名称对应表
    for(i=0;i<MAX_SENSOR_NUMBERS;i++)
    {
        senNumNameTab[i].sensor_number = 0xff;
        senNumNameTab[i].sensor_name[0] = '\0';
    }

    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp); 
    websWrite(wp, "{\"data\":[");

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

    target_addr = gIPMBAddr[wp->index];
    if(target_addr == 0x20)
    {
        /* Get number of SEL records in the system at this time */
        wRet = LIBIPMI_HL_GetNumOfSELEntries(&UDSSession, &nEntries, DEFAULT_TIMEOUT);
    }
    else
    {
        wRet = IPMC_GetNumOfSELEntries(&UDSSession, target_addr, &nEntries, DEFAULT_TIMEOUT);
    }

    if(wRet != 0)
    {
        printf("Error getting num of sel recods\n");
        goto error_out;
    }
    else
    {
        if(nEntries > MAX_SEL_RECORD)   nEntries = MAX_SEL_RECORD;  //最大只能显示这么多日志
        if(nEntries == 0)
        {
            cJSON_AddItemToObject(root, "data", pJsonArry);
            websWrite(wp, "]}");
            websFlush(wp, 0);
            websDone(wp);
            return;
        }

        /* Allocate the buffer to hold SEL entries */
        pSELBuff = (SELEventRecordWithSensorName_T *) walloc(nEntries * sizeof(SELEventRecordWithSensorName_T) + 10);   //margin 10
        if(pSELBuff == NULL)
        {
            goto error_out;
        }

        //printf("Reserve SEL, sel number %d\n", nEntries);
        //Reserve SEL
        if(target_addr == 0x20)
        {
            wRet = IPMICMD_ReserveSEL(&UDSSession, &ReserveSelRes, DEFAULT_TIMEOUT);
        }
        else
        {
            wRet = IPMC_ReserveSEL(&UDSSession, target_addr, &ReserveSelRes, DEFAULT_TIMEOUT);
        }

        if(wRet == 0)
        {
            ReserveID = ReserveSelRes.ReservationID;
            RecID = 0;  //first record
            for(i=0;i<nEntries;i++)
            {
                
                //获取日志
                GetSelReq.ReservationID = ReserveID;
                GetSelReq.RecID = RecID;
                GetSelReq.Offset = 0;
                GetSelReq.Size = 0xff;  //FFh means read entire record.
                if(target_addr == 0x20)
                {
                    wRet = IPMI_GetSELEntry(&UDSSession, &GetSelReq,  &SELEventData, &RecID, DEFAULT_TIMEOUT);
                }
                else
                {
                    wRet = IPMC_GetSELEntry(&UDSSession, target_addr, &GetSelReq,  &SELEventData, &RecID, DEFAULT_TIMEOUT);
                }
                if((wRet != 0))
                {
                    break;
                }
                // cJSON_AddItemToArray(pJsonArry,pJsonsub=cJSON_CreateObject()); /* 给创建的数组增加对对象*/
                // cJSON_AddNumberToObject(pJsonsub, "D1", SELEventData.hdr.ID);    //RecordID      -> D1
                // cJSON_AddNumberToObject(pJsonsub, "D2", SELEventData.hdr.Type);  //RecordType    -> D2
                // cJSON_AddNumberToObject(pJsonsub, "D3", SELEventData.hdr.TimeStamp); //TimeStamp -> D3
                // cJSON_AddNumberToObject(pJsonsub, "D4", SELEventData.GenID[0]);      //GenID1    -> D4
                // cJSON_AddNumberToObject(pJsonsub, "D5", SELEventData.GenID[1]);      //GenID2    -> D5
                // cJSON_AddNumberToObject(pJsonsub, "D6", SELEventData.EvMRev);        //EvmRev    -> D6
                // cJSON_AddNumberToObject(pJsonsub, "D7", SELEventData.SensorType);    //SensorType    -> D7
                // cJSON_AddNumberToObject(pJsonsub, "D8", SELEventData.EvtDirType);    //EventDirType  -> D8
                // cJSON_AddNumberToObject(pJsonsub, "D9", SELEventData.EvtData1);      //EventData1    -> D9
                // cJSON_AddNumberToObject(pJsonsub, "D10", SELEventData.EvtData2);     //EventData2    -> D10
                // cJSON_AddNumberToObject(pJsonsub, "D11", SELEventData.EvtData3);     //EventData3    -> D11

                if(i!=0)
                {
                    websWrite(wp, ",");
                }

                //printf("Get sel i = %d\n", i);
                if(SELEventData.hdr.Type == 0x02)
                {
                    //printf("system sel\n");
                    websWrite(wp, "{\"D1\":%d,\"D2\":%d,\"D3\":%d,\"D4\":%d,\"D5\":%d,\"D6\":%d,\"D7\":%d,\"D8\":%d,\"D9\":%d,\"D10\":%d,\"D11\":%d,",
                        SELEventData.hdr.ID, SELEventData.hdr.Type, SELEventData.hdr.TimeStamp, 
                        SELEventData.body.sysEventRecord.GenID[0],  SELEventData.body.sysEventRecord.GenID[1], 
                        SELEventData.body.sysEventRecord.EvMRev, SELEventData.body.sysEventRecord.SensorType, 
                        SELEventData.body.sysEventRecord.EvtDirType,SELEventData.body.sysEventRecord.EvtData1, 
                        SELEventData.body.sysEventRecord.EvtData2, SELEventData.body.sysEventRecord.EvtData3);
                                
                    //获取传感器名称
                    //printf("sensor number %d\n", SELEventData.SensorNum);
                    if(SELEventData.body.sysEventRecord.SensorNum != 0xff)
                    {
                        found_flag = 0;
                        for(j=0;j<MAX_SENSOR_NUMBERS;j++)   //先从之前的缓存里查找传感器名称
                        {
                            if(senNumNameTab[j].sensor_number == 0xff)  //再往后没有内容了。
                                break;

                            if(senNumNameTab[j].sensor_number == SELEventData.body.sysEventRecord.SensorNum)
                            {                                                
                                //cJSON_AddStringToObject(pJsonsub, "D12", senNumNameTab[i].sensor_name);  //SensorName -> D12
                                websWrite(wp, "\"D12\":\"%s\"}", senNumNameTab[j].sensor_name);
                                found_flag = 1;
                                break;
                            }
                        }

                        if(found_flag == 0) //在缓存里没有找到
                        {
                            if(target_addr == 0x20)
                            {
                                wRet = IPMI_GetSensorName(&UDSSession, SELEventData.body.sysEventRecord.SensorNum, sensorName, DEFAULT_TIMEOUT);
                                //printf("---> get sensor name: %s\n", sensorName);
                            }
                            else
                            {
                                wRet = IPMC_GetSensorName(&UDSSession, target_addr,SELEventData.body.sysEventRecord.SensorNum, sensorName, DEFAULT_TIMEOUT);
                            }
                            //cJSON_AddStringToObject(pJsonsub, "D12", senNumNameTab[i].sensor_name);     //SensorName->D12
                            websWrite(wp, "\"D12\":\"%s\"}", sensorName);
                            if(wRet == 0)
                            {
                                //将得到的传感器名称保存到缓存中
                                for(j=0;j<MAX_SENSOR_NUMBERS;j++)
                                {
                                    if(senNumNameTab[j].sensor_number == 0xff)
                                    {
                                        senNumNameTab[j].sensor_number = SELEventData.body.sysEventRecord.SensorNum;
                                        strcpy(senNumNameTab[j].sensor_name, sensorName);                                
                                        break;
                                    }
                                }
                            }    
                        }                
                    }
                    else
                    {
                        //cJSON_AddStringToObject(pJsonsub, "D12", "--"); //SensorName -> D12
                        websWrite(wp, "\"D12\":\"--\"}");
                    }
                }
                else if(SELEventData.hdr.Type == 0xC0)
                {
                    //printf("oem sel\n");
                    websWrite(wp, "{\"D1\":%d,\"D2\":%d,\"D3\":%d,\"D4\":%d,\"D5\":%d,\"D6\":%d,\"D7\":%d,\"D8\":%d,\"D9\":%d,\"D10\":0,\"D11\":0,\"D12\":0}",
                        SELEventData.hdr.ID, SELEventData.hdr.Type, SELEventData.hdr.TimeStamp, 
                        SELEventData.body.oemEventRecord.OEMDefined[0], SELEventData.body.oemEventRecord.OEMDefined[1],
                        SELEventData.body.oemEventRecord.OEMDefined[2], SELEventData.body.oemEventRecord.OEMDefined[3],
                        SELEventData.body.oemEventRecord.OEMDefined[4], SELEventData.body.oemEventRecord.OEMDefined[5]);
                                
                }

                if(RecID == 0xffff) //last record
                    break;

                //usleep(1);
            }
        }
    }

    //Close session
    LIBIPMI_CloseSession(&UDSSession );

    //cJSON_AddItemToObject(root, "data", pJsonArry);

    websWrite(wp, "]}");
    websFlush(wp, 0);
    websDone(wp);
    //printf("cJSON:%s\n",pStr);
    
    // if(root)
    //     cJSON_Delete(root);
    // if(pStr)
    //     wfree(pStr);
    if(pSELBuff)
        wfree(pSELBuff);

    return;

error_out:
    //Close session
    LIBIPMI_CloseSession(&UDSSession );
    websError(wp, 404, "Get SEL error!");
    // if(root)
    //     cJSON_Delete(root);
    // if(pStr)
    //     wfree(pStr);
    if(pSELBuff)
        wfree(pSELBuff);

}


void SetTime(Webs *wp)
{
    int wRet = 0;
    IPMI20_UDS_SESSION_T    UDSSession;
    SetSELTimeReq_T SetSELTimeReq;
    SetSELTimeUTCOffsetReq_T SetSELTimeUTCOffsetReq;
    uint8_t target_addr;
    
    char *strUTCOffset = websGetVar(wp, "UTCOffset", NULL); //这里的时区单位是 分钟
    char *strTime = websGetVar(wp, "time", NULL);

    SetSELTimeUTCOffsetReq.UTCOffset = atoi(strUTCOffset);  //东8区就是 8*60
    printf("strUTCOffset: %s, UTCOffset: %d\n", strUTCOffset, SetSELTimeUTCOffsetReq.UTCOffset);
    
    SetSELTimeReq.Time = atoi(strTime);
    printf("strTime: %s, Time: %d\n", strTime, SetSELTimeReq.Time);
  
    //Create session
    LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);
    
    target_addr = gIPMBAddr[wp->index];
    if(target_addr == 0x20)
    {
        wRet = IPMICMD_SetSELTime(&UDSSession,  &SetSELTimeReq, DEFAULT_TIMEOUT);
    }
    else
    {
        wRet = IPMC_SetSELTime(&UDSSession, target_addr, &SetSELTimeReq, DEFAULT_TIMEOUT);
    }
    if(wRet != 0)
    {
        websError(wp, 404, "Set sel time fail!");
        //Close session
        LIBIPMI_CloseSession(&UDSSession );
        return;
    }

    if(target_addr == 0x20)
    {
        wRet = IPMICMD_SetSELTimeUTCOffset(&UDSSession, &SetSELTimeUTCOffsetReq, DEFAULT_TIMEOUT);
    }
    else
    {
        wRet = IPMC_SetSELTimeUTCOffset(&UDSSession, target_addr, &SetSELTimeUTCOffsetReq, DEFAULT_TIMEOUT);
    }
    if(wRet != 0)
    {
        websError(wp, 404, "Set sel time UTC offset fail!");
        //Close session
        LIBIPMI_CloseSession(&UDSSession );
        return;
    }
    //Close session
    LIBIPMI_CloseSession(&UDSSession );
    
    
    cJSON * root =  cJSON_CreateObject();
    cJSON * data =  cJSON_CreateObject();
    cJSON_AddItemToObject(root, "data", data);//根节点下添加
    cJSON_AddStringToObject(root, "msg", "");
    cJSON_AddNumberToObject(root, "code", 200);

    char *pStr;
    pStr = cJSON_PrintUnformatted(root);
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp); 
    websWrite(wp,"%s", pStr);
    websFlush(wp, 0);
    websDone(wp);
    //printf("cJSON:%s\n", pStr);

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

}


void GetTime(Webs *wp)
{
    int wRet = 0;
    IPMI20_UDS_SESSION_T    UDSSession;
    GetSELTimeRes_T GetSELTimeRes;
    GetSELTimeUTCOffsetRes_T GetSELTimeUTCOffsetRes;
    uint8_t target_addr;
  
    //Create session
    LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);

    target_addr = gIPMBAddr[wp->index];
    if(target_addr == 0x20)
    {
        wRet = IPMICMD_GetSELTime(&UDSSession, &GetSELTimeRes, DEFAULT_TIMEOUT);
    }
    else
    {
        wRet = IPMC_GetSELTime(&UDSSession, target_addr, &GetSELTimeRes, DEFAULT_TIMEOUT);
    }
    if(wRet != 0)
    {
        websError(wp, 404, "Get sel time fail!");
        //Close session
        LIBIPMI_CloseSession(&UDSSession );
        return;
    }
    if(target_addr == 0x20)
    {
        wRet = IPMICMD_GetSELTimeUTCOffset(&UDSSession, &GetSELTimeUTCOffsetRes, DEFAULT_TIMEOUT);
    }
    else
    {
        wRet = IPMC_GetSELTimeUTCOffset(&UDSSession, target_addr, &GetSELTimeUTCOffsetRes, DEFAULT_TIMEOUT);
    }
    if(wRet != 0)
    {
        websError(wp, 404, "Get time UTC offset fail!");
        //Close session
        LIBIPMI_CloseSession(&UDSSession );
        return;
    }
    //Close session
    LIBIPMI_CloseSession(&UDSSession );
    
    
    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, "time", GetSELTimeRes.Time);  //据1970年的秒数，UTC时间
    cJSON_AddNumberToObject(data, "UTCOffset", GetSELTimeUTCOffsetRes.UTCOffset);   //时区

    char *pStr;
    pStr = cJSON_PrintUnformatted(root);
    websSetStatus(wp, 200);
    websWriteHeaders(wp, -1, 0);
    websWriteEndHeaders(wp); 
    websWrite(wp,"%s", pStr);
    websFlush(wp, 0);
    websDone(wp);
    //printf("cJSON:%s\n", pStr);

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