//extern ESP8266WebServer httpServer;

static const char httpRoot[] PROGMEM =
  R"(<html><body>
  <h1><span id='devname'></span></h1>
  <h3>WiFi Thermostat</h3>
  
  <form id='minusBtnFrm'>
  <input type='hidden' name='minusBtn' value='1'>
  </form>
  <form id='plusBtnFrm'>
  <input type='hidden' name='plusBtn' value='1'>
  </form>
  <form id='modeBtnFrm'>
  <input type='hidden' name='modeBtn' value='1'>
  </form>
  <form id='onoffBtnFrm'>
  <input type='hidden' name='onoffBtn' value='1'>
  </form>  
  <span style="font-size:xx-large" id='setTemp'></span> &#8451;<br>
  <span id='mode'></span><br>
 <input type='button' onclick='return sendMinusBtn()' value='-'/>
  <input type='button' onclick='return sendPlusBtn()' value='+'/>
  <input type='button' onclick='return sendModeBtn()' value='MODE'/>
  <br>  
  <br>  
  <input id='btn_onoff' type='button' onclick='return sendOnOffBtn()' value=''/><br>
  <br>
  
  Current: <span id='temp'></span> &#8451;&nbsp;&nbsp;&nbsp;<span id='hum'></span> %<br>
  Heating <span id='heating'></span><br>
  <br>
  WiFi connected to <i><span id='ssid'></span></i>.<br>
  <h6>Last update 
  <span id='ut'></span> seconds ago. 
  <span id='status'></span>
  </h6>
  <br>
  <a href='/wifi.htm'>WiFi settings</a><br>
  <a href='/conf'>Base configuration</a><br>
  <a href='/conf2'>Extended configuration</a><br>
  <a href='/update'>Firmware update</a><br>
  <a href='/restart'>Restart</a>
  <script>
  function g(i) { return document.getElementById(i) };
  var xhttp, updateTime, reqTime, reqFin;
  var textA = 'OFF';
  var textE = 'ON';
  
  function sendMinusBtn() {
  var form = document.getElementById('minusBtnFrm');
  return transmit(form);
  }
  function sendPlusBtn() {
  var form = document.getElementById('plusBtnFrm');
  return transmit(form);
  }
  function sendModeBtn() {
  var form = document.getElementById('modeBtnFrm');
  return transmit(form);
  }
  function sendOnOffBtn() {
  var form = document.getElementById('onoffBtnFrm');
  return transmit(form);
  }
  
  function transmit(f) {
    if (!xhttp) { 
      g('status').innerHTML = 'loading...';
   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);
      if(data.devname != undefined) g('devname').innerHTML = data.devname;
          g('temp').innerHTML = data.temp.toFixed(1);
          g('hum').innerHTML = data.hum;
          g('setTemp').innerHTML = data.setTemp.toFixed(1);
          g('ssid').innerHTML = data.ssid;
            
          if(data.mode == '0') {
        g('btn_onoff').value = textA;
            g('mode').innerHTML = 'Heating OFF';
          }
          else if(data.mode == '1') {
        g('btn_onoff').value = textE;
            g('mode').innerHTML = 'Normal';
          }
          else if(data.mode == '2') {
        g('btn_onoff').value = textE;
            g('mode').innerHTML = 'Reduction';
          }
          
          if(data.heating == '1') g('heating').innerHTML = 'active';
          else if(data.heating == '0') g('heating').innerHTML = 'not active';

          xhttp = null;
          g('status').innerHTML = '';
          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>Base configuration</h3>
<a href='/'>Home</a><br><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><br>
HTTP User *: <input type='text' name='httpUser' id='httpUser'/><br>
HTTP Password *: <input type='text' name='httpPass' id='httpPass'/><br><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='text' name='mqttPass' id='mqttPass'/><br><br>
In Topic *: <input type='text' name='inTop' id='inTop'/><br>
Out Topic: <input type='text' name='outTop' id='outTop'/><br>
Out Retain *: <input type='checkbox' name='outRet' id='outRet'/><br><br>
LastWill Topic *: <input type='text' name='willTop' id='willTop'/><br>
LastWill Qos *: <select name='willQos' id='willQos'><option>0</option><option>1</option><option>2</option></select><br>
LastWill Retain *: <input type='checkbox' name='willRet' id='willRet'/><br>
LastWill Message *: <input type='text' name='willMsg' id='willMsg'/><br><br>
Domoticz Out Topic *: <input type='text' name='domOutTop' id='domOutTop'/><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 setCheckbox(ele, dat) {
    if(dat == 1) {
      ele.checked = true;
      ele.style.visibility = 'visible';
    }
    else {
      ele.checked = false;
      ele.style.visibility = 'visible';
    }
  }
  function updateCheckboxValue(ele) {
    if (ele.checked) ele.value ='1';
    else {
      ele.value = '0';
      ele.checked = true;
      ele.style.visibility = 'hidden';
    }
  }
  
  function transmit(f) {
    if (!xhttp) {   
    reqTime = 0;
    reqFin = false;
    updateCheckboxValue(g('outRet'));
    updateCheckboxValue(g('willRet'));    
    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;
        setCheckbox(g('outRet'), data.outRet);
        setCheckbox(g('willRet'), data.willRet);
        g('willMsg').value = data.willMsg;
        g('domOutTop').value = data.domOutTop;
        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>Extended configuration</h3>
<a href='/'>Home</a><br><br>
<input type='button' value='reload' onclick='return transmit()'/><br>
<form id='form1' onsubmit='return transmit(this)'>

<h4>Domoticz</h4>
Idx setTemp: <input type='number' name='domIdxTherm' id='domIdxTherm'/><br>
Idx mode: <input type='number' name='domIdxMode' id='domIdxMode'/><br>
Idx TempHum Sensor: <input type='number' name='domIdxTempHum' id='domIdxTempHum'/><br>
Idx PIR: <input type='number' name='domIdxPIR' id='domIdxPIR'/><br>

<h4>Outside Temp/Hum via MQTT</h4>
Temp In-Topic: <input type='text' name='outTempTop' id='outTempTop'/><br>
Hum In-Topic: <input type='text' name='outHumTop' id='outHumTop'/><br>

<h4>Auto-Save</h4>
setTemp: <input type='checkbox' name='autoSaveTemp' id='autoSaveTemp'/><br>
Mode: <input type='checkbox' name='autoSaveMode' id='autoSaveMode'/><br>

<h4>Thermostat / Heating</h4>
Min. Off-Time: <input type='number' name='minOffTime' id='minOffTime'/><br>
Min. Temp: <input type='text' name='tempMin' id='tempMin'/><br>
Max. Temp: <input type='text' name='tempMax' id='tempMax'/><br>
Reduction Mode Temp: <input type='text' name='tempLow' id='tempLow'/><br>
Hysteresis: <input type='text' name='hyst' id='hyst'/><br>
Temp Correction.: <input type='text' name='tempCorr' id='tempCorr'/><br>
Hum Correction: <input type='number' name='humCorr' id='humCorr'/><br>

<h4>Intervals / Timeouts</h4>
Measure Interval: <input type='number' name='measInt' id='measInt'/><br>
Display Interval: <input type='number' name='dispInt' id='dispInt'/><br>
Display Timeout: <input type='number' name='dispTout' id='dispTout'/><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 setCheckbox(ele, dat) {
    if(dat == 1) {
      ele.checked = true;
      ele.style.visibility = 'visible';
    }
    else {
      ele.checked = false;
      ele.style.visibility = 'visible';
    }
  }
  function updateCheckboxValue(ele) {
    if (ele.checked) ele.value ='1';
    else {
      ele.value = '0';
      ele.checked = true;
      ele.style.visibility = 'hidden';
    }
  }

  function transmit(f) {
    if (!xhttp) {
      updateCheckboxValue(g('autoSaveTemp'));
    updateCheckboxValue(g('autoSaveMode'));
      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);
          setCheckbox(g('autoSaveTemp'), data.autoSaveTemp);
          setCheckbox(g('autoSaveMode'), data.autoSaveMode);
          g('domIdxTherm').value = data.domIdxTherm;
          g('domIdxMode').value = data.domIdxMode;
          g('domIdxTempHum').value = data.domIdxTempHum;
          g('domIdxPIR').value = data.domIdxPIR;
          g('outTempTop').value = data.outTempTop;
          g('outHumTop').value = data.outHumTop;
          g('minOffTime').value = data.minOffTime;
          g('tempMin').value = data.tempMin;
          g('tempMax').value = data.tempMax;
          g('tempLow').value = data.tempLow;
          g('hyst').value = data.hyst;
          g('tempCorr').value = data.tempCorr;
          g('humCorr').value = data.humCorr;
          g('measInt').value = data.measInt;
          g('dispInt').value = data.dispInt;
          g('dispTout').value = data.dispTout;
          
          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 httpServerHandleNotFound() {
  //  if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
  //    if (!httpServer.authenticate(http_user, http_pass))
  //      return httpServer.requestAuthentication();
  httpServer.send(404, "text/plain", "");
  //}
}

void httpServerInit() {
  httpServer.on("/delconf", []() {
    Serial.println("httpServer.on /delconf");
    if (httpServer.hasArg("token")) {
      char buf[20];
      httpServer.arg("token").toCharArray(buf, 20);
      if (strcmp(buf, CLEARCONF_TOKEN) == 0) {
        //        httpServer.send(200, "text / plain", "Token OK - deleting config");
        deleteConfig();
      }
    } //if
    //    else {
    //      httpServer.send(200, "text / plain", "not allowed");
    //    }
  });

  httpServer.on("/api", []() {
    DEBUG_PRINT("httpServer.on /api");
    if (httpServer.hasArg("plusBtn")) {
      plusButtonAction();
      DEBUG_PRINT(P("web plusBtn"));
    } //if
    if (httpServer.hasArg("minusBtn")) {
      minusButtonAction();
      DEBUG_PRINT(P("web minusBtn"));
    } //if
    if (httpServer.hasArg("modeBtn")) {
      modeButtonAction();
      DEBUG_PRINT(P("web modeBtn"));
    } //if
    if (httpServer.hasArg("onoffBtn")) {
      modeButtonHoldAction();
      DEBUG_PRINT(P("web onoffBtn"));
    } //if

    //build json object of program data
    StaticJsonBuffer<200> jsonBuffer;
    JsonObject &json = jsonBuffer.createObject();
    json["devname"] = deviceName;
    json["ssid"] = WiFi.SSID();
    json["setTemp"] = setTemp;
    json["temp"] = temperature;
    json["hum"] = int(humidity);
    json["mode"] = heatingMode;
    json["heating"] = turnHeatingOn;

    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", []() {
    boolean sendData = false;
    if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
      if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
      sendData = true;
    }
    else sendData = true;
    if (sendData) {
      Serial.println("httpServer.on /confdata");

      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 (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");
      }
      yield();

      //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["outRet"] = mqtt_outRetain;
      json["willTop"] = mqtt_willTopic;
      json["willQos"] = mqtt_willQos;
      json["willRet"] = mqtt_willRetain;
      json["willMsg"] = mqtt_willMsg;
      json["domOutTop"] = domoticz_out_topic;

      yield();

      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", []() {
    boolean sendData = false;
    if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
      if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
      sendData = true;
    }
    else sendData = true;
    if (sendData) {
      Serial.println("httpServer.on /confdata2");

      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 (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");
      }
      yield();

      //build json object of program data
      StaticJsonBuffer<1000> jsonBuffer;
      JsonObject &json = jsonBuffer.createObject();

      json["domIdxTherm"] = domoticzIdx_Thermostat;
      json["domIdxMode"] = domoticzIdx_ThermostatMode;
      json["domIdxTempHum"] = domoticzIdx_TempHumSensor;
      json["domIdxPIR"] = domoticzIdx_PIR;
      json["outTempTop"] = outTemp_topic_in;
      json["outHumTop"] = outHum_topic_in;
      json["autoSaveTemp"] = autoSaveSetTemp;
      json["autoSaveMode"] = autoSaveHeatingMode;
      json["minOffTime"] = heatingMinOffTime;
      json["tempMin"] = setTempMin;
      json["tempMax"] = setTempMax;
      json["tempLow"] = setTempLow;
      json["hyst"] = hysteresis;
      json["tempCorr"] = tempCorrVal;
      json["humCorr"] = humCorrVal;
      json["measInt"] = measureInterval;
      json["dispInt"] = displayInterval;
      json["dispTout"] = displayTimeout;


      yield();

      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, []() {
    boolean sendData = false;
    if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
      if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
      sendData = true;
    }
    else sendData = true;
    if (sendData) {
      String json = " {";
      json += "\"wifissid\":\"" + WiFi.SSID() + "\"";
      json += "\"heap\":" + String(ESP.getFreeHeap());
      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();
}

