/*
 * RBPXPLRTERM web server functions
 * 
 * uses WebServer library coming with ESP32 core
 * About the library: https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer
 */

#include "RBPXPLRTERM_webserver.h"

#include <WebServer.h>
#include "commands.h"
#include "actuator.h"
#include "printer.h"
#include "softwareInfo.h"
#include "loopScanner.h"
#include "leds.h"
#include "timeutils.h"
#include "textBuffer.h"

#ifdef ENA_WEBSERVER

/* *************************************************************
 * Web server
 */

#ifndef WEBSERVER_PORT
#error WEBSERVER_PORT not defined
#endif

WebServer webServer(WEBSERVER_PORT);

extern void webOnNetUp(int event, int param, String data) {
  SERIAL_PRINTF("webServer: handling NetUp event %d, parameter %d\n",event,param);
  setBlinkStep(BLE_CONN);
  beginServer();
}

extern void webOnNetDown(int event, int param, String data) {
  SERIAL_PRINTF("webServer: handling NetDown event %d, parameter %d\n",event,param);
  setBlinkStep(BLE_IDLE);
  endServer();
}

extern void initWebServer() {
  addEventHandler(EVT_NET_UP,   webOnNetUp,   0, "handleNetUpWebServer");
  addEventHandler(EVT_NET_DOWN, webOnNetDown, 0, "handleNetDownWebServer");
  addLoopScanner(20,webserverLoop,0,"webserverLoop");
}

//
// generate command key HTML markup to be included in page HTML code
//
String ckm(String cmd, String caption, String addParam) {
  if (addParam.length()>0) {
    return "<td><button onclick=\"window.location.href='/charCommand?charCmd="+cmd+"&"+addParam+"'\">"+caption+"</td>";
  } else {
    return "<td><button onclick=\"window.location.href='/charCommand?charCmd="+cmd+"'\">"+caption+"</td>";
  }
}

String getPage(boolean enableRefresh) {
  String page = "<html lang=en-EN><head>";
  if (enableRefresh) {
    page += "<meta http-equiv='refresh' content='60'/>";
  }
  page += "<title>RBPXPLRTERM WiFi Terminal</title>";
  page += "<style> body { background-color: #fffff; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }</style>";
  page += "</head><body><h1><a href='/'>RBPXPLRTERM WiFi Terminal</a></h1>";
  page += "<form action='/' method='POST'>";
  page += "<ul>";
  page += "<li><INPUT type='radio' name='LED' value='ON'>ON</li>";
  page += "<li><INPUT type='radio' name='LED' value='OFF'>OFF</li></ul>";
  page += "<INPUT type='submit' value='Set LED'>";
  page += "</form>";
  page += "<form action='/' method='POST'>";
  page += "<ul>";
  page += "<li><INPUT type='radio' name='relay' value='ON'>ON</li>";
  page += "<li><INPUT type='radio' name='relay' value='OFF'>OFF</li></ul>";
  page += "<INPUT type='submit' value='Set relay'>";
  page += "</form>";
  page += "<form action='/' method='POST'>";
  page += "<p>Text to print: <INPUT type='text' name='inputLine'>&nbsp;</INPUT><INPUT type='submit' value='Print'></p>";  
  page += "</form>";
  page += "<table>";
  page += "<tr><td>Microseconds since restart: </td><td>";
  char ms[20];
  snprintf(ms,20,"%lu",micros());
  page += ms;
  page += "</td></tr>";
  page += "</table>";
  page += "<table>";
  page += "<tr><td><button onclick=\"window.location.href='/charCommand?charCmd=1'\">Function A</td>";
  page +=     "<td><button onclick=\"window.location.href='/charCommand?charCmd=2'\">Function B</td>";
  page +=     "<td><button onclick=\"window.location.href='/charCommand?charCmd=3'\">Function C</td>";
  page +=     "<td><button onclick=\"window.location.href='/charCommand?charCmd=4'\">Function D</td></tr>";
  page += "</table>\n";
  page += "<hr/>\n";
  page += " loop microseconds: ";
  snprintf(ms,20,"%lu",getLoopMicros());
  page += ms;
  page += "<hr/>\n";
  page += "Software Version Info: ";
  page += "<pre>\n" + softwareInfo() + "\n</pre>";
  page += "<hr/>\n";
  page += "</body></html>";
  return page;
}

void handleSubmit() {
  if (webServer.hasArg("LED")) {
    String LEDValue;
    LEDValue = webServer.arg("LED");
    if ( LEDValue == "ON" ) {
      setLED(true);
      webServer.send ( 200, "text/html", getPage(false) );
    } else if ( LEDValue == "OFF" ) {
      setLED(false);
      webServer.send ( 200, "text/html", getPage(false) );
    } else {
      SERIAL_PRINTLN("Error Led Value");
      webServer.send( 404, "text/html", "<html><body><h1>Illegal LED Value</h1></body></html>" );
    }
  } else if (webServer.hasArg("relay")) {
    String relayValue;
    relayValue = webServer.arg("relay");
    if ( relayValue == "ON" ) {
      setRelay(true);
      webServer.send ( 200, "text/html", getPage(false));
    } else if ( relayValue == "OFF" ) {
      setRelay(false);
      webServer.send ( 200, "text/html", getPage(false) );
    } else {
      SERIAL_PRINTLN("Error relay Value");
      webServer.send( 404, "text/html", "<html><body><h1>Illegal relay value</h1></body></html>" );
    }
  } else if (webServer.hasArg("inputLine")) {
    String lineToPrint = webServer.arg("inputLine");
    SERIAL_PRINTLN("======= webServer/Print ==========");
    SERIAL_PRINTLN(lineToPrint);
    SERIAL_PRINTLN("==================================");
    printPrinterLine(lineToPrint);
    webServer.send ( 200, "text/html", getPage(false) );
    SERIAL_PRINTLN("======== response sent ===========");
    SERIAL_PRINTLN("==================================");
  }
}

void dumpWebServerInfo() {
  String message;
  message = getTimeString() + " ==== WEB REQUEST: \n URI: ";
  message += webServer.uri();
  message += "\nMethod: ";
  message += ( webServer.method() == HTTP_GET ) ? "GET" : "POST";
  message += "\nArguments: ";
  message += webServer.args();
  message += "\n";

  for ( uint8_t i = 0; i < webServer.args(); i++ ) {
    message += " " + webServer.argName ( i ) + ": " + webServer.arg ( i ) + "\n";
  } 
  SERIAL_PRINTLN(message);
}

void handleRoot() { 
  dumpWebServerInfo();
  if ( webServer.hasArg("relay") || webServer.hasArg("LED") || webServer.hasArg("colorCode") || webServer.hasArg("inputLine") ) {
    handleSubmit();
  } else {
    webServer.send ( 200, "text/html", getPage(true) );
  }  
}

void handleWebCharCommand() {
  dumpWebServerInfo();
  if (webServer.hasArg("charCmd")) {
    handleCharCommand(webServer.arg("charCmd").charAt(0));
  }
  webServer.send(200,"text/html", getPage(false));
}
    
void beginServer() {
  webServer.on ( "/", handleRoot );
  webServer.on ( "/charCommand", handleWebCharCommand );
  webServer.on("/inline",[](){
    SERIAL_PRINTLN("Inline handler for /inline");
    webServer.send(200, "text/plain", "hello port 80 /inline");
  });
  webServer.begin();
  SERIAL_PRINTLN( "HTTP webServer started" );
}

extern void endServer() {
  webServer.stop();
  SERIAL_PRINTLN("HTTP webServer ended");
}

// this is to be called each loop() to check if web requests are to be processed
extern void webserverLoop(int lparam) {
#ifdef ENA_WEBSERVER
  webServer.handleClient();
#endif  
}

#endif
