#include <user_config.h>
#include <SmingCore/SmingCore.h>

#include "../include/configuration.h"
#include "webserver.h"

bool serverStarted = false;
HttpServer server;

extern float SensorT, SensorH, SensorHI, SensorCR;
extern String StrCF;
extern time_t NTPLastUpdate;

/*
 * Index page.
 * Show dht22 data as integer.
 */
void
onIndex (HttpRequest &request, HttpResponse &response)
{
  TemplateFileStream *tmpl = new TemplateFileStream ("index.html");
  auto &vars = tmpl->variables ();
  vars["T"] = String (SensorT, 0);
  vars["RH"] = String (SensorH, 0);
  vars["HI"] = String (SensorHI, 0);
  vars["CR"] = String (SensorCR, 0);
  vars["CF"] = StrCF; // это первое место, где оно используется
  vars["ADC"] = String (system_adc_read ());
  vars["VDD"] = String (system_get_vdd33 ());
  vars["LASTNTP"] = String (SystemClock.now () - NTPLastUpdate);
  response.sendTemplate (tmpl);
}

/*
 * Configuration page.
 */
void
onConfiguration (HttpRequest &request, HttpResponse &response)
{
  ClockConfig cfg = loadConfig ();
  if (request.getRequestMethod () == RequestMethod::POST)
    {
      // Update config
      if (request.getPostParameter ("SSID").length () > 0) // Network
        {
          cfg.NetworkSSID = request.getPostParameter ("SSID");
          cfg.NetworkPassword = request.getPostParameter ("Password");
        }

      if (request.getPostParameter ("TZ").length () > 0) // Correction
        {
          float tz = request.getPostParameter ("TZ").toFloat ();
          if (cfg.AddTZ != tz)
            {
              cfg.AddTZ = tz;
              SystemClock.setTimeZone (cfg.AddTZ);
              if (cfg.AddTZ < 0 || cfg.AddTZ > 23)
                {
                  cfg.AddTZ = 0;
                }
            }
        }

      if (request.getPostParameter ("BLow").length () > 0) // Low brightness level.
        {
          cfg.BrightnessLow = request.getPostParameter ("BLow").toInt ();
          if (cfg.BrightnessLow < 0 || cfg.BrightnessLow > 15)
            {
              cfg.BrightnessLow = 0;
            }
        }
      if (request.getPostParameter ("BMid").length () > 0) // Middle brightness level.
        {
          cfg.BrightnessMiddle = request.getPostParameter ("BMid").toInt ();
          if (cfg.BrightnessMiddle < 0 || cfg.BrightnessMiddle > 15)
            {
              cfg.BrightnessMiddle = 7;
            }
        }
      if (request.getPostParameter ("BHigh").length () > 0) // High brightness level.
        {
          cfg.BrightnessHigh = request.getPostParameter ("BHigh").toInt ();
          if (cfg.BrightnessHigh < 0 || cfg.BrightnessHigh > 15)
            {
              cfg.BrightnessHigh = 15;
            }
        }

      if (request.getPostParameter ("LLow").length () > 0) // Low light level trh.
        {
          cfg.LightTrhLow = request.getPostParameter ("LLow").toInt ();
          if (cfg.LightTrhLow < 0 || cfg.LightTrhLow > 1023)
            {
              cfg.LightTrhLow = 0;
            }
        }
      if (request.getPostParameter ("LHigh").length () > 0) // High light level trh.
        {
          cfg.LightTrhHigh = request.getPostParameter ("LHigh").toInt ();
          if (cfg.LightTrhHigh < 0 || cfg.LightTrhHigh > 1023)
            {
              cfg.LightTrhHigh = 1023;
            }
        }
      saveConfig (cfg);
      response.redirect ();
    }

  TemplateFileStream *tmpl = new TemplateFileStream ("config.html");
  auto &vars = tmpl->variables ();
  vars["SSID"] = cfg.NetworkSSID;
  vars["TZ"] = String (cfg.AddTZ, 2);
  vars["LLow"] = String (cfg.LightTrhLow);
  vars["LHigh"] = String (cfg.LightTrhHigh);
  vars["BLow"] = String (cfg.BrightnessLow);
  vars["BMid"] = String (cfg.BrightnessMiddle);
  vars["BHigh"] = String (cfg.BrightnessHigh);
  response.sendTemplate (tmpl);
}

/*
 * роутер
 */
void
onFile (HttpRequest &request, HttpResponse &response)
{
  String file = request.getPath ();
  if (file[0] == '/')
    file = file.substring (1);

  if (file[0] == '.')
    response.forbidden ();
  else
    {
      response.setCache (86400, true); // It's important to use cache for better performance.
      response.sendFile (file);
    }
}

/// API ///
/*
 * API page.
 */
void
onApiDoc (HttpRequest &request, HttpResponse &response)
{
  TemplateFileStream *tmpl = new TemplateFileStream ("api.html");
  auto &vars = tmpl->variables ();
  vars["IP"] = (
      WifiStation.isConnected () ?
          WifiStation.getIP () : WifiAccessPoint.getIP ()).toString ();
  response.sendTemplate (tmpl);
}

/*
 * Get json data
 * данные с датчиков выдаём с максимальным разрешением.
 */
void
onApiSensors (HttpRequest &request, HttpResponse &response)
{
  JsonObjectStream* stream = new JsonObjectStream ();
  JsonObject& json = stream->getRoot ();
  json["status"] = (bool) true;
  JsonObject& sensors = json.createNestedObject ("sensors");
  sensors["temperature"] = String (SensorT, 2);
  sensors["humidity"] = String (SensorH, 2);
  sensors["heatindex"] = String (SensorHI, 2);
  sensors["comfortp"] = String (SensorCR, 2);
  sensors["comforts"] = StrCF.c_str (); // второе место
  sensors["adcvalue"] = String (system_adc_read ());
  sensors["vddvalue"] = String (system_get_vdd33 ());
  time_t now = SystemClock.now ();
  sensors["datetime"] = String (now);
  sensors["lastntp"] = String (now - NTPLastUpdate);
  response.sendJsonObject (stream);
}

/*
 * Управление выводом. кандидат на удаление.
 */
#include "max7219.h"
void
onApiControl (HttpRequest &request, HttpResponse &response)
{
  int val = request.getQueryParameter ("bright", "-1").toInt ();
  if (val < 1)
    {
      val = 1;
    }
  if (val > 15)
    {
      val = 15;
    }

  MAX7219_writeData (MAX7219_MODE_INTENSITY, val);

  JsonObjectStream* stream = new JsonObjectStream ();
  JsonObject& json = stream->getRoot ();
  json["status"] = val;
  response.sendJsonObject (stream);
}

void
startWebServer ()
{
  if (serverStarted)
    return;

  server.listen (80);
  server.addPath ("/", onIndex);
  server.addPath ("/api", onApiDoc);
  server.addPath ("/api/sensors", onApiSensors);
  server.addPath ("/api/control", onApiControl);
  server.addPath ("/config", onConfiguration);
  server.setDefaultHandler (onFile);
  serverStarted = true;
  /*
   if (WifiStation.isEnabled())
   debugf("STA: %s", WifiStation.getIP().toString().c_str());
   if (WifiAccessPoint.isEnabled())
   debugf("AP: %s", WifiAccessPoint.getIP().toString().c_str());
   */
}
