#include "archinc.h"
#include "cli.h"
#include "strutil.h"
#include "nvstore.h"
#include "bdinfo.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef CONFIG_INCLUDE_NVSTORE

#define NVSTORE_BOARD_SERIAL_NAME "serial"
#define NVSTORE_BOARD_ECO_LEVEL_NAME "ecolevel"
#define BDINFO_BUFFER_SIZE (8)

static char serialNum[BDINFO_BUFFER_SIZE];
static char ecoLevel[BDINFO_BUFFER_SIZE];

static void clearBuffer(char * pBuf)
{
  int i;
  for(i=0;i<BDINFO_BUFFER_SIZE;i++)
    pBuf[i] = 0x00;
}

static int serialHandler(int argc, char * argv[], int flags)
{
  int retVal = 0;
  int sendPort;
  char * pOutBuf;
  int bufLen;
  char serialLen;

  pOutBuf = clicharGetOutputBuffer(&bufLen);

  if (argc == 2) {
    /*
     * Store the serial number in nvram
     */
    serialLen = (char)strlen(argv[1]);
    if (serialLen == 0) {
      return -1;
      }
    else if (serialLen > BDINFO_BUFFER_SIZE) {
      serialLen = BDINFO_BUFFER_SIZE;
      }

    /*
     * First, write the data to nvram
     */

    retVal = nvstoreWrite(NVSTORE_BOARD_SERIAL_NAME, argv[1], serialLen);
    if (retVal != 0) {
      sprintf(pOutBuf, "%s: board serial number write failed\r\n", argv[0]);
      clicharSendOutputBuffer(pOutBuf, bufLen);
      return retVal;
      }

    /*
     * Second, read the data back and put it in a volatile buffer
     */

    clearBuffer(serialNum);
    retVal = nvstoreRead(NVSTORE_BOARD_SERIAL_NAME, serialNum, &serialLen);

    if (retVal == 0) {
      sprintf(pOutBuf, "%s: board serial number is [%s]\r\n", argv[0], serialNum);
      clicharSendOutputBuffer(pOutBuf, bufLen);
      }
    }
  else if (argc == 1) {

    /* 
     * retrieve the serial number from nvram
     */

    serialLen = BDINFO_BUFFER_SIZE;
    clearBuffer(serialNum);
    retVal = nvstoreRead(NVSTORE_BOARD_SERIAL_NAME, serialNum, &serialLen);
    if (retVal == 0) {
      sprintf(pOutBuf, "%s: board serial number is [%s]\r\n", argv[0], serialNum);
      }
    else {
      sprintf(pOutBuf, "%s: board serial number not set or read failed\r\n", argv[0]);
      }
     clicharSendOutputBuffer(pOutBuf, bufLen);
    }
  else {
    retVal = -1;
    }
  

  return retVal;
}

static int ecolevelHandler(int argc, char * argv[], int flags)
{
  int retVal = 0;
  int sendPort;
  char * pOutBuf;
  int bufLen;
  char ecolevelLen;

  pOutBuf = clicharGetOutputBuffer(&bufLen);

  if (argc == 2) {
    /*
     * Store the eco level in nvram
     */
    ecolevelLen = (char)strlen(argv[1]);
    if (ecolevelLen == 0)
      return -1;
    else if (ecolevelLen > BDINFO_BUFFER_SIZE)
      ecolevelLen = BDINFO_BUFFER_SIZE;

    /*
     * First, write the data to nvram
     */

    retVal = nvstoreWrite(NVSTORE_BOARD_ECO_LEVEL_NAME, argv[1], ecolevelLen);
    if (retVal != 0) {
      sprintf(pOutBuf, "%s: board ECO level write failed\r\n", argv[0]);
      }

    /*
     * Second, read the data back and put it in a volatile buffer
     */

    clearBuffer(ecoLevel);
    retVal = nvstoreRead(NVSTORE_BOARD_ECO_LEVEL_NAME, ecoLevel, &ecolevelLen);

    if (retVal == 0) {
      sprintf(pOutBuf, "%s: board ECO level is [%s]\r\n", argv[0], ecoLevel);
      }

    }
  else if (argc == 1) {
    /* 
     * retrieve the eco level from nvram
     */
    ecolevelLen = BDINFO_BUFFER_SIZE;
    clearBuffer(ecoLevel);
    retVal = nvstoreRead(NVSTORE_BOARD_ECO_LEVEL_NAME, ecoLevel, &ecolevelLen);
    if (retVal == 0) {
      sprintf(pOutBuf, "%s: board ECO level is [%s]\r\n", argv[0], ecoLevel);
      }
    else {
      sprintf(pOutBuf, "%s: board ECO level not set or read failed\r\n", argv[0]);
      }
    }
  else {
    retVal = -1;
    }
  
  clicharSendOutputBuffer(pOutBuf, bufLen);

  return retVal;

}

void bdinfoGetSerial(char * pRetSerialNum)
{
  int i;
  if (pRetSerialNum == NULL)
    return;

  for(i=0;i<BDINFO_BUFFER_SIZE;i++)
    pRetSerialNum[i] = serialNum[i];
}

void bdinfoGetEcoLevel(char * pRetEcoLevel)
{
  int i;
  if (pRetEcoLevel == NULL)
    return;

  for(i=0;i<BDINFO_BUFFER_SIZE;i++)
    pRetEcoLevel[i] = ecoLevel[i];
}

int bdinfoInit(void)
{
  int retVal;
  int bufLen;
  char * pOutBuf;
  char length;

  pOutBuf = clicharGetOutputBuffer(&bufLen);

  length = BDINFO_BUFFER_SIZE;
  clearBuffer(serialNum);
  retVal = nvstoreRead(NVSTORE_BOARD_SERIAL_NAME, serialNum, &length);

  if (retVal != 0) {
    sprintf(pOutBuf, "!! no board serial info is stored\r\n");
    clicharSendOutputBuffer(pOutBuf, bufLen);
    }


  length = BDINFO_BUFFER_SIZE;
  clearBuffer(ecoLevel);
  retVal = nvstoreRead(NVSTORE_BOARD_ECO_LEVEL_NAME, ecoLevel, &length);

  if (retVal != 0) {
    sprintf(pOutBuf, "!! no board ECO level is stored\r\n");
    clicharSendOutputBuffer(pOutBuf, bufLen);
    }

  cliRegisterCommand("serial", serialHandler, "serial [number] - stores board serial number");
  cliRegisterCommand("ecolevel", ecolevelHandler, "ecolevel [level] - stores board ECO level");

  return retVal;
}

#endif /* CONFIG_INCLUDE_NVSTORE */
