#include "ConnectivityManager.h"

//#define DEBUG_CONMAN

ConnectivityManager::ConnectivityManager(bool persistent)
{
  ConnectivityManager::persistent(persistent);
}

ConnectivityManager::ConnectivityManager(SDCardManager &sdCardManager, bool persistent) :  _sdCardManager(&sdCardManager)
{
  ConnectivityManager::persistent(persistent);
}

boolean ConnectivityManager::connect()
{
  if(!_sdCardManager) // ie _sdCardManager was not provided in contructor
  {
    if(!WiFi.disconnect(true))_error |= STA_ENABLED_DISABLE_ERR;
    if(!WiFi.softAPdisconnect(true))_error |= AP_ENABLED_DISABLE_ERR;
    if(!softAP("ESP8266SwissArmyBoard"))_error |= AP_SETUP_ERR;

    return _error == NO_ERROR;
  }
  else
  {
    return connectToSTA() && startAP();
  }
}

boolean ConnectivityManager::connectToSTA()
{
  //STATION PART
  CFGFileParser cfgFileParserSTA(*_sdCardManager, STA_CFG_FILE);
  CFGDictionary<CFGParameterValue> *cfgDictionary = (CFGDictionary<CFGParameterValue> *) cfgFileParserSTA.parseFile();
  
  const char *PSK(nullptr);
  uint8_t channel(0);
  boolean toBeReturned(true);
  if(!WiFi.disconnect(true))_error |= STA_ENABLED_DISABLE_ERR;
  
  if(cfgDictionary != nullptr)
  {
    if((*cfgDictionary)("ENABLED") != nullptr && (*cfgDictionary)("SSID") != nullptr)
    {
      if((*cfgDictionary)("ENABLED")->booleanValue())
      {
        if((*cfgDictionary)("PASSWORD") != nullptr)
          PSK = (*cfgDictionary)("PASSWORD")->stringValue();
        if((*cfgDictionary)("CHANNEL") != nullptr)
          channel = (*cfgDictionary)("CHANNEL")->intValue();
        if(!begin((*cfgDictionary)("SSID")->stringValue(), PSK, channel))
        {
          _error |= STA_SETUP_ERR;
          toBeReturned = false;
        }
      }
    }
    delete cfgDictionary;
  }
  return toBeReturned;
}

boolean ConnectivityManager::startAP()
{
  CFGFileParser cfgFileParser(*_sdCardManager, AP_CFG_FILE);
  CFGDictionary<CFGParameterValue> *cfgDictionary = (CFGDictionary<CFGParameterValue> *) cfgFileParser.parseFile();
  const char defaultSSID[] = "ESP8266SwissArmyBoard";
  const char *SSID(defaultSSID);
  const char *PSK(nullptr);
  uint8_t channel(1), maxConnection(4);
  boolean hideSSID(false);


  boolean toBeReturned(true);
  if(!WiFi.softAPdisconnect(true))_error |= AP_ENABLED_DISABLE_ERR;
  
  if(cfgDictionary == nullptr)
  {
    if(!softAP(defaultSSID))
    {
      _error |= AP_SETUP_ERR;
      toBeReturned = false;
    }
  }
  else
  {
    if((*cfgDictionary)("ENABLED") != nullptr)
    {
      if((*cfgDictionary)("ENABLED")->booleanValue())
      {
        if((*cfgDictionary)("SSID") != nullptr)
          SSID = (*cfgDictionary)("SSID")->stringValue();
        if((*cfgDictionary)("PASSWORD") != nullptr)
          PSK = (*cfgDictionary)("PASSWORD")->stringValue();
        if((*cfgDictionary)("CHANNEL") != nullptr)
          channel = (*cfgDictionary)("CHANNEL")->intValue();
        if((*cfgDictionary)("HIDE_SSID") != nullptr)
          hideSSID = (*cfgDictionary)("HIDE_SSID")->booleanValue();
        if((*cfgDictionary)("AP_MAX_CONNECTION") != nullptr)
          maxConnection = (*cfgDictionary)("AP_MAX_CONNECTION")->intValue();

        #ifdef DEBUG_CONMAN
        Serial.printf("AP is enabled, params are :\nSSID : %s\nPSK : %s\nCHAN : %u\nHIDE_SSID : %u\nMAX_CON : %u\n",
        SSID,
        PSK ? PSK : "",
        channel,
        hideSSID,
        maxConnection);
        #endif

        if(!softAP(SSID, PSK, channel, hideSSID, maxConnection))
        {
          _error |= AP_SETUP_ERR;
          toBeReturned = false;
        }
      }
      else
      {
        #ifdef DEBUG_CONMAN
        Serial.printf("AP is disabled, nothing to be done\n");
        #endif
      }
    }
    else //If the enable parameter is not specified we start the AP by default.
    {
      #ifdef DEBUG_CONMAN
      Serial.printf("ENABLED param missing, enabling AP\n");
      #endif
      if(!softAP(SSID, PSK, channel, hideSSID, maxConnection))
      {
        _error |= AP_SETUP_ERR;
        toBeReturned = false;
      }
    }
    delete cfgDictionary;
  }
  return toBeReturned;
}

boolean ConnectivityManager::enableSTAAndAP(boolean enabled)
{
  return enableSTA(enabled) && enableAP(enabled);
}

boolean ConnectivityManager::isSTAEnabled()
{
  return (getMode() == WIFI_AP_STA || getMode() == WIFI_STA);
}

boolean ConnectivityManager::isAPEnabled()
{
  return (getMode() == WIFI_AP_STA || getMode() == WIFI_AP);
}

unsigned char ConnectivityManager::RSSIPercent()
{
  int RSSIdBm = RSSI();
  return (RSSIdBm < MIN_RSSI) ? 0 : COEF_RSSI * ((double)RSSIdBm - (double)MIN_RSSI);
}

unsigned char ConnectivityManager::getError() const
{
  return _error;
}
