#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 "com_BmcType.h"
#include "libipmi_usermgmt.h"
#include <string.h>
#include <math.h>
#include "com_IPMI_LANConfig.h"

uint8_t mac2hex(const char *strMac, uint8_t index);
uint8_t ip2dec(const char *strIp, uint8_t index);


void restoreFactorySettings(Webs *wp){
	uint16_t    wRet = LIBIPMI_E_SUCCESS;
    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)
    {
        //擦除Flash的配置区
        wRet = IPMICMD_restoreFactorySettings(&UDSSession, DEFAULT_TIMEOUT);
    }
    else
    {
        wRet = IPMC_restoreFactorySettings(&UDSSession, target_addr, DEFAULT_TIMEOUT);
    }
    
    //重启BMC
    if(target_addr == 0x20)
    {
        wRet = IPMICMD_ResetBMC(&UDSSession, DEFAULT_TIMEOUT);
    }
    else
    {
        wRet = IPMC_ResetBMC(&UDSSession, target_addr,DEFAULT_TIMEOUT);
    }
	if(wRet != 0)
	{
		websError(wp, 404, "Reset BMC fail!");
	}

	//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 web_ResetBMC(Webs *wp){
	uint16_t    wRet = LIBIPMI_E_SUCCESS;
    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)
    {
	   wRet = IPMICMD_ResetBMC(&UDSSession, DEFAULT_TIMEOUT);
    }
    else
    {
        wRet = IPMC_ResetBMC(&UDSSession, target_addr, DEFAULT_TIMEOUT);
    }
	if(wRet != 0)
	{
		websError(wp, 404, "Reset BMC fail!");
	}

	//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 web_GetLanInfo(Webs *wp){
    uint16_t    wRet = LIBIPMI_E_SUCCESS;
    IPMI20_UDS_SESSION_T    UDSSession;
    LanInfo_T   LanInfo;
    uint8_t index = 0;
    char *EthName = websGetVar(wp, "eth", NULL);
    uint8_t target_addr;

    if(strcmp(EthName, "eth0") == 0)
    {
        index = 0;
    }
    else
    {
        websError(wp, 404, "Invalid eth name!");
        return;
    }

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

    target_addr = gIPMBAddr[wp->index];
    if(target_addr == 0x20)
    {
        wRet = IPMICMD_GetLanInfo(&UDSSession, index, &LanInfo, DEFAULT_TIMEOUT);
        if(wRet != 0)
        {
            websError(wp, 404, "Get Lan Info fail!");
        }
    }
    else
    {
        memset(&LanInfo, 0, sizeof(LanInfo_T));
    }

    //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_AddStringToObject(data, "eth", "eth0");
    cJSON_AddStringToObject(data, "mode", "static");
    
    char strIp[16] = {0};
    sprintf(strIp, "%d.%d.%d.%d", LanInfo.IPAddr[0], LanInfo.IPAddr[1], 
        LanInfo.IPAddr[2], LanInfo.IPAddr[3]);
    cJSON_AddStringToObject(data, "ip", strIp);

    char strMac[18] = {0};
    sprintf(strMac, "%02x:%02x:%02x:%02x:%02x:%02x", LanInfo.MACAddr[0], LanInfo.MACAddr[1], 
        LanInfo.MACAddr[2], LanInfo.MACAddr[3], LanInfo.MACAddr[4], LanInfo.MACAddr[5]);
    cJSON_AddStringToObject(data, "mac", strMac);

    char strBrdCast[16] = {0};
    sprintf(strBrdCast, "%d.%d.%d.%d", LanInfo.BroadCast[0], LanInfo.BroadCast[1], 
        LanInfo.BroadCast[2], LanInfo.BroadCast[3]);
    cJSON_AddStringToObject(data, "broadcast", strBrdCast);

    char strMask[16] = {0};
    sprintf(strMask, "%d.%d.%d.%d", LanInfo.NetMask[0], LanInfo.NetMask[1], 
        LanInfo.NetMask[2], LanInfo.NetMask[3]);
    cJSON_AddStringToObject(data, "netmask", strMask);

    char strGw[16] = {0};
    sprintf(strGw, "%d.%d.%d.%d", LanInfo.DefaultGW[0], LanInfo.DefaultGW[1], 
        LanInfo.DefaultGW[2], LanInfo.DefaultGW[3]);
    cJSON_AddStringToObject(data, "defaultgw", strGw);

    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 web_SetLanInfo(Webs *wp){
    uint16_t    wRet = LIBIPMI_E_SUCCESS;
    IPMI20_UDS_SESSION_T    UDSSession;
    LanInfo_T   LanInfo;
    uint8_t index = 0;
    uint8_t target_addr;
    
    char *EthName = websGetVar(wp, "eth", NULL);    //eth0
    char *strMode = websGetVar(wp, "mode", NULL);   //static DHCP
    char *strMac = websGetVar(wp, "mac", NULL);     //00:12:34:56:78:88
    char *strIp = websGetVar(wp, "ip", NULL);       //192.168.0.208
    char *strBrdCast = websGetVar(wp, "broadcast", NULL);   //192.168.0.255
    char *strMask = websGetVar(wp, "netmask", NULL);        //255.255.255.0
    char *strGw = websGetVar(wp, "defaultgw", NULL);        //192.168.0.1
    char *strSave = websGetVar(wp, "isSave", NULL);         //0 or 1

    int  isSave = atoi(strSave);

    if(strlen(EthName) > 20)
    {
        printf("EthName is too long! %s\n", EthName);
        websError(wp, 404, "EthName is too long!");
        return;
    }

    if(strcmp(EthName, "eth0") == 0)    //目前只有一个网卡
    {
        index = 0;
    }
    else
    {
        websError(wp, 404, "Invalid eth name!");
        return;
    }

    target_addr = gIPMBAddr[wp->index];
    if(target_addr == 0x20)
    {
        LanInfo.IPAddr[0] = ip2dec(strIp, 0);
        LanInfo.IPAddr[1] = ip2dec(strIp, 1);
        LanInfo.IPAddr[2] = ip2dec(strIp, 2);
        LanInfo.IPAddr[3] = ip2dec(strIp, 3);
        
        LanInfo.BroadCast[0] = ip2dec(strBrdCast, 0);
        LanInfo.BroadCast[1] = ip2dec(strBrdCast, 1);
        LanInfo.BroadCast[2] = ip2dec(strBrdCast, 2);
        LanInfo.BroadCast[3] = ip2dec(strBrdCast, 3);

        LanInfo.NetMask[0] = ip2dec(strMask, 0);
        LanInfo.NetMask[1] = ip2dec(strMask, 1);
        LanInfo.NetMask[2] = ip2dec(strMask, 2);
        LanInfo.NetMask[3] = ip2dec(strMask, 3);

        LanInfo.DefaultGW[0] = ip2dec(strGw, 0);
        LanInfo.DefaultGW[1] = ip2dec(strGw, 1);
        LanInfo.DefaultGW[2] = ip2dec(strGw, 2);
        LanInfo.DefaultGW[3] = ip2dec(strGw, 3);

        LanInfo.MACAddr[0] = mac2hex(strMac, 0);
        LanInfo.MACAddr[1] = mac2hex(strMac, 1);
        LanInfo.MACAddr[2] = mac2hex(strMac, 2);
        LanInfo.MACAddr[3] = mac2hex(strMac, 3);
        LanInfo.MACAddr[4] = mac2hex(strMac, 4);
        LanInfo.MACAddr[5] = mac2hex(strMac, 5);

        //isSave 只能是0和1这两个值。
        if(isSave != 1)
        {
            isSave = 0;
        }
        
        //Create session
        LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);

        wRet = IPMICMD_SetLanInfo(&UDSSession, index, isSave, &LanInfo, DEFAULT_TIMEOUT);
        if(wRet != 0)
        {
            websError(wp, 404, "Reset BMC fail!");
        }

        //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 web_GetRunTime(Webs *wp){
    uint16_t    wRet = LIBIPMI_E_SUCCESS;
    IPMI20_UDS_SESSION_T    UDSSession;
    uint8_t target_addr;
    uint32_t    TotalRunTime = 1000;    //模块总运行时间，单位： 分钟
    uint32_t    CurRunTime = 50;        //模块本次运行时间，单位： 分钟
   
    
    cJSON * root =  cJSON_CreateObject();
    cJSON * data =  cJSON_CreateObject();
    cJSON_AddItemToObject(root, "data", data);//根节点下添加
    cJSON_AddStringToObject(data, "TotalRunTime", "129 hour 40 min");
    cJSON_AddStringToObject(data, "CurRunTime", "1 hour 3 min");
    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 web_SetModIdentifyOn(Webs *wp){
    uint16_t    wRet = LIBIPMI_E_SUCCESS;
    IPMI20_UDS_SESSION_T    UDSSession;
    uint8_t target_addr;
    char *strTime = websGetVar(wp, "timeSelect", NULL);    //
    int timeSelect = atoi(strTime);
    uint8_t identifySec = 0;

    switch(timeSelect)
    {
        case 0: //15s
            identifySec = 15;
            break;
        case 1: //30s
            identifySec = 30;
            break;
        case 2: //60s
            identifySec = 60;
            break;
        case 3: //120s
            identifySec = 120;
            break;
        case 4: //forever
            identifySec = 0xff;
            break;
        default:
            identifySec = 15;
            break;
    }

    printf("---> identify on Sec = %d\n", identifySec);
    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 web_SetModIdentifyOff(Webs *wp){
    uint16_t    wRet = LIBIPMI_E_SUCCESS;
    IPMI20_UDS_SESSION_T    UDSSession;
    uint8_t target_addr;
    uint8_t identifySec = 0;


    printf("---> identify off Sec = %d\n", identifySec);
    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 web_SaveConfig(Webs *wp){
    uint16_t    wRet = LIBIPMI_E_SUCCESS;
    IPMI20_UDS_SESSION_T    UDSSession;
    uint8_t target_addr;
    uint8_t identifySec = 0;

    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 web_RestoreConfig(Webs *wp){
    uint16_t    wRet = LIBIPMI_E_SUCCESS;
    IPMI20_UDS_SESSION_T    UDSSession;
    uint8_t target_addr;
    uint8_t identifySec = 0;

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

/*
    index = 0,1,2,3,4,5
*/
uint8_t mac2hex(const char *strMac, uint8_t index)
{
    int i = 0;
    char    *pStr = (char *)strMac;
    char    *pTmp = NULL;
    uint8_t macByte = 0;;
    char    tmp[3] = {0};

    if(index > 5)
    {
        printf("Invalid index %d\n", index);
        return -1;
    }

    //find
    while(pStr)
    {
        if(i == index)
            break;

        if(*pStr == ':')
            i++;
        
        pStr++;
    }

    if(*(pStr+1) == ':')
    {
        tmp[0] = *pStr;
        tmp[1] = '\0';
        tmp[2] = '\0';
    }
    else
    {
        tmp[0] = *pStr;
        tmp[1] = *(pStr+1);
        tmp[2] = '\0';
    }

    i=0;
    macByte = 0;
    while(tmp[i])
    {
        macByte = macByte<<4;
        if((tmp[i]>='0') && (tmp[i]<='9'))
            macByte += (tmp[i]-'0');
        else if((tmp[i]>='a') && (tmp[i]<='f'))
            macByte += (tmp[i]-'a') + 10;
        else if((tmp[i]>='A') && (tmp[i]<='F'))
            macByte += (tmp[i]-'A') + 10;

        i++;
    }

    return macByte;     
}

/*
    index = 0,1,2,3
*/
uint8_t ip2dec(const char *strIp, uint8_t index)
{
    int i = 0;
    char    *pStr = (char *)strIp;
    uint8_t ipByte = 0;;
    char    tmp[4] = {0};

    if(index > 3)
    {
        printf("Invalid index %d\n", index);
        return -1;
    }

    //find
    while(pStr)
    {
        if(i == index)
            break;

        if(*pStr == '.')
            i++;
        
        pStr++;
    }

    if(*(pStr+1) == '.')
    {
        tmp[0] = *pStr;
        tmp[1] = '\0';
        tmp[2] = '\0';
        tmp[3] = '\0';
    }
    else if(*(pStr+2) == '.')
    {
        tmp[0] = *pStr;
        tmp[1] = *(pStr+1);
        tmp[2] = '\0';
        tmp[3] = '\0';
    }
    else
    {
        tmp[0] = *pStr;
        tmp[1] = *(pStr+1);
        tmp[2] = *(pStr+2);
        tmp[3] = '\0';
    }

    ipByte = atoi(tmp);

    return ipByte;     
}


