#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;
    
	//Create session
    LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);

    //擦除Flash的配置区
    IPMICMD_restoreFactorySettings(&UDSSession, DEFAULT_TIMEOUT);
    
    //重启BMC
    wRet = IPMICMD_ResetBMC(&UDSSession, DEFAULT_TIMEOUT);
	if(wRet != 0)
	{
		websError(wp, 404, "Reset BMC fail!");
	}

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

  
    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 web_ResetBMC(Webs *wp){
	uint16_t    wRet = LIBIPMI_E_SUCCESS;
    IPMI20_UDS_SESSION_T    UDSSession;
    
	//Create session
    LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);

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

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

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

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

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

    wRet = IPMICMD_GetLanInfo(&UDSSession, index, &LanInfo, DEFAULT_TIMEOUT);
    if(wRet != 0)
    {
        websError(wp, 404, "Get Lan Info fail!");
    }

    //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, "eth", LanInfo.EthName);

    if(LanInfo.IPAddrSrc == STATIC_IP_SOURCE)
        cJSON_AddStringToObject(data, "mode", "static");
    else if(LanInfo.IPAddrSrc == DHCP_IP_SOURCE)
        cJSON_AddStringToObject(data, "mode", "DHCP");
    else if(LanInfo.IPAddrSrc == BIOS_IP_SOURCE)
        cJSON_AddStringToObject(data, "mode", "BIOS");
    else 
        cJSON_AddStringToObject(data, "mode", "Other");
    
    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);

    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 web_SetLanInfo(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);    //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

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

    strcpy(LanInfo.EthName, EthName);
    if((strcmp(strMode, "static") == 0) || (strcmp(strMode, "Static") == 0) 
        || (strcmp(strMode, "STATIC") == 0))
    {
        LanInfo.IPAddrSrc = STATIC_IP_SOURCE;  //0:unspecified 1:Static 2:DHCP  3:BIOS 4:other    
    }
    else if((strcmp(strMode, "DHCP") == 0) || (strcmp(strMode, "Dhcp") == 0 )
        || (strcmp(strMode, "dhcp") == 0))
    {
        LanInfo.IPAddrSrc = DHCP_IP_SOURCE;    
    }
    else if((strcmp(strMode, "BIOS") == 0) || (strcmp(strMode, "Bios") == 0 )
        || (strcmp(strMode, "bios") == 0))
    {
        LanInfo.IPAddrSrc = BIOS_IP_SOURCE;    
    }
    else
    {
        LanInfo.IPAddrSrc = BMC_OTHER_SOURCE;  
    }

    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);
    
    //Create session
    LIBIPMI_CreateSession(&UDSSession, DEFAULT_TIMEOUT);

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

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

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


/*
    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;     
}


