#include "definition.h" 
#include "PinMapping.h"
#include "SAB.h"
#include "views.h"
#include "webApi.h"
#include "tasks.h"
#include "CFGDictionary.h"
#include "CFGParameterValue.h"
#define DEBUG

SAB sab;

unsigned long currentMs = 0, buttonMs = 0;
volatile boolean ioStateChange(false);
View1Packet v1p = {sab.getRtcManager().getDateTime(), sab.getSdCardManager().getSize(GBYTE), sab.getPowerInfo(),0, sab.getSoftVersion(), &sab};
ViewAPPacket vap = {sab.getConnectivityManager().softAPmacAddress(), sab.getConnectivityManager().softAPSSID(), sab.getConnectivityManager().softAPIP(), sab.getConnectivityManager().softAPgetStationNum()};
ViewSTAPacket vstap = {sab.getConnectivityManager().macAddress(), sab.getConnectivityManager().localIP(), sab.getConnectivityManager().RSSI()};
ViewIoInfoPacket vio = {{0},{0}};
SdCardApiPacket sdCardApiPacket = {NULL, NULL};

void setup() 
{
  // put your setup code here, to run once:
  Serial.println("Starting setup");
  CFGFileParser cfgFileParser(sab.getSdCardManager(), AP_CFG_FILE);
  CFGDictionary<CFGParameterValue> *cfgDictionary = (CFGDictionary<CFGParameterValue> *) cfgFileParser.parseFile();
  
  if(cfgDictionary != NULL)
  {
    Serial.print("AP PASSWORD : ");if((*cfgDictionary)("PASSWORD") != NULL)Serial.println((*cfgDictionary)("PASSWORD")->stringValue());
  }
  
  CFGFileParser cfgFileParsert1(sab.getSdCardManager(), "/CONFIG/TEST1.CFG");
  CFGFileParser cfgFileParsert2(sab.getSdCardManager(), "/CONFIG/TEST2.CFG");
  
  Serial.print("TEST1 : ");Serial.println(cfgFileParsert1.save(cfgDictionary));
  Serial.print("TEST2 : ");Serial.println(cfgFileParsert2.save(cfgDictionary));
  
  delete cfgDictionary;
  
  sab.getScreenManager().addView(&(view_1), &v1p, 0);
  sab.getScreenManager().addView(&(view_2), &vap, 1);
  sab.getScreenManager().addView(&(view_3), &vstap, 2);
  sab.getScreenManager().addView(&(memInfo), NULL, 3);
  sab.getScreenManager().addView(&(ioInfo), &vio, 4);
  sab.getScreenManager().addView(&(sysErrorInfo), &sab, 5);
  sab.getScreenManager().addView(NULL, NULL, 6); //for testing purposes
  sab.getScreenManager().addView(&(dummy), NULL, 7); //for testing purposes
  
  sab.getScreenManager().displayView(0);
  if(sab.getRtcManager().hasLostPower())
  {
    Serial.println("Clock lost power");
    sab.getRtcManager().setDateTime(DateTime(F(__DATE__), F(__TIME__)));
  }
  
  sab.getWebServerManager().addApiRoutine("/sab/web/apitester", &(apiTesterApi), NULL);
  sab.getWebServerManager().addApiRoutine("/sab/view/next", &(nextViewApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/view", &(viewByUIDApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/rtc/get/datetime", &(rtcGetTimeApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/rtc/set/datetime", &(rtcSetTimeApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/sdcard/size", &(sdCardSizeApi), &sab, WEBServerManager::GET);
  sdCardApiPacket.pSab = &sab;sdCardApiPacket.pView = &v1p;
  sab.getWebServerManager().addApiRoutine("/sab/sdcard/unmount", &(sdCardUnmountApi), &sdCardApiPacket, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/sdcard/mount", &(sdCardMountApi), &sdCardApiPacket, WEBServerManager::GET);
  
  sab.getWebServerManager().addApiRoutine("/esp/restart", &(espRestartApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/esp/reset", &(espResetApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/wifi/stainfo", &(staWifiInfoApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/systeminfo", &(systemInfoApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/power/info", &(powerInfoApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/io/get/level", &(ioGetLevelApi), vio.ioState, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/io/set/level", &(ioSetLevelApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/io/get/mode", &(ioGetModeApi), &sab, WEBServerManager::GET);
  sab.getWebServerManager().addApiRoutine("/sab/io/set/mode", &(ioSetModeApi), &sab, WEBServerManager::GET);

  sab.getIoManager().setISROnIOChange(&(ioISR), GPIO_3_RX);

  sab.getTaskSchedulerManager().addTask(1, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setEnabled(false), &(task1));
  sab.getTaskSchedulerManager().addTask(2, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setMillis(5000)->setEnabled(false), &(task2));
  sab.getTaskSchedulerManager().addTask(3, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setMillis(5000), &(task_blink), &sab);
  sab.getTaskSchedulerManager().addTask(4, TaskSchedulerManagerHelper::Schedule::scheduleBuilder()->setSeconds(10), &(task_batt_sensing), &v1p);
  
  Serial.println("End setup");
}

void loop() 
{
  
  if(millis() - currentMs >= 1000 || ioStateChange)
  {
    currentMs = millis();
    v1p.dateTime = sab.getRtcManager().getDateTime();
    v1p.nbViews = sab.getScreenManager().getViewCount();
    vap.ipAddr = sab.getConnectivityManager().softAPIP();
    vap.macAddr = sab.getConnectivityManager().softAPmacAddress();
    vap.nbOfCon = sab.getConnectivityManager().softAPgetStationNum();
    vstap.macAddr = sab.getConnectivityManager().macAddress();
    vstap.ipAddr = sab.getConnectivityManager().localIP();
    vstap.sigStrength = sab.getConnectivityManager().RSSI();

    sab.getIoManager().getPcf().digitalReadAll(vio.ioState);
    sab.getIoManager().getPcf().getPinModeAll(vio.ioMode);

    sab.getScreenManager().displayView();

    if(ioStateChange) Serial.println(F("ISR triggered"));
    ioStateChange = false;
  }
  
  if(digitalRead(GPIO_0) == 0 && millis() - buttonMs > 500)
  {
    buttonMs = millis();
    sab.getScreenManager().displayNextView();
    #ifdef DEBUG
    Serial.println("Changing view");
    Serial.print("Selected view is : ");Serial.println(sab.getScreenManager().getCurrentViewUID());
    #endif
  }

  //Run the webServer
  sab.getWebServerManager().runServer();
  sab.getTaskSchedulerManager().runTaskScheduler();
}

ICACHE_RAM_ATTR void ioISR()
{
  ioStateChange = true;
}
