#include <ESP8266WiFi.h>

// !!IMPORTANT!!
// You need to rename the file 'env.h.example' to 'env.h' otherwise this line will throw an error !!
// All user specific variables (like wifi password and ssid) are configured in that file !!

#include "env.h"

// helper vars
String header;
bool LEDstate = false;
volatile unsigned long oldTime = 0, debounceTime = 200;

// the HTML code for the whole ebinterface, can be called with http://<ip-adress>/
String webInterface = "<!DOCTYPE html>\n<html lang=\"de\">\n\n<head>\n\n<meta charset=\"utf-8\" />\n\n<title>Das Schmalter</title>\n\n<style>\n\t.test{\n\t\tmargin-left:auto;\n\t\tmargin-right:auto;\n\t}\n    h1{\n        text-align: center;\n    }\n\t.switch {\t\n  position: relative;\n  display: inline-block;\n  width: 120px;\n  height: 68px;\n}\n\n.switch input {\n  opacity: 0;\n  width: 0;\n  height: 0;\n}\n\n.slider {\n  position: absolute;\n  cursor: pointer;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  background-color: #ccc;\n  -webkit-transition: .4s;\n  transition: .4s;\n}\n\n.slider:before {\n  position: absolute;\n  content: \"\";\n  height: 52px;\n  width: 52px;\n  left: 8px;\n  bottom: 8px;\n  background-color: white;\n  -webkit-transition: .4s;\n  transition: .4s;\n}\n\ninput:checked + .slider {\n  background-color: #2196F3;\n}\n\ninput:focus + .slider {\n  box-shadow: 0 0 1px #2196F3;\n}\n\ninput:checked + .slider:before {\n  -webkit-transform: translateX(52px);\n  -ms-transform: translateX(52px);\n  transform: translateX(52px);\n}\n\n/* Rounded sliders */\n.slider.round {\n  border-radius: 34px;\n}\n\n.slider.round:before {\n  border-radius: 50%;\n}\n\t\n\tdiv{\n\ttext-align:center;\n\tcolor:red;\n\tfont-size: 150%;\n\tmargin-top: 40px;\n\t}\n\t\n</style>\n\n<script>\n\nvar currentState=\"\";\nvar ipAdress = window.location.host;\nfunction getState(){\n\tsendRequest(\"http://\"+ipAdress+\"/api/state\");\n}\n\nfunction requestFinished(){\n\tif(this.readyState === 4 && this.status === 200){\n\t\tif(this.responseText !== \"\"){\n\t\t\n\t\t\tresponseObj = JSON.parse(this.responseText);\n\t\t\t\n\t\t\tif(responseObj[\"command\"] == \"state\"){\n\t\t\t\t\n\t\t\t\tcurrentState = responseObj[\"response\"];\n\t\t\t\t\n\t\t\t\tif(currentState == 'OFF'){\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").classList.remove(\"disabled\");\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").checked = false;\n\t\t\t\n\t\t\t\t\tdocument.getElementById(\"errorDiv\").innerHTML = \"\";\n\t\t\t\t}\n\t\t\t\n\t\t\t\telse if(currentState == 'ON'){\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").classList.remove(\"disabled\");\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").checked = true;\n\t\t\t\n\t\t\t\t\tdocument.getElementById(\"errorDiv\").innerHTML = \"\";\n\t\t\t\t}\n\t\t\t\n\t\t\t\telse{\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").classList.add(\"disabled\");\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").innerHTML = \"ERROR\";\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"errorDiv\").innerHTML = \"Unkwon error while connecting to Das Schmalter\";\n\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t\tdocument.getElementById(\"errorDiv\").innerHTML = \"\";\n\t\t\n\t\t}\n\t}\n\telse if(this.readyState == 4){\n\t\tdocument.getElementById(\"errorDiv\").innerHTML = \"Error while connecting to Das Schmalter: \"+this.status\n\t}\n}\n\nfunction toggleLigth(){\n\tif(document.getElementById(\"toggleLightBt\").classList.contains(\"disabled\")){\n\t\treturn;\n\t}\n\tif(currentState == 'OFF'){\n\t\tsendRequest(\"http://\"+ipAdress+\"/api/on\")\n\t}\n\telse if(currentState == 'ON'){\n\t\tsendRequest(\"http://\"+ipAdress+\"/api/off\")\n\t}\n\telse{\n\t\talert(\"ERROR! \" + currentState);\n\t}\n\tgetState();\n}\nfunction sendRequest(link){\n    xmlhttp = new XMLHttpRequest();\n    xmlhttp.onreadystatechange = requestFinished;\n    xmlhttp.open(\"GET\", link, true);\n    xmlhttp.send();\n}\n\nsetInterval(function(){getState();},200)\n\n</script>\n\n</head>\n\n<body>\n\n<h1>Das Schmalter</h1>\n<div class=\"test\">\n<label class=\"switch\">\n  <input type=\"checkbox\" onclick=\"toggleLigth()\" id=\"toggleLightBt\" class=\"test\">\n  <span class=\"slider round\" class=\"test\"></span>\n</label>\n<div>\n\n<div id=\"errorDiv\"></div>\n\n</body>\n\n</html>";
// older version of the web interface, can be called with http://<ip-adress>/old
String oldWebInterface = "<!DOCTYPE html>\n<html lang=\"de\">\n\n<head>\n\n<meta charset=\"utf-8\" />\n\n<title>Das Schmalter</title>\n\n<style>\n\t\n    h1{\n        text-align: center;\n    }\n\t\n    button{\n\t\twidth: 40%;\n\t    height: 100px;\n\t\tdisplay: block;\n\t\tmargin-left: auto;\n\t\tmargin-right: auto;\n\t\tbackground-color: white;\n\t\tcolor:black;\n\t\tborder: 4px solid #4CAF50;\n\t\tborder-radius: 100px;\n\t\ttransition-duration: 0.8s;\n\t\tfont-size: 200%;\n    }\n    button:hover{\n        background-color:#4CAF50;\n        color:white;\n    }\n\t\n\t.disabled{\n\t\topacity: 0.6;\n\t\tcursor: not-allowed;\n\t}\n\t\n\tdiv{\n\ttext-align:center;\n\tcolor:red;\n\tfont-size: 200%;\n\tmargin-top: 40px;\n\t}\n\t\n</style>\n\n<script>\n\nvar currentState=\"\";\nvar ipAdress = window.location.host;\nfunction getState(){\n\tsendRequest(\"http://\"+ipAdress+\"/api/state\");\n}\n\nfunction requestFinished(){\n\tif(this.readyState === 4 && this.status === 200){\n\t\tif(this.responseText !== \"\"){\n\t\t\n\t\t\tresponseObj = JSON.parse(this.responseText);\n\t\t\t\n\t\t\tif(responseObj[\"command\"] == \"state\"){\n\t\t\t\t\n\t\t\t\tcurrentState = responseObj[\"response\"];\n\t\t\t\t\n\t\t\t\tif(currentState == 'OFF'){\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").classList.remove(\"disabled\");\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").innerHTML = \"Turn on\";\n\t\t\t\n\t\t\t\t\tdocument.getElementById(\"errorDiv\").innerHTML = \"\";\n\t\t\t\t}\n\t\t\t\n\t\t\t\telse if(currentState == 'ON'){\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").classList.remove(\"disabled\");\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").innerHTML = \"Turn off\";\n\t\t\t\n\t\t\t\t\tdocument.getElementById(\"errorDiv\").innerHTML = \"\";\n\t\t\t\t}\n\t\t\t\n\t\t\t\telse{\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").classList.add(\"disabled\");\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"toggleLightBt\").innerHTML = \"ERROR\";\n\t\t\t\t\t\n\t\t\t\t\tdocument.getElementById(\"errorDiv\").innerHTML = \"Unkwon error while connecting to Das Schmalter\";\n\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\n\t\t}\n\t}\n\telse if(this.readyState == 4){\n\t\tdocument.getElementById(\"toggleLightBt\").classList.add(\"disabled\");\n\t\tdocument.getElementById(\"errorDiv\").innerHTML = \"Error while connecting to Das Schmalter: \"+this.status\n\t}\n}\n\nfunction toggleLigth(){\n\tif(document.getElementById(\"toggleLightBt\").classList.contains(\"disabled\")){\n\t\treturn;\n\t}\n\tif(currentState == 'OFF'){\n\t\tsendRequest(\"http://\"+ipAdress+\"/api/on\")\n\t}\n\telse if(currentState == 'ON'){\n\t\tsendRequest(\"http://\"+ipAdress+\"/api/off\")\n\t}\n\telse{\n\t\talert(\"ERROR! \" + currentState);\n\t}\n\tgetState();\n}\nfunction sendRequest(link){\n    xmlhttp = new XMLHttpRequest();\n    xmlhttp.onreadystatechange = requestFinished;\n    xmlhttp.open(\"GET\", link, true);\n    xmlhttp.send();\n}\n\nsetInterval(function(){getState();},200)\n\n</script>\n\n</head>\n\n<body>\n\n<h1>Das Schmalter</h1>\n\n<div style=\"height:50px\"></div>\n\n<a><button id=\"toggleLightBt\" class=\"disabled\" onclick=\"toggleLigth()\">Turn on</button></a>\n\n<div id=\"errorDiv\"></div>\n\n</body>\n\n</html>";

// Set web server port number to 80
WiFiServer server(80);


void handleInterrupt() {
  // function to handle the external hardware switch
  
  if ((millis() - oldTime) > debounceTime) {
    if (digitalRead(button) == LOW) {
      LEDstate = ! LEDstate;
      digitalWrite(led, LEDstate);
    }
  }
  
  oldTime = millis();
}

void setup() {
  // configure all pins
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP);

  // attach an interrupt for the hardware switch
  attachInterrupt(digitalPinToInterrupt(button), handleInterrupt, FALLING);

  // start the serial monitor
  Serial.begin(9600);

#ifdef WIFI_MODE_MASTER
  // wifi mode master -> configure an access point
  Serial.print("Configuring access point...");

  WiFi.softAP(ssid, password);

  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
#endif

#ifdef WIFI_MODE_CLIENT
  // wifi mode client -> connect to given wifi network
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi..");
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("Connected to the WiFi network");
  Serial.println(WiFi.localIP());
#endif

  // start the web server
  server.begin();
}


void loop() {
  // check if a client has sent a request
  WiFiClient client = server.available();

  if (client) {
    // if a client has connected

    // string to hold incoming data from the client
    String currentLine = "";
    while (client.connected()) {
      // while the client is connected we're in this loop
      
      if (client.available()) {
        // if the client has sent some data
        
        // read id
        char c = client.read();
        header += c;
        
        if (c == '\n') {
          // if the data was a new line char
          if (currentLine.length() == 0) {
            // if the current line is empty -> client request (HTTP header) is over
            // => send response to client
            
            // send HTTP header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Access-Control-Allow-Origin: *");
            client.println("Connection: close");
            client.println();

            // check what the client wants ...
            if (header.indexOf("GET /api/on") >= 0) {
              // ... turn the lamp on
              
              LEDstate = true;
              digitalWrite(led, HIGH);
              client.println("{\"command\":\"on\",\"response\":\"OK\"}");
              
            } else if (header.indexOf("GET /api/off") >= 0) {
              // ... turn the lamp off
              
              LEDstate = false;
              digitalWrite(led, LOW);
              client.println("{\"command\":\"off\",\"response\":\"OK\"}");
              
            } else if (header.indexOf("GET /api/state") >= 0) {
              // ... get the state of the lamp
              
              if(LEDstate) {
                client.println("{\"command\":\"state\",\"response\":\"ON\"}");
              }
              else {
                client.println("{\"command\":\"state\",\"response\":\"OFF\"}");
              }
              
            } else if (header.indexOf("GET /old") >= 0) {
              // ... get the old HTML web page
              
              client.println(oldWebInterface);
            }
            else {
              // ... get the HTML web page
              
              client.println(webInterface);
            }

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
            
          } 
          else {
            // if we got a newline -> clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {
          // if the data was anything but a carriage return character -> add it to the end of the currentLine
          currentLine += c;
        }
      }
    }
    // Clear the header variable
    header = "";
    
    // Close the connection
    client.stop();
  }
}
