//extern ESP8266WebServer httpServer;

static const char httpRoot[] PROGMEM =
  R"(<html><body>
  <h1><span id='devname'></span></h1>
  <h3>WiFi Switch</h3>
  <form id='BtnFrm1'><input type='hidden' name='Btn1' value='1'></form>
  <form id='BtnFrm2'><input type='hidden' name='Btn2' value='1'></form>
  <form id='BtnFrm3'><input type='hidden' name='Btn3' value='1'></form>
  <div style='font-size:xx-large'>
  <div id='sw1div'>1: <input type='button' id='tbtn1' onclick='return sendBtn(1)'/><br></div>
  <div id='sw2div' style='display:none;'>2: <input type='button' id='tbtn2' onclick='return sendBtn(2)'/><br></div>
  <div id='sw3div' style='display:none'>3: <input type='button' id='tbtn3' onclick='return sendBtn(3)'/><br></div>
  </div>
  <br>  
  <br>
  WiFi verbunden mit <i><span id='ssid'></span></i>.<br>
  <h6>Letztes Update vor
  <span id='ut'></span> Sekunden.
  <span id='status'></span>
  </h6>
  <br>
  <a href='/wifi.htm'>WiFi-Einstellungen</a><br>
  <a href='/conf'>Basis-Einstellungen</a><br>
  <a href='/conf2'>Erweiterte Einstellungen</a><br>
  <a href='/update'>Firmware Update</a>
  <script>
  function g(i) { return document.getElementById(i) };
  var xhttp, updateTime, reqTime, reqFin;
  var textA = 'AUS';
  var textE = 'EIN';
  
  function sendBtn(btn) {
  var frmn='BtnFrm'+btn;
  var form = g(frmn);
  return transmit(form);
  }
  
  function transmit(f) {
    if (!xhttp) { 
      g('status').innerHTML = 'l&auml;dt...';
   reqTime = 0;
    reqFin = false;
      xhttp = new XMLHttpRequest();
      xhttp.timeout = 2000;
      xhttp.open('POST', 'api');
      xhttp.send(f ? (new FormData(f)) : '');
      xhttp.onreadystatechange = function () {
      if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status === 200) {
        var data = JSON.parse(xhttp.responseText);
        g('ssid').innerHTML = data.ssid;
        if(data.devname != undefined) g('devname').innerHTML = data.devname;
        if(data.swState2 != undefined) g('sw2div').style.display='inline';
        else g('sw2div').style.display='none';
        if(data.swState3 != undefined) g('sw3div').style.display='inline';
        else g('sw3div').style.display='none';
        if(data.swState1 == '1') g('tbtn1').value = textE;
        else g('tbtn1').value = textA;
        if(data.swState2 == '1') g('tbtn2').value = textE;
        else g('tbtn2').value = textA;
        if(data.swState3 == '1') g('tbtn3').value = textE;
        else g('tbtn3').value = textA;
        xhttp = null;
        updateTime = 0;
    reqFin = true;
        }
    else{
          if(!reqFin && reqTime > 10) {
          xhttp = null;
          reqFin = true;
          }
    }
      }
    }
    return false;
  }
  transmit();
  setInterval(function () { g('ut').innerHTML = ++updateTime; ++reqTime; }, 1000);
  setInterval(transmit, 5000);
</script>
</body></html>)";


static const char httpConfPage[] PROGMEM =
  R"(<html><head><body>
<h3>Configuration</h3>
<a href='/'>Home</a><br>
<input type='button' value='reload' onclick='return transmit()'/><br><br>
<form id='form1' onsubmit='return transmit(this)'>
Device Name: <input type='text' name='devName' id='devName'/><br>
HTTP User *: <input type='text' name='httpUser' id='httpUser'/><br>
HTTP Password *: <input type='password' name='httpPass' id='httpPass'/><br>
MQTT Server *: <input type='text' name='mqttHost' id='mqttHost'/><br>
MQTT Port *: <input type='number' name='mqttPort' id='mqttPort'/><br>
MQTT User *: <input type='text' name='mqttUser' id='mqttUser'/><br>
MQTT Password *: <input type='password' name='mqttPass' id='mqttPass'/><br>
In Topic *: <input type='text' name='inTop' id='inTop'/><br>
Out Topic: <input type='text' name='outTop' id='outTop'/><br>
LastWill Topic *: <input type='text' name='willTop' id='willTop'/><br>
LastWill Qos *: <input type='number' name='willQos' id='willQos'/><br>
LastWill Retain *: <input type='checkbox' name='willRet' id='willRet'/><br>
LastWill Message *: <input type='text' name='willMsg' id='willMsg'/><br>
Domoticz Out Topic *: <input type='text' name='domoOutTop' id='domoOutTop'/><br>
<br>
<input type='submit' value='Save'/>
</form>
<form id='restartForm' onsubmit='return res()'>
<input type='hidden' name='restart' value='1'>
<input type='submit' value='Restart'/>
</form>

<script>
 function g(i) { return document.getElementById(i) };
  var xhttp, reqTime, reqFin, rxhttp;
  
  function res() {
    rxhttp = new XMLHttpRequest();
 rxhttp.timeout = 1000;
  rxhttp.open('POST', 'restart');
  rxhttp.send('');
  rxhttp = null;
  return false;
  }

  function transmit(f) {
    if (!xhttp) {   
    reqTime = 0;
    reqFin = false;
    
    var wRet = g('willRet');
    if (wRet.checked) wRet.value ='1';
    else {
    wRet.value = '0';
    wRet.checked = true;
    wRet.style.visibility = 'hidden';
    }
    
      xhttp = new XMLHttpRequest();
    xhttp.timeout = 2000;
      xhttp.open('POST', 'confdata');
      xhttp.send(f ? (new FormData(f)) : '');
      xhttp.onreadystatechange = function () {
        if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status === 200) {
          var data = JSON.parse(xhttp.responseText);
          g('httpUser').value = data.httpUser;
          g('httpPass').value = data.httpPass;
      g('devName').value = data.devName
          g('mqttHost').value = data.mqttHost;
          g('mqttPort').value = data.mqttPort;
          g('mqttUser').value = data.mqttUser;
          g('mqttPass').value = data.mqttPass;
          g('inTop').value = data.inTop;
          g('outTop').value = data.outTop;
          g('willTop').value = data.willTop;
          g('willQos').value = data.willQos;
          
      if(data.willRet == 1) {
      wRet.checked = true;
      wRet.style.visibility = 'visible';
      }
      else {
      wRet.checked = false;
      wRet.style.visibility = 'visible';
      }
      
          g('willMsg').value = data.willMsg;
          g('domoOutTop').value = data.domoOutTop;
          xhttp = null;
      reqFin = true;
        }
    else{
          if(!reqFin && reqTime > 10) {
          xhttp = null;
          reqFin = true;
          }
    }
      }
    }
    return false;
  }
  transmit();
  setInterval(function () { ++reqTime; }, 1000);
</script>
</body></html>)";

static const char httpConf2Page[] PROGMEM =
  R"(<html><head><body>
<h3>Configuration 2</h3>
<a href='/'>Home</a><br>
<input type='button' value='reload' onclick='return transmit()'/><br><br>
<form id='form1' onsubmit='return transmit(this)'>
used Relais: <input type='number' name='usedRelais' id='usedRelais'/><br>
used Buttons: <input type='number' name='usedButtons' id='usedButtons'/><br>
Out Topic Hold 1: <input type='text' name='outTop_hold1' id='outTop_hold1'/><br>
Out Topic Hold 2: <input type='text' name='outTop_hold2' id='outTop_hold2'/><br>
Out Topic Hold 3: <input type='text' name='outTop_hold3' id='outTop_hold3'/><br>
Out Payload Hold 1: <input type='text' name='outPld_hold1' id='outPld_hold1'/><br>
Out Payload Hold 2: <input type='text' name='outPld_hold2' id='outPld_hold2'/><br>
Out Payload Hold 3: <input type='text' name='outPld_hold3' id='outPld_hold3'/><br>
Domoticz Idx 1: <input type='number' name='domoIdx1' id='domoIdx1'/><br>
Domoticz Idx 2: <input type='number' name='domoIdx2' id='domoIdx2'/><br>
Domoticz Idx 3: <input type='number' name='domoIdx3' id='domoIdx3'/><br>
Relais Impulse 1: <input type='number' name='impuls1' id='impuls1'/><br>
Relais Impulse 2: <input type='number' name='impuls2' id='impuls2'/><br>
Relais Impulse 3: <input type='number' name='impuls3' id='impuls3'/><br>
<br>
<input type='submit' value='Save'/>
</form>
<form id='rebootForm' onsubmit='return res()'>
<input type='submit' value='Restart'/>
</form>

<script>
 function g(i) { return document.getElementById(i) };
  var xhttp, reqTime, reqFin, rxhttp;
  
  function res() {
    rxhttp = new XMLHttpRequest();
 rxhttp.timeout = 1000;
  rxhttp.open('POST', 'restart');
  rxhttp.send('');
  rxhttp = null;
  return false;
  }

  function transmit(f) {
    if (!xhttp) {
      xhttp = new XMLHttpRequest();
    xhttp.timeout = 2000;
      xhttp.open('POST', 'confdata2');
      xhttp.send(f ? (new FormData(f)) : '');
      xhttp.onreadystatechange = function () {
        if (xhttp.readyState === XMLHttpRequest.DONE && xhttp.status === 200) {
          var data = JSON.parse(xhttp.responseText);
          g('usedRelais').value = data.usedRelais;
      g('usedButtons').value = data.usedButtons;
      g('outTop_hold1').value = data.outTop_hold1;
          g('outTop_hold2').value = data.outTop_hold2;
          g('outTop_hold3').value = data.outTop_hold3;
          g('outPld_hold1').value = data.outPld_hold1;
          g('outPld_hold2').value = data.outPld_hold2;
          g('outPld_hold3').value = data.outPld_hold3;
          g('domoIdx1').value = data.domoIdx1;
          g('domoIdx2').value = data.domoIdx2;
          g('domoIdx3').value = data.domoIdx3;
          g('impuls1').value = data.impuls1;
          g('impuls2').value = data.impuls2;
          g('impuls3').value = data.impuls3;
          xhttp = null;
      reqFin = false;
        }
      else {
          if(!reqFin && reqTime > 10) {
            xhttp = null;
            reqFin = true;
            }
      }
    }
    }
    return false;
  }
  transmit();
  setInterval(function () { ++reqTime; }, 1000);
</script>
</body></html>)";

void httpServerHandleRoot() {
  httpServer.send_P(200, "text/html", httpRoot);
}

void httpServerHandleConfPage() {
  httpServer.send_P(200, "text/html", httpConfPage);
}

void httpServerHandleConf2Page() {
  httpServer.send_P(200, "text/html", httpConf2Page);
}

void httpServerHandleNotFound() {
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += httpServer.uri();
  message += "\nMethod: ";
  message += (httpServer.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += httpServer.args();
  message += "\n";
  for (uint8_t i = 0; i < httpServer.args(); i++) {
    message += " " + httpServer.argName(i) + ": " + httpServer.arg(i) + "\n";
  }
  httpServer.send(404, "text/plain", message);
}


void httpServerInit() {  
  httpServer.on("/api", []() {
    //Serial.println("httpServer.on /api");
    if (httpServer.hasArg("Btn1")) {
      lastSwitchSource[0] = 2;
      relaisToggle(0);
      Serial.println("web Btn1");
    } //if
    if (httpServer.hasArg("Btn2")) {
      lastSwitchSource[1] = 2;
      relaisToggle(1);
      Serial.println("web Btn2");
    } //if
    if (httpServer.hasArg("Btn3")) {
      lastSwitchSource[2] = 2;
      relaisToggle(2);
      Serial.println("web Btn3");
    } //if

    //build json object of program data
    StaticJsonBuffer<200> jsonBuffer;
    JsonObject &json = jsonBuffer.createObject();
    json["ssid"] = WiFi.SSID();
    json["swState1"] = relais_state[0];
    if (usedRelaisCount > 1) json["swState2"] = relais_state[1];
    if (usedRelaisCount > 2) json["swState3"] = relais_state[2];
    json["devname"] = deviceName;

    char jsonchar[200];
    json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
    httpServer.send(200, "application/json", jsonchar);

  }); //httpServer.on /api

  httpServer.on("/restart", []() {
    Serial.println("web triggered restart");
    ESP.restart();
  });

  httpServer.on("/confdata", []() {
    Serial.println("httpServer.on /confdata");

    //    if (httpServer.hasArg("saveToFlash")) {
    //      if (httpServer.arg("saveToFlash").toInt() == 1) {
    //        Serial.println("web saveToFlash triggered");
    //        //saveConfig();
    //        saveConfigToFlash = true;
    //      }
    //    }
    //    else if (httpServer.hasArg("restart")) {
    //      if (httpServer.arg("restart").toInt() == 1) {
    //        Serial.println("web restart triggered");
    //        ESP.restart();
    //      }
    //    }
    //    else {
    for (int i = 0; i < httpServer.args(); i++) {
      char bufName[20];
      char bufValue[101];
      httpServer.argName(i).toCharArray(bufName, 20);
      httpServer.arg(i).toCharArray(bufValue, 101);

      //if(strcmp(bufName, "willRet") == 0) {
      //          willRetSet = true;
      //      }

      //if (strlen(bufName) > 0 && strlen(bufValue) > 0) {
      if (strlen(bufName) > 0) {
        Serial.print("web update ");
        Serial.print(bufName);
        Serial.print(" = ");
        Serial.println(bufValue);
        setConfig(bufName, bufValue);
      }
      saveConfigToFlash = true; // will be saved in next loop()
      Serial.println("web triggered saveConfigToFlash");
    }
    //    }

    //build json object of program data
    StaticJsonBuffer<1000> jsonBuffer;
    JsonObject &json = jsonBuffer.createObject();
    json["devName"] = deviceName;
    json["httpUser"] =  http_user;
    json["httpPass"] =  http_pass;
    json["mqttHost"] = mqtt_server;
    json["mqttPort"] = mqtt_port;
    json["mqttUser"] =  mqtt_user;
    json["mqttPass"] =  mqtt_pass;
    json["inTop"] = mqtt_topic_in;
    json["outTop"] = mqtt_topic_out;
    json["willTop"] = mqtt_willTopic;
    json["willQos"] = mqtt_willQos;
    json["willRet"] = mqtt_willRetain;
    json["willMsg"] = mqtt_willMsg;
    json["domoOutTop"] = domoticz_out_topic;

    char jsonchar[1000];
    json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
    httpServer.send(200, "application/json", jsonchar);

  }); //httpServer.on /confdata

  httpServer.on("/confdata2", []() {
    Serial.println("httpServer.on /confdata2");

    //    if (httpServer.hasArg("saveToFlash")) {
    //      if (httpServer.arg("saveToFlash").toInt() == 1) {
    //        Serial.println("web saveToFlash triggered");
    //        //saveConfig();
    //        saveConfigToFlash = true;
    //      }
    //    }
    //    else if (httpServer.hasArg("restart")) {
    //      if (httpServer.arg("restart").toInt() == 1) {
    //        Serial.println("web restart triggered");
    //        ESP.restart();
    //      }
    //    }
    //    else {
    for (int i = 0; i < httpServer.args(); i++) {
      char bufName[20];
      char bufValue[101];
      httpServer.argName(i).toCharArray(bufName, 20);
      httpServer.arg(i).toCharArray(bufValue, 101);

      //if(strcmp(bufName, "willRet") == 0) {
      //          willRetSet = true;
      //      }

      //if (strlen(bufName) > 0 && strlen(bufValue) > 0) {
      if (strlen(bufName) > 0) {
        Serial.print("web update ");
        Serial.print(bufName);
        Serial.print(" = ");
        Serial.println(bufValue);
        setConfig(bufName, bufValue);
      }
      saveConfig2ToFlash = true;
      Serial.println("web triggered saveConfig2ToFlash");
    }
    //    }

    //build json object of program data
    StaticJsonBuffer<1000> jsonBuffer;
    JsonObject &json = jsonBuffer.createObject();
    json["usedRelais"] = usedRelaisCount;
    json["usedButtons"] = usedButtonsCount;
    json["outTop_hold1"] = mqtt_topic_out_hold_1;
    json["outTop_hold2"] = mqtt_topic_out_hold_2;
    json["outTop_hold3"] = mqtt_topic_out_hold_3;
    json["outPld_hold1"] = mqtt_payload_out_hold_1;
    json["outPld_hold2"] = mqtt_payload_out_hold_2;
    json["outPld_hold3"] = mqtt_payload_out_hold_3;
    json["domoIdx1"] = domoticzIdx[0];
    json["domoIdx2"] = domoticzIdx[1];
    json["domoIdx3"] = domoticzIdx[2];
    json["impuls1"] = relais_impulse[0];
    json["impuls2"] = relais_impulse[1];
    json["impuls3"] = relais_impulse[2];
    char jsonchar[1000];
    json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
    httpServer.send(200, "application/json", jsonchar);

  }); //httpServer.on /confdata2


  //get heap status, analog input value and all GPIO statuses in one json call
  httpServer.on("/info", HTTP_GET, []() {
    String json = "{";
    json += "\"wifissid\":\"" + WiFi.SSID() + "\"";
    json += "\"heap\":" + String(ESP.getFreeHeap());
    //json += ", \"analog\":" + String(analogRead(A0));
    //json += ", \"gpio\":" + String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
    json += "}";
    httpServer.send(200, "text/json", json);
    json = String();
  }); //httpServer.on /info

  httpServer.on("/", []() {
    httpServerHandleRoot();
  });

  httpServer.on("/conf", []() {
    httpServerHandleConfPage();
  });

  httpServer.on("/conf2", []() {
    httpServerHandleConf2Page();
  });

  httpServer.onNotFound([]() {
    httpServerHandleNotFound();
  }); //httpServer.onNotFound

  // HTTP Updater at /update
  httpUpdater.setup(&httpServer);


  httpServer.begin();
}


