#include "SAB.h"
#include "webApi.h"
#include "tasks.h"

boolean apiTesterApi(WEBServerManager::HttpRequestData &HRD, WiFiClient* wc, void* pData)
{
  wc->print(F("HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"API\" : \"available\" }"));
  return true;
}

boolean viewByUIDApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SAB *p = (SAB *)pData;
  char buffer[200];
  DictionaryHelper::StringEntity *pSE = HRD.getParams("UID");

  if(pSE == NULL)
  {
    sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"failed\", \"message\" : \"expected UID parameter\" }");
  }
  else if(strlen(pSE->getString()) > 0)
  {
    if(p->getScreenManager().displayView(atoi(pSE->getString())))
      sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"ViewUID\" : \"%d\" }", p->getScreenManager().getCurrentViewUID());
    else
      sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"failed\", \"message\" : \"%s\" }", p->getScreenManager().getErrorMessage());
  }
  else
    sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"failed\", \"message\" : \"UID parameter empty\" }");
  wc->print(buffer);
  return true;
}

boolean nextViewApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SAB *p = (SAB *)pData;
  char buffer[200];
  if(p->getScreenManager().displayNextView())
    sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"ViewUID\" : \"%d\" }", p->getScreenManager().getCurrentViewUID());
  else
    sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"failed\", \"message\" : \"%s\" }", p->getScreenManager().getErrorMessage());
  wc->print(buffer);
  return true;
}

boolean rtcGetTimeApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SAB *p = (SAB *)pData;
  char buffer[200];
  DateTime d = p->getRtcManager().getDateTime();
  sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"date\" : \"%d/%d/%d\", \"time\" : \"%d:%d:%d\" }", d.day(), d.month(), d.year(), d.hour(), d.minute(), d.second());
  wc->print(buffer);
  return true;
}

boolean rtcSetTimeApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SAB *p = (SAB *)pData;
  char buffer[200];
  DictionaryHelper::StringEntity *pSE = HRD.getParams("datetime");
  if(pSE == NULL)
  {
    sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"failed\", \"message\" : \"expected datetime parameter\" }");
  }
  else if(strlen(pSE->getString()) > 0)
  {
    Dictionary<DictionaryHelper::StringEntity> *dictio = pSE->split('_');
    if(dictio == NULL)
    {
      sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"failed\", \"message\" : \"datetime format error\" }");
      wc->print(buffer);
      return true;
    }
    else
    {
      if(dictio->count() != 6)
      {
        sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"error\", \"message\" : \"datetime format error\" }"); 
      }
      else
      {
        p->getRtcManager().setDateTime(DateTime( 
          atoi(dictio->getAt(2)->getString()),
          atoi(dictio->getAt(1)->getString()),
          atoi(dictio->getAt((unsigned int)0)->getString()),
          atoi(dictio->getAt(3)->getString()),
          atoi(dictio->getAt(4)->getString()),
          atoi(dictio->getAt(5)->getString())
          ));
        DateTime d = p->getRtcManager().getDateTime();
        sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"date\" : \"%d/%d/%d\", \"time\" : \"%d:%d:%d\" }", d.day(), d.month(), d.year(), d.hour(), d.minute(), d.second());
      }
      
      wc->print(buffer);
      delete dictio;
      
      return true;
    }
  }
  wc->print(buffer);
  return true;
}

boolean sdCardUnmountApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SdCardApiPacket *pV = (SdCardApiPacket*)pData;
  SAB *p = (SAB *)pV->pSab;
  float *sdCardSize = (float *) &pV->pView->sdCardSize;
  char buffer[200];
  p->getSdCardManager().end();
  *sdCardSize = 0.0;
  sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"card\" : \"unmounted\" }");
  wc->print(buffer);
  return true;
}

boolean sdCardMountApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SdCardApiPacket *pV = (SdCardApiPacket*)pData;
  SAB *p = (SAB *)pV->pSab;
  float *sdCardSize = (float *) &pV->pView->sdCardSize;
  char buffer[200];
  
  if(p->getSdCardManager().begin(p->getSdCardConfig().getSPISpeed(), p->getPinConfig().getSPI_sdCard_cs()))
  {
    sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"card\" : \"mounted\" }");
    *sdCardSize = p->getSdCardManager().getSize(GBYTE);
  }
  else
    sprintf(buffer,"HTTP/1.1 500 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"error\", \"message\" : \"begin failed\" }");
    
  wc->print(buffer);
  return true;
}

boolean espRestartApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SAB *sab = (SAB*)pData;
  char  buffer[200];
  
  sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"message\" : \"module %s in 10 seconds\" }",strstr(HRD.httpResource,"reset") == NULL ? "restarting" : "resetting");
  wc->print(buffer);
  
  sab->getTaskSchedulerManager().addTask(sab->getTaskSchedulerManager().findFreeTaskId(), TaskSchedulerManagerHelper::Schedule::scheduleBuilder()
  ->setSeconds(10)
  ->setTriggerType(TaskSchedulerManagerHelper::Schedule::TRIGGER_ONCE_AND_DELETE)
  ->setTriggerRightAway(false), &(task_esp_reset_restart), NULL);
  
  return true;
}

boolean espResetApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  return espRestartApi(HRD, wc, pData);
}

boolean sdCardSizeApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
	SAB *p = (SAB *)pData;
	char buffer[200];
	double size = p->getSdCardManager().getSize(GBYTE);
	if(size == 0.0)
		sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"card\" : \"not present\", \"size\" : \"0\" }");
	else
		sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"card\" : \"present\", \"size\" : \"%.2f\", \"unit\" : \"GByte\" }",size);
	
	wc->print(buffer);
	return true;
}

boolean staWifiInfoApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
	SAB *p = (SAB *)pData;
	char buffer[300];
  IPAddress IP = p->getConnectivityManager().localIP();
 
  sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"RSSI\" : \"%d\", \"RSSI2\" : \"%d\", \"local IP\" : \"%u.%u.%u.%u\", \"mac\" : \"%s\" }", p->getConnectivityManager().RSSI(), p->getConnectivityManager().RSSIPercent(), IP[0], IP[1], IP[2], IP[3], p->getConnectivityManager().macAddress().c_str());
  
  wc->print(buffer);
	return true;
}

boolean systemInfoApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SAB *p = (SAB *)pData;
  char buffer[300];
  uint32_t freeMem;
  uint16_t biggestContigMemBlock;
  uint8_t frag;
  ESP.getHeapStats(&freeMem, &biggestContigMemBlock, &frag);
  sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"CPU freq\" : \"%u\", \"free RAM\" : \"%u\", \"heap frag\" : \"%u\", \"max block\" : \"%u\", \"nb views\" : \"%u\" }", ESP.getCpuFreqMHz(), freeMem, frag, biggestContigMemBlock, p->getScreenManager().getViewCount());
  
  wc->print(buffer);
  return true;
}

boolean powerInfoApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SAB *p = (SAB *)pData;
  char buffer[300];
  PowerInfo pi = p->getPowerInfo();
   
  sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"power type\" : \"%s\", \"level\" : \"%u\", \"unit\" : \"%%\" }", pi.powerType == USB ? "USB" : "BAT", pi.level);
  
  wc->print(buffer);
  return true;
}

boolean ioGetLevelApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  boolean *ioState = (boolean *)pData;
  char buffer[300] = "";
  char helperBuffer[20] = "";

  if(HRD.getParams.count() == 0)//We send every IO state
  {
    sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"P0\" : \"%d\", \"P1\" : \"%d\", \"P2\" : \"%d\", \"P3\" : \"%d\", \"P4\" : \"%d\", \"P5\" : \"%d\", \"P6\" : \"%d\", \"P7\" : \"%d\" }",ioState[0],ioState[1],ioState[2],ioState[3],ioState[4],ioState[5],ioState[6],ioState[7]);
  }
  else
  {
    strcpy(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\"");
    if(HRD.getParams("P0") != NULL)
    {
      sprintf(helperBuffer,", \"P0\" : \"%d\"",ioState[0]);
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P1") != NULL)
    {
      sprintf(helperBuffer,", \"P1\" : \"%d\"",ioState[1]);
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P2") != NULL)
    {
      sprintf(helperBuffer,", \"P2\" : \"%d\"",ioState[2]);
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P3") != NULL)
    {
      sprintf(helperBuffer,", \"P3\" : \"%d\"",ioState[3]);
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P4") != NULL)
    {
      sprintf(helperBuffer,", \"P4\" : \"%d\"",ioState[4]);
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P5") != NULL)
    {
      sprintf(helperBuffer,", \"P5\" : \"%d\"",ioState[5]);
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P6") != NULL)
    {
      sprintf(helperBuffer,", \"P6\" : \"%d\"",ioState[6]);
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P7") != NULL)
    {
      sprintf(helperBuffer,", \"P7\" : \"%d\"",ioState[7]);
      strcat(buffer,helperBuffer);
    }
    strcat(buffer," }");
  }

  wc->print(buffer);
  return true;
}

boolean ioSetLevelApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SAB *p = (SAB *)pData;
  char buffer[300] = "";
  boolean ioState[8] = {0};

  if(HRD.getParams("P0") != NULL)
  {
    p->getIoManager().getPcf().digitalWrite(PCF8574::P0,atoi(HRD.getParams("P0")->getString()));
  }
  if(HRD.getParams("P1") != NULL)
  {
    p->getIoManager().getPcf().digitalWrite(PCF8574::P1,atoi(HRD.getParams("P1")->getString()));
  }
  if(HRD.getParams("P2") != NULL)
  {
    p->getIoManager().getPcf().digitalWrite(PCF8574::P2,atoi(HRD.getParams("P2")->getString()));
  }
  if(HRD.getParams("P3") != NULL)
  {
    p->getIoManager().getPcf().digitalWrite(PCF8574::P3,atoi(HRD.getParams("P3")->getString()));
  }
  if(HRD.getParams("P4") != NULL)
  {
    p->getIoManager().getPcf().digitalWrite(PCF8574::P4,atoi(HRD.getParams("P4")->getString()));
  }
  if(HRD.getParams("P5") != NULL)
  {
    p->getIoManager().getPcf().digitalWrite(PCF8574::P5,atoi(HRD.getParams("P5")->getString()));
  }
  if(HRD.getParams("P6") != NULL)
  {
    p->getIoManager().getPcf().digitalWrite(PCF8574::P6,atoi(HRD.getParams("P6")->getString()));
  }
  if(HRD.getParams("P7") != NULL)
  {
    p->getIoManager().getPcf().digitalWrite(PCF8574::P7,atoi(HRD.getParams("P7")->getString()));
  }

  p->getIoManager().getPcf().digitalReadAll(ioState);//We retrieve the IO state
  sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"P0\" : \"%d\", \"P1\" : \"%d\", \"P2\" : \"%d\", \"P3\" : \"%d\", \"P4\" : \"%d\", \"P5\" : \"%d\", \"P6\" : \"%d\", \"P7\" : \"%d\" }",ioState[0],ioState[1],ioState[2],ioState[3],ioState[4],ioState[5],ioState[6],ioState[7]);
  
  wc->print(buffer);
  return true;
}

boolean ioGetModeApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SAB *p = (SAB *)pData;
  boolean ioMode[8] = {0};
  char buffer[300] = "";
  char helperBuffer[20] = "";

  p->getIoManager().getPcf().getPinModeAll(ioMode);//We retrieve the IO modes aka INPUT or OUTPUT

  if(HRD.getParams.count() == 0)//We send every IO mode
  {
    sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"P0\" : \"%s\", \"P1\" : \"%s\", \"P2\" : \"%s\", \"P3\" : \"%s\", \"P4\" : \"%s\", \"P5\" : \"%s\", \"P6\" : \"%s\", \"P7\" : \"%s\" }",ioMode[0] ? "OUT":"IN",ioMode[1] ? "OUT":"IN",ioMode[2] ? "OUT":"IN",ioMode[3] ? "OUT":"IN",ioMode[4] ? "OUT":"IN",ioMode[5] ? "OUT":"IN",ioMode[6] ? "OUT":"IN",ioMode[7] ? "OUT":"IN");
  }
  else
  {
    strcpy(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\"");
    if(HRD.getParams("P0") != NULL)
    {
      sprintf(helperBuffer,", \"P0\" : \"%s\"",ioMode[0] ? "OUT":"IN");
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P1") != NULL)
    {
      sprintf(helperBuffer,", \"P1\" : \"%s\"",ioMode[1] ? "OUT":"IN");
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P2") != NULL)
    {
      sprintf(helperBuffer,", \"P2\" : \"%s\"",ioMode[2] ? "OUT":"IN");
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P3") != NULL)
    {
      sprintf(helperBuffer,", \"P3\" : \"%s\"",ioMode[3] ? "OUT":"IN");
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P4") != NULL)
    {
      sprintf(helperBuffer,", \"P4\" : \"%s\"",ioMode[4] ? "OUT":"IN");
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P5") != NULL)
    {
      sprintf(helperBuffer,", \"P5\" : \"%s\"",ioMode[5] ? "OUT":"IN");
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P6") != NULL)
    {
      sprintf(helperBuffer,", \"P6\" : \"%s\"",ioMode[6] ? "OUT":"IN");
      strcat(buffer,helperBuffer);
    }
    if(HRD.getParams("P7") != NULL)
    {
      sprintf(helperBuffer,", \"P7\" : \"%s\"",ioMode[7] ? "OUT":"IN");
      strcat(buffer,helperBuffer);
    }
    strcat(buffer," }");
  }

  wc->print(buffer);
  return true;
}

boolean ioSetModeApi(WEBServerManager::HttpRequestData &HRD, WiFiClient *wc, void *pData)
{
  SAB *p = (SAB *)pData;
  char buffer[300] = "";
  boolean ioMode[8] = {0};

  if(HRD.getParams("P0") != NULL)
  {
    p->getIoManager().getPcf().pinMode(PCF8574::P0,strcmp(HRD.getParams("P0")->getString(), "IN") == 0 ? INPUT:OUTPUT);
  }
  if(HRD.getParams("P1") != NULL)
  {
    p->getIoManager().getPcf().pinMode(PCF8574::P1,strcmp(HRD.getParams("P1")->getString(), "IN") == 0 ? INPUT:OUTPUT);
  }
  if(HRD.getParams("P2") != NULL)
  {
    p->getIoManager().getPcf().pinMode(PCF8574::P2,strcmp(HRD.getParams("P2")->getString(), "IN") == 0 ? INPUT:OUTPUT);
  }
  if(HRD.getParams("P3") != NULL)
  {
    p->getIoManager().getPcf().pinMode(PCF8574::P3,strcmp(HRD.getParams("P3")->getString(), "IN") == 0 ? INPUT:OUTPUT);
  }
  if(HRD.getParams("P4") != NULL)
  {
    p->getIoManager().getPcf().pinMode(PCF8574::P4,strcmp(HRD.getParams("P4")->getString(), "IN") == 0 ? INPUT:OUTPUT);
  }
  if(HRD.getParams("P5") != NULL)
  {
    p->getIoManager().getPcf().pinMode(PCF8574::P5,strcmp(HRD.getParams("P5")->getString(), "IN") == 0 ? INPUT:OUTPUT);
  }
  if(HRD.getParams("P6") != NULL)
  {
    p->getIoManager().getPcf().pinMode(PCF8574::P6,strcmp(HRD.getParams("P6")->getString(), "IN") == 0 ? INPUT:OUTPUT);
  }
  if(HRD.getParams("P7") != NULL)
  {
    p->getIoManager().getPcf().pinMode(PCF8574::P7,strcmp(HRD.getParams("P7")->getString(), "IN") == 0 ? INPUT:OUTPUT);
  }

  p->getIoManager().getPcf().getPinModeAll(ioMode);//We retrieve the IO modes aka INPUT or OUTPUT
  sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{ \"status\" : \"ok\", \"P0\" : \"%s\", \"P1\" : \"%s\", \"P2\" : \"%s\", \"P3\" : \"%s\", \"P4\" : \"%s\", \"P5\" : \"%s\", \"P6\" : \"%s\", \"P7\" : \"%s\" }",ioMode[0] ? "OUT":"IN",ioMode[1] ? "OUT":"IN",ioMode[2] ? "OUT":"IN",ioMode[3] ? "OUT":"IN",ioMode[4] ? "OUT":"IN",ioMode[5] ? "OUT":"IN",ioMode[6] ? "OUT":"IN",ioMode[7] ? "OUT":"IN");
  
  wc->print(buffer);
  return true;
}
