#include "Dtypes.h"
#include "MessageCodes.h"
#include "SwimTrackerConfig.h"

#include <ArduinoWebsockets.h>
#include <ArduinoJson.h>

class WifiManager;

class WifiAPI
{
public:
  WifiAPI(WifiManager &wifiManager)
      : wifiManager_(wifiManager), restartScheduled_(false)
  {
  }

  void onClientConnect(websockets::WebsocketsClient &client);
  bool handleMessage(websockets::WebsocketsClient &client, MessageCode code, const char *payload, size_t size);

  template <typename TServer>
  void iteration(TServer &server);

private:
  void sendWifiState(websockets::WebsocketsClient &client);

  template <typename TServer>
  void reportScanResultIfAvailable(TServer &server);

  WifiManager &wifiManager_;
  bool restartScheduled_;
};

template <typename TServer>
void WifiAPI::iteration(TServer &server)
{
  if (restartScheduled_)
  {
    LOG_INFO("Restart triggered by WifiAPI");
    ESP.restart();
  }
  reportScanResultIfAvailable(server);
}

template <typename TServer>
void WifiAPI::reportScanResultIfAvailable(TServer &server)
{
  auto numNetworks = WiFi.scanComplete();

  if (numNetworks >= 0)
  {
    DynamicJsonDocument response(192 * numNetworks);
    for (uint16_t i = 0; i < numNetworks; ++i)
    {
      JsonObject wifiObj = response.createNestedObject();
      wifiObj["ssid"] = WiFi.SSID(i);
      wifiObj["rssi"] = WiFi.RSSI(i);
      wifiObj["channel"] = WiFi.channel(i);

      switch (WiFi.encryptionType(i))
      {
      case WIFI_AUTH_OPEN:
        wifiObj["sec"] = "open";
        break;
      case WIFI_AUTH_WEP:
        wifiObj["sec"] = "WEP";
        break;
      case WIFI_AUTH_WPA_PSK:
        wifiObj["sec"] = "WPA_PSK";
        break;
      case WIFI_AUTH_WPA2_PSK:
        wifiObj["sec"] = "WPA2_PSK";
        break;
      case WIFI_AUTH_WPA_WPA2_PSK:
        wifiObj["sec"] = "WPA_WPA2_PSK";
        break;
      case WIFI_AUTH_WPA2_ENTERPRISE:
        wifiObj["sec"] = "WPA2_ENTP";
        break;
      default:
        wifiObj["sec"] = "?";
      }
    }
    server.sendToAll(MessageCode::WIFI_SCAN_RESPONSE, response);
    WiFi.scanDelete();
  }
}