#include <SmingCore.h>
#include "configuration.h"

bool serverStarted = false;
HttpServer server;

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

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.sendNamedStream(tmpl);
}

void onConfiguration(HttpRequest& request, HttpResponse& response)
{
	ClockConfig cfg = loadConfig();
	if(request.method == HTTP_POST) {
		debugf("Update config");
		// Update config

		// Network
		if(request.getPostParameter("SSID").length() > 0) 
		{
			cfg.NetworkSSID = request.getPostParameter("SSID");
			cfg.NetworkPassword = request.getPostParameter("Password");
		}
		// Correction
		if(request.getPostParameter("TZ").length() > 0) {
			float tz = request.getPostParameter("TZ").toFloat();
			if (cfg.AddTZ != tz) {
				cfg.AddTZ = tz;
				if (cfg.AddTZ < 0 || cfg.AddTZ > 23) {
					cfg.AddTZ = 0;
				}
				SystemClock.setTimeZone(cfg.AddTZ);
			}
		}
		// Low brightness level.
		if (request.getPostParameter ("BLow").length () > 0) {
			cfg.BrightnessLow = request.getPostParameter ("BLow").toInt ();
			if (cfg.BrightnessLow < LedBrightMin || cfg.BrightnessLow > LedBrightMax) {
				cfg.BrightnessLow = LedBrightMin;
			}
		}
		// Middle brightness level.
		if (request.getPostParameter ("BMid").length () > 0) {
			cfg.BrightnessMiddle = request.getPostParameter ("BMid").toInt ();
			if (cfg.BrightnessMiddle < LedBrightMin || cfg.BrightnessMiddle > LedBrightMax) {
				cfg.BrightnessMiddle = LedBrightMiddl;
			}
		}
		// High brightness level.
		if (request.getPostParameter ("BHigh").length () > 0) {
			cfg.BrightnessHigh = request.getPostParameter ("BHigh").toInt ();
			if (cfg.BrightnessHigh < LedBrightMin || cfg.BrightnessHigh > LedBrightMax) {
				cfg.BrightnessHigh = LedBrightMax;
			}
		}
		// Low light level trh.
		if (request.getPostParameter ("LLow").length () > 0) {
			cfg.LightTrhLow = request.getPostParameter ("LLow").toInt ();
			if (cfg.LightTrhLow < MinLightThreshold || cfg.LightTrhLow > MaxLightThreshold) {
				cfg.LightTrhLow = MinLightThreshold;
			}
		}
		// High light level trh.
		if (request.getPostParameter ("LHigh").length () > 0) {
			cfg.LightTrhHigh = request.getPostParameter ("LHigh").toInt ();
			if (cfg.LightTrhHigh < MinLightThreshold || cfg.LightTrhHigh > MaxLightThreshold) {
				cfg.LightTrhHigh = MaxLightThreshold;
			}
		}

		saveConfig(cfg);
		response.headers[HTTP_HEADER_LOCATION] = "/";
	}

	debugf("Send template");
	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.sendNamedStream(tmpl);
}

/**
 * @brief Router
 */
void onFile(HttpRequest& request, HttpResponse& response)
{
	String file = request.uri.getRelativePath();

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

/// API ///

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.sendNamedStream(tmpl);
}

/**
 * @brief 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.sendDataStream(stream, MIME_JSON);
}

void startWebServer()
{
	if(serverStarted)
		return;

	server.listen(80);
	server.paths.set("/", onIndex);
	server.paths.set("/api", onApiDoc);
	server.paths.set("/api/sensors", onApiSensors);
	server.paths.set("/config", onConfiguration);
	server.paths.setDefault(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());
}
