const solarMQTT = {
    getMQTT: function () {
        const id = Math.random().toString(36).substring(7);
        const topic = "#";
        const connection = "wss://mqtt.nas.el-wa.org:443"
        mqttsolarTreeDone = false;
        // const connection = "ws://username:password@37.97.203.138:8083" // Works
        // const connection = "wss://public:public@public.cloud.shiftr.io" // Works
        const client = mqtt.connect(connection, {
            rejectUnauthorized: false,
        });

        client.on("message", messageReceived);
        client.on("connect", function () {
            client.subscribe("solarManager/#");
            client.subscribe("wattpilot/properties/lmo/state");
            client.subscribe("wattpilot/properties/ftt/state");
            client.subscribe("wattpilot/properties/fte/state");
            client.subscribe("wattpilot/properties/amp/state");
            client.subscribe("wattpilot/properties/car/state");
            client.subscribe("go-eCharger/270003/amp");
            client.subscribe("go-eCharger/270003/ate");
            client.subscribe("go-eCharger/270003/lmo");
            client.subscribe("go-eCharger/270003/att");
            client.subscribe("go-eCharger/270003/car");
            client.subscribe("weatherStation/#");
        });
        client.on("error", function (error) {
            //alert("MQTT Error: " + error);
        });
        client.on('end', function () {
            setTimeout(getMQTT, 5000);
            alert("MQTT Disconnected, try to reconnect in 5 secs.");
        })

        function getNestedProp(obj, path) {
            return path.split('/').reduce((acc, key) => acc && acc[key], obj);
        }
        function setNestedProp(obj, path, value) {
            var schema = obj;  // a moving reference to internal objects within obj
            var pList = path.split('/');
            var len = pList.length;
            for (var i = 0; i < len - 1; i++) {
            var elem = pList[i];
            if (!schema[elem]) schema[elem] = {}
            schema = schema[elem];
            }

            schema[pList[len - 1]] = value;
        }

        function messageReceived(topic, message) {
          mqttData[topic] = message;
          if (topic == "solarManager/P_Load") {
            setTimeout(function () { solarSVG.updateValuesMQTT(mqttData) }, 200); //give the object tree some time to build up and receive all values
          }else if(topic == "weatherStation/windDeg"){
            setTimeout(function () { updateValuesWeather() }, 200); //give the object tree some time to build up and receive all values
          }
        }
    }
}

const solarSVG = {
    updateCnt: 99,
    fillElementArray: function () {
        
    },
    updateValuesMQTT: function (mqttData) {

        const angleFactor = 15000 / 288;
        const sixkWangleFactor = 6000 / 288;
        var cons = Number(mqttData["solarManager/P_Load"]);
        var pvn = JSON.parse(mqttData["solarManager/P_PVn"]);
        var pv = Number(mqttData["solarManager/P_PV"]);
        var pv2 = Number(pvn[1]);
        var pv1 = Number(pvn[0]);
        var pv3 = pv - (pv1 + pv2);
        var pbatt = Number(mqttData["solarManager/P_Akku"]);
        var limbatt = Number(mqttData["solarManager/crgMaxPct"]);
        var grid = Number(mqttData["solarManager/P_Grid"]);
        var soc = Number(mqttData["solarManager/SOC"]);
        var og = Number(mqttData["solarManager/og"]);
        var eg = Number(mqttData["solarManager/eg"]);
        var ug = Number(mqttData["solarManager/ug"]);
        var evsoc = Number(mqttData["solarManager/evSOC"]);
        var evlock = Number(mqttData["solarManager/evLock"]);
        var evMode = mqttData["solarManager/evMode"];
        var evPower = Number(mqttData["solarManager/evPower"]);
        var plugev = Number(mqttData["solarManager/evPlug"]);
        var fuelev = Number(mqttData["solarManager/evFuel"]);
        var heatOG = Number(mqttData["solarManager/heatOG"]);
        var heatEG = Number(mqttData["solarManager/heatEG"]);
        var puffO = Number(mqttData["solarManager/t_buffT"]);
        var puffM = Number(mqttData["solarManager/t_buffM"]);
        var puffU = Number(mqttData["solarManager/t_buffB"]);
        var heatMode = mqttData["solarManager/heatMode"];
        var carRemChrg = Number(mqttData["solarManager/carRemChrg"]);
        var aut = Number(mqttData["solarManager/autarky"]);
        var Pheat = Number(mqttData["solarManager/pHeat"]);
        var waterHeight = Number(mqttData["solarManager/waterHeight"]);
        var waterTemp = Number(mqttData["solarManager/waterTemp"]);
        var p_wr = Number(mqttData["solarManager/P_WR"]);
        var eff = Number(mqttData["solarManager/eff"]);
        var i_l1evu = Number(mqttData["solarManager/i_l1evu"]);
        var i_l2evu = Number(mqttData["solarManager/i_l2evu"]);
        var i_l3evu = Number(mqttData["solarManager/i_l3evu"]);
        var evPowerOG = Number(mqttData["solarManager/evPowerOG"]);
        var evPlugOG = Number(mqttData["solarManager/evPlugOG"]);
        var evModeOG = mqttData["solarManager/evModeOG"];

      
        var common = -cons - ug - eg + og ;
        if(common < 0){
          common = 0;
        }

        var htmlNode = document
        htmlNode.getElementById('consumerArc').setAttribute("d", describeArc(100, 100, 95, 0, Math.round(-cons / angleFactor)));

        htmlNode.getElementById("ogArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(-og / angleFactor)));
        htmlNode.getElementById("consumerText").innerHTML = powerToString(-cons);

        htmlNode.getElementById("consumerTextAllg").innerHTML = "Gemein: "+powerToString(common);

        if (evPower > 0) {
            htmlNode.getElementById("evCharge").style.display = "";
            if (carRemChrg > -1) {
                var today = new Date();
                today.setMinutes(today.getMinutes() + carRemChrg);
                var h = today.getHours();
                var m = today.getMinutes();
                if (h < 10)
                    h = "0" + h;
                if (m < 10)
                    m = "0" + m;
                htmlNode.getElementById("evRemText").innerHTML = h + ":" + m
            }
        } else {
            htmlNode.getElementById("evRemText").innerHTML = "";
        }
        htmlNode.getElementById("ogText").innerHTML = powerToString(-og);
        htmlNode.getElementById("egText").innerHTML = powerToString(eg);
        htmlNode.getElementById("ugText").innerHTML = powerToString(ug);
        htmlNode.getElementById("pvText").innerHTML = powerToString(pv);
        htmlNode.getElementById("pv1txt").innerHTML = powerToString(pv1);
        htmlNode.getElementById("pv2txt").innerHTML = powerToString(pv2);
        htmlNode.getElementById("pv3txt").innerHTML = powerToString(pv3);
        htmlNode.getElementById("il1txt").innerHTML = Math.round(i_l1evu * 10) / 10 + " A"
        htmlNode.getElementById("il2txt").innerHTML = Math.round(i_l2evu * 10) / 10 + " A"
        htmlNode.getElementById("il3txt").innerHTML = Math.round(i_l3evu * 10) / 10 + " A"
        htmlNode.getElementById("batText").innerHTML = powerToString(pbatt);
        htmlNode.getElementById("heatText").innerHTML = powerToString(Pheat);
        htmlNode.getElementById("evText").innerHTML = powerToString(evPower * 1000);
        htmlNode.getElementById("evTextOG").innerHTML = powerToString(evPowerOG * 1000);
        htmlNode.getElementById("genText").innerHTML = "Autarkie: " + Math.round(aut) + " %";
        htmlNode.getElementById("genInfoText").innerHTML = "Wirkungsgrad: " + Math.round(eff) + " %";// powerToString(p_wr);
        htmlNode.getElementById("gridText").innerHTML = powerToString(grid);
        htmlNode.getElementById("waterText").innerHTML = Math.round(waterHeight) / 10 + " cm"
        htmlNode.getElementById("waterTemp").innerHTML = (waterTemp).toPrecision(3) + " °C"
        htmlNode.getElementById("waterState").setAttribute("y", (100 - (waterHeight / 1500) * 100) + "%");

        for (i = 0; i < pvn.length; i++) {
            htmlNode.getElementById("det_pv" + i + "P").innerHTML = powerToString(pvn[i]);
        }

        tttext = ""
        var i = 0;
        while (mqttData["solarManager/inverters" + i]) {
            if (mqttData["solarManager/inverters" + i+"/error"] > 0) {
                tttext = tttext + '<tspan x="0" dy="1.2em">' + mqttData["solarManager/inverters" + i+"/name"] + ":</tspan>"
                tttext = tttext + '<tspan x="160">' + "--" + " °C</tspan>"
                tttext = tttext + '<tspan x="215">' + "-- W" + "</tspan>"
            } else {
                tttext = tttext + '<tspan x="0" dy="1.2em">' + mqttData["solarManager/inverters" + i+"/name"] + ":</tspan>"
                tttext = tttext + '<tspan x="160">' + Math.round(mqttData["solarManager/inverters" + i+"/temp"]) + " °C</tspan>"
                tttext = tttext + '<tspan x="215">' + powerToString(mqttData["solarManager/inverters" + i+"/p_AC"]) + "</tspan>"
            }
            i++;
        }

        htmlNode.getElementById("invList").innerHTML = tttext
        htmlNode.getElementById("egArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(eg / angleFactor)));
        htmlNode.getElementById("ugArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(ug / angleFactor)));
        htmlNode.getElementById("pvArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(pv1 / angleFactor)));
        htmlNode.getElementById("pv2Arc").setAttribute("d", describeArc(100, 100, 95, Math.round(pv1 / angleFactor), Math.round(pv1 / angleFactor) + Math.round(pv2 / angleFactor)));
        htmlNode.getElementById("pv3Arc").setAttribute("d", describeArc(100, 100, 95, Math.round(pv1 / angleFactor) + Math.round(pv2 / angleFactor), Math.round(pv1 / angleFactor) + Math.round(pv2 / angleFactor) + Math.round(pv3 / angleFactor)));

        if (pbatt < 0) {
            if (limbatt < 100) {
                htmlNode.getElementById("charge").style.display = "none";
                htmlNode.getElementById("batLim").style.display = "";
                htmlNode.getElementById("batLimText").innerHTML = Math.round(limbatt) + "%";
            } else {
                htmlNode.getElementById("charge").style.display = "";
                htmlNode.getElementById("batLim").style.display = "none";
            }
            htmlNode.getElementById("batArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(-pbatt / angleFactor)));
            htmlNode.getElementById("battani").setAttribute("class", "stream-rev");
            htmlNode.getElementById("battani").setAttribute("stroke-width", 55 * (1 - Math.exp(pbatt / 2000)));
        } else {
            htmlNode.getElementById("charge").style.display = "none";
            htmlNode.getElementById("batLim").style.display = "none";
            htmlNode.getElementById("batArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(pbatt / angleFactor)));
            htmlNode.getElementById("battani").setAttribute("class", "stream");
            htmlNode.getElementById("battani").setAttribute("stroke-width", 55 * (1 - Math.exp(-pbatt / 2000)));
        }
        htmlNode.getElementById("batChargeState").setAttribute("y", (100 - soc) + "%");
        //htmlNode.getElementById("heatChargeState").setAttribute("y", 100 - ((((puffO + puffM) / 2) - 30) * 1.66) + "%");
        htmlNode.getElementById('tmpH').setAttribute("stop-color", assignColor("#2389BA", "#BA3B23", 20, 80, puffO));
        htmlNode.getElementById('tmpM').setAttribute("stop-color", assignColor("#2389BA", "#BA3B23", 20, 80, puffM));
        htmlNode.getElementById('tmpL').setAttribute("stop-color", assignColor("#2389BA", "#BA3B23", 20, 80, puffU));
        htmlNode.getElementById("batSOC").innerHTML = soc + " %";
        htmlNode.getElementById("evArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(evPower * 2000 / angleFactor)));
        htmlNode.getElementById("evChargeState").setAttribute("y", (100 - evsoc) + "%");
        htmlNode.getElementById("evSOC").innerHTML = evsoc + " %";
        htmlNode.getElementById("evFuel").innerHTML = fuelev + " %";

        htmlNode.getElementById("heatArc").setAttribute("d", describeArc(100, 100, 95, 0, Math.round(Pheat / sixkWangleFactor)));
        htmlNode.getElementById("heatUp").innerHTML = Math.round(puffO * 10) / 10 + " °C";
        htmlNode.getElementById("heatDown").innerHTML = Math.round(puffM * 10) / 10 + " °C";

        if (evlock == false) {
            htmlNode.getElementById("evLock").style.display = "none";
        } else {
            htmlNode.getElementById("evLock").style.display = "";
        }
        if (heatMode == "eco") {
            htmlNode.getElementById("heatEco").style.display = "";
            htmlNode.getElementById("heatDefault").style.display = "none";
        } else {
            htmlNode.getElementById("heatEco").style.display = "none";
            htmlNode.getElementById("heatDefault").style.display = "";
        }
        if (evMode == "Eco") {
            htmlNode.getElementById("evEco").style.display = "";
            htmlNode.getElementById("evNextTrip").style.display = "none";
            htmlNode.getElementById("evDefault").style.display = "none";
        } else if (evMode == "Next Trip") {
            htmlNode.getElementById("evEco").style.display = "none";
            htmlNode.getElementById("evNextTrip").style.display = "";
            htmlNode.getElementById("evDefault").style.display = "none";
        } else {
            htmlNode.getElementById("evEco").style.display = "none";
            htmlNode.getElementById("evNextTrip").style.display = "none";
            htmlNode.getElementById("evDefault").style.display = "";
        }
        if (heatOG) {
            htmlNode.getElementById("heatOG").style.display = "";
        } else {
            htmlNode.getElementById("heatOG").style.display = "none";
        }
        if (heatEG) {
            htmlNode.getElementById("heatEG").style.display = "";
        } else {
            htmlNode.getElementById("heatEG").style.display = "none";
        }
        if (plugev != "no car") {
            htmlNode.getElementById("evPlug").style.display = "";
        } else {
            htmlNode.getElementById("evPlug").style.display = "none";
        }
        if (evModeOG == "Eco") {
            htmlNode.getElementById("evEcoOG").style.display = "";
            htmlNode.getElementById("evNextTripOG").style.display = "none";
            htmlNode.getElementById("evDefaultOG").style.display = "none";
        } else if (evModeOG == "Next Trip") {
            htmlNode.getElementById("evEcoOG").style.display = "none";
            htmlNode.getElementById("evNextTripOG").style.display = "";
            htmlNode.getElementById("evDefaultOG").style.display = "none";
        } else {
            htmlNode.getElementById("evEcoOG").style.display = "none";
            htmlNode.getElementById("evNextTripOG").style.display = "none";
            htmlNode.getElementById("evDefaultOG").style.display = "";
        }
        if (evPlugOG > 0) {
            htmlNode.getElementById("evPlugOG").style.display = "";
        } else {
            htmlNode.getElementById("evPlugOG").style.display = "none";
        }
        if (grid < 0) {
            htmlNode.getElementById("gridArc").setAttribute("d", describeArc(100, 100, 95, 0, -grid / angleFactor));
            htmlNode.getElementById("consGridani").setAttribute("class", "stream-rev");
            htmlNode.getElementById("consGridani").setAttribute("stroke-width", 55 * (1 - Math.exp(grid / 2000)));
        } else {
            htmlNode.getElementById("gridArc").setAttribute("d", describeArc(100, 100, 95, 0, grid / angleFactor));
            htmlNode.getElementById("consGridani").setAttribute("class", "stream");
            htmlNode.getElementById("consGridani").setAttribute("stroke-width", 55 * (1 - Math.exp(-grid / 2000)));
        }

        htmlNode.getElementById("consEVani").setAttribute("stroke-width", 55 * (1 - Math.exp(-evPower)));
        htmlNode.getElementById("consEVOGani").setAttribute("stroke-width", 55 * (1 - Math.exp(-evPowerOG)));
        htmlNode.getElementById("consOGani").setAttribute("stroke-width", 55 * (1 - Math.exp(og / 2000)));

        htmlNode.getElementById("consUGani").setAttribute("stroke-width", 55 * (1 - Math.exp( -ug / 2000)));

        htmlNode.getElementById("consHeatAni").setAttribute("stroke-width", 55 * (1 - Math.exp(-Pheat / 2000)));
        htmlNode.getElementById("consAni").setAttribute("stroke-width", 55 * (1 - Math.exp(cons / 2000)));
        htmlNode.getElementById("consEGani").setAttribute("stroke-width", 55 * (1 - Math.exp(-eg / 2000)));
        htmlNode.getElementById("pvani").setAttribute("stroke-width", 55 * (1 - Math.exp(-pv / 2000)));
        htmlNode.getElementById("pvani");
    }

}

var chartSettings = {
    type: 'line',
    options: {
      animation: true,
      plugins: {
        annotation: {
          common: { type: 'box', drawTime: 'beforeDatasetsDraw', yScaleID: 'y-axis-0', backgroundColor: 'rgba(255, 255, 255, 0.05)', init: true },
          annotations: []
        },
        tooltip: {
          position: 'nearest',
          pointStyle: "circle",
          boxWidth: 4,
          usePointStyle: true,
          callbacks: {
            footer: function (tooltipItems){return ""},
          },
        },
        legend: {
          position: "bottom",
          labels: {
            pointStyleWidth: 10,
            usePointStyle: true,
            pointStyle: "line",
          }
        },
      },
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        intersect: false,
        mode: 'index',
      },
      scales: {
        x: {
          adapters: {
            date: {
              locale: "DE-de"
            }
          },
          ticks: {

          },
          type: 'timestack',
        },
        y: {
          stacked: true,
          display: true,
          min: 0,
          position: 'left',
          ticks: {
            callback: value => `${value / 1000} kW`,
          },
          /*title: {
            display: true,
            text: "Leistung"
          }*/
        },
        y1: {
          stacked: false,
          display: true,
          position: 'right',
          min: 0,
          max: 100,
          ticks: {
            callback: value => `${value} %`,
          },
          /*title: {
            display: true,
            text: "Ladestand"
          },*/
          data:{}
        }
      }
    }
  };

  var forecastChartSettings = {
    type: 'bar',
    options: {
      animation: true,
      plugins: {
        tooltip: {
          position: 'nearest',
          pointStyle: "circle",
          boxWidth: 4,
          usePointStyle: true,
          callbacks: {
            footer: function (tooltipItems){return ""},
          },
        },
        legend: {
          position: "bottom",
          labels: {
            pointStyleWidth: 10,
            usePointStyle: true,
            pointStyle: "line",
          }
        },
      },
      responsive: true,
      maintainAspectRatio: false,
      interaction: {
        intersect: false,
        mode: 'index',
      },
      scales: {
        x: {
          adapters: {
            date: {
              locale: "DE-de"
            }
          },
          ticks: {
          },
          type: 'timestack',
          timestack:{
            right_floating_tick_thres: 0.3,
            format_style: {month: 'long'},
          }
        },
        y: {
          stacked: false,
          display: true,
          position: 'left',
          ticks: {
            callback: value => `${value / 1000} kW`,
          },
          /*title: {
            display: true,
            text: "Leistung"
          }*/
        },
      }
    }
  };

  var modalEV = new bootstrap.Modal(document.getElementById('modalEV'), {
    keyboard: false
  });
  var chartData = {};
  var mqttData = {};
  var timeFrom = -24;
  var timeTo = 12;
  const consChart = new Chart(
    document.querySelector('#consumption-chart'),
    Object.assign({}, chartSettings)
  );
  const prodChart = new Chart(
    document.querySelector('#production-chart'),
    Object.assign({}, chartSettings)
  );

  const foreChart = new Chart(
    document.querySelector('#forecast-chart'),
    Object.assign({}, forecastChartSettings)
  );

  function updateCharts(){
    getData(consChart, 'ajax/getConsData.php',true,false,false);
    getData(prodChart, 'ajax/getProdData.php',true,false,false);
  }

  function prevDay(){
    timeFrom -= 24;
    timeTo -= 24;

    var now = new Date();
    now.setDate(now.getDate()+1+(timeFrom/24));
    var day = ("0" + now.getDate()).slice(-2);
    var month = ("0" + (now.getMonth() + 1)).slice(-2);
    var selected = now.getFullYear()+"-"+(month)+"-"+(day);
    document.getElementById("DatePickerCons").value = selected;
    document.getElementById("DatePickerProd").value = selected;
    updateCharts();
  }

  function changeDay(e){
    const date1 = new Date(e.target.value);
    const date2 = new Date();
    const difference = Math.floor((date1.getTime() - date2.getTime()) / (1000*60*60*24)) *24;
    timeFrom = difference;
    timeTo = difference+36;   
    updateCharts();
      //.then((ret) => enableEvents());
  }
  
  function nextDay(){
    timeFrom += 24;
    timeTo += 24;
    var now = new Date();
    now.setDate(now.getDate()+1+(timeFrom/24));
    var day = ("0" + now.getDate()).slice(-2);
    var month = ("0" + (now.getMonth() + 1)).slice(-2);
    var selected = now.getFullYear()+"-"+(month)+"-"+(day);
    document.getElementById("DatePickerCons").value = selected;
    document.getElementById("DatePickerProd").value = selected;
    updateCharts();
  }

  document.addEventListener('readystatechange', function () {
    if (event.target.readyState === "complete") {
      solarMQTT.getMQTT();
      getData(consChart, 'ajax/getConsData.php');
      getData(prodChart, 'ajax/getProdData.php');
      getData(foreChart,'ajax/getForecastData.php', false);
      getStats("Stats-Year","ajax/getStats.php?type=ThisYear");
      solarSVG.fillElementArray();
      this.getElementById("meteogram").innerHTML = "<iframe src='"+meteogramURL+"' frameborder='0' scrolling=NO' allowtransparency='true' sandbox='allow-same-origin allow-scripts allow-popups allow-popups-to-escape-sandbox' style='width: 100%;height: 500px;border: 0;overflow: hidden;'></iframe><!-- DO NOT REMOVE THIS LINK --><a href='https://www.meteoblue.com/de/wetter/woche/index' target='_blank' rel='noopener'></a>";
    }
  });

  String.prototype.toHHMM = function () {
    var sec_num = parseInt(this, 10); // don't forget the second param
    var hours = Math.floor(sec_num / 3600);
    var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
    //var seconds = sec_num - (hours * 3600) - (minutes * 60);

    if (hours < 10) { hours = "0" + hours; }
    if (minutes < 10) { minutes = "0" + minutes; }
    return hours + ':' + minutes;
  }

  function loadingHTML(msg) {
    return "<div class='m-4'><div class='spinner-border' role='status'><span class='visually-hidden'>Loading...</span></div>&nbsp;&nbsp;&nbsp;" + msg + "</div>"
  }

  function openModal(type) {
    switch(type){
      case "CarEG":
        document.getElementById("modal-title").innerHTML = "Autoladung EG";
        contentURL = "ajax/carEG.php";
        break;
      case "CarOG":
        document.getElementById("modal-title").innerHTML = "Autoladung OG";
        contentURL = "ajax/carOG.php";
        break;
      case "heater":
        document.getElementById("modal-title").innerHTML = "Steuerung Heizstab";
        contentURL = "ajax/heater.php";
        break;
      default:
        document.getElementById("modal-title").innerHTML = "Fehler";
        contentURL = "";
        break;
    }
    
    modalBodyElement = document.getElementById('modal-body');
    modalBodyElement.innerHTML = loadingHTML("Wird geladen...");
    document.getElementById("modalSaveBtn").addEventListener("click", submitFormAjax);
    document.getElementById("modalSaveBtn").contentURL = contentURL;
    modalEV.show();
    fetch(contentURL, {
      method: 'GET',
      headers: {
        'X-Requested-From-Modal': 'a',
        'Requested-With-Ajax': 'ajax'
      }
    })
      .then(response => response.text())
      .then(html => {
        modalBodyElement.innerHTML = html;
        
        var slider = document.getElementById("modal-slider");
        var span = document.getElementById("modal-slider-label");
        switch(type){
          case "CarEG":
            slider.oninput = function () {
              marginValue = parseInt(this.value);
              slider.style.setProperty("--background-size", `${marginValue}%`);
              if (marginValue < 10) {
                marginValue = marginValue - 0.4 * marginValue;
              } else if (marginValue < 85) {
                marginValue = marginValue - 4;
              }
              else {
                marginValue = marginValue - 4 - 0.5 * (marginValue - 85);
              }
              span.setAttribute('style', 'margin-left:' + marginValue + '%;');
              span.innerHTML = this.value + "%";
            }
            document.getElementById("evStart/Stop").addEventListener("click", submitFormAjax);
            document.getElementById("evStart/Stop").contentURL = contentURL;
            mode = new TextDecoder().decode(mqttData["wattpilot/properties/lmo/state"]);
            time = String(mqttData["wattpilot/properties/ftt/state"]);
            energy = mqttData["wattpilot/properties/fte/state"];
            amp = new TextDecoder().decode(mqttData["wattpilot/properties/amp/state"]);
            car = new TextDecoder().decode(mqttData["wattpilot/properties/car/state"]);
            charge = Number(mqttData["solarManager/p_l1ev"])+Number(mqttData["solarManager/p_l2ev"])+Number(mqttData["solarManager/p_l3ev"])
            if (charge < 0.2) { document.getElementById("evStart/Stop").innerHTML = 'Laden starten' }
            else { document.getElementById("evStart/Stop").innerHTML = 'Laden stoppen' }
            if (mode == "Awattar") { document.getElementById("EV_Eco").click(); }
            else if (mode == "Default") { document.getElementById("EV_Default").click(); }
            else if (mode == "AutomaticStop") { document.getElementById("EV_NextTrip").click(); }
            else { alert(mode); }
            document.getElementById("EV_NextTripTime").value = time.toHHMM();
            document.getElementById("modal-slider").value = Math.round(energy * 100 / 14000);
            document.getElementById("modal-slider").dispatchEvent(new Event('input'));
            if (amp == "16") { document.getElementById("EV_16A").click(); }
            else if (amp == "10") { document.getElementById("EV_10A").click(); }
            else if (amp == "6") { document.getElementById("EV_6A").click(); }
            break;
          case "CarOG":
            slider.oninput = function () {
              marginValue = parseInt((this.value-this.min)*100/this.max);
              slider.style.setProperty("--background-size", `${marginValue}%`);
              if (marginValue < 10) {
                marginValue = marginValue - 0.4 * marginValue;
              } else if (marginValue < 85) {
                marginValue = marginValue - 4;
              }
              else {
                marginValue = marginValue - 4 - 0.5 * (marginValue - 85);
              }
              span.setAttribute('style', 'margin-left:' + marginValue + '%;');
              span.innerHTML = this.value + "%";
            }
            document.getElementById("evStart/Stop").addEventListener("click", submitFormAjax);
            document.getElementById("evStart/Stop").contentURL = contentURL;
            mode = mqttData["go-eCharger/270003/lmo"];
            time = String(mqttData["go-eCharger/270003/att"]);
            energy = mqttData["go-eCharger/270003/ate"];
            amp = mqttData["go-eCharger/270003/amp"];
            car = mqttData["go-eCharger/270003/car"];
            if (car != "2") { document.getElementById("evStart/Stop").innerHTML = 'Laden starten' }
            else { document.getElementById("evStart/Stop").innerHTML = 'Laden stoppen' }
            if (mode == "4") { document.getElementById("EV_Eco").click(); }
            else if (mode == "3") { document.getElementById("EV_Default").click(); }
            else if (mode == "5") { document.getElementById("EV_NextTrip").click(); }
            else { alert(mode); }
            document.getElementById("EV_NextTripTime").value = time.toHHMM();
            document.getElementById("modal-slider").value = Math.round(energy * 100 / 14000);
            document.getElementById("modal-slider").dispatchEvent(new Event('input'));
            if (amp == "16") { document.getElementById("EV_16A").click(); }
            else if (amp == "10") { document.getElementById("EV_10A").click(); }
            else if (amp == "6") { document.getElementById("EV_6A").click(); }
            break;
            case "heater":
              slider.oninput = function () {
                marginValue = parseInt((this.value-this.min)*100/this.max);
                slider.style.setProperty("--background-size", `${marginValue}%`);
                if (marginValue < 10) {
                  marginValue = marginValue - 0.4 * marginValue;
                } else if (marginValue < 85) {
                  marginValue = marginValue - 4;
                }
                else {
                  marginValue = marginValue - 4 - 0.5 * (marginValue - 85);
                }
                span.setAttribute('style', 'margin-left:' + marginValue + '%;');
                if(this.value == 0){
                  span.innerHTML = "Automatik";
                }else{
                  span.innerHTML = (this.value/10) + " kW";
                }
              }
              if(mqttData["solarManager/heatMode"] == "eco"){
                document.getElementById("modal-slider").value = 0;
              }else{
                document.getElementById("modal-slider").value = Math.round(mqttData["solarManager/pHeat"]/100);
              }
              document.getElementById("modal-slider").dispatchEvent(new Event('input'));
              break;
        }

      })
      .catch(error => {
        modalBodyElement.innerHTML = error.message;
      });
  }

  function submitFormAjax(event) {
    let xmlhttp = window.XMLHttpRequest ?
      new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");

    xmlhttp.onreadystatechange = function () {
      if (this.readyState === 4 && this.status === 200)
        modalEV.hide();
    }
    const form = document.getElementById('modalEV').querySelector('form');
    post = "";
    // ✅ Get interesting form elements
    if (event.currentTarget.id == "evStart/Stop") {
      post = "evStart/Stop=" + event.currentTarget.innerHTML;
    } else {
      const formElements = Array.from(form.elements);
      for (let i = 0; i < formElements.length; i++) {
        if(formElements[i].name){
          if (formElements[i].type == "radio" && formElements[i].checked) {
            post += formElements[i].name + "=" + encodeURIComponent(formElements[i].value) + "&";
          } else if(formElements[i].type == "checkbox" && formElements[i].checked){
            post += formElements[i].name + "=" + encodeURIComponent(formElements[i].value) + "&";
          } else if(formElements[i].type == "button" && !formElements[i].classList.contains("accordion-button")){
            post += formElements[i].name + "=" + encodeURIComponent(formElements[i].innerHTML) + "&";
          }else if(formElements[i].type != "checkbox" && formElements[i].type != "radio") {
            post += formElements[i].name + "=" + encodeURIComponent(formElements[i].value) + "&";
          }
        }
      }
    }
    xmlhttp.open("POST", event.currentTarget.contentURL, true);
    xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    document.getElementById('modalEV').querySelector('.modal-body').innerHTML = loadingHTML("Änderungen werden übernommen...");
    xmlhttp.send(post);
    return false;
  }

  async function getData(chrt, url, sunrise=true, autoUpdate=true, animation=true) {
    try {
      chrt.options.events = [];
      console.log("fetching "+url+"?FROM="+timeFrom+"&TO="+timeTo);
      const response = await fetch(url+"?FROM="+timeFrom+"&TO="+timeTo);
      if (!response.ok) {
        console.log("err");
        throw new Error(`Response status: ${response.status}`);
      }

      chrt.data = await response.json();
      if(sunrise){
        const response2 = await fetch("ajax/getSunrise.php?FROM="+timeFrom+"&TO="+timeTo);
        if (!response2.ok) {
          console.log("err");
          throw new Error(`Response status: ${response2.status}`);
        }
        chrt.options.plugins.annotation.annotations = await response2.json();
      }
      chrt.options.events = ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'];
      if(animation)
        chrt.update();
      else
        chrt.update("none");
    } catch (error) {
      console.log(error.message);
    }
    if(autoUpdate){
      setTimeout(function () { getData(chrt, url, sunrise,autoUpdate,animation) }, 5 * 60 * 1000); //renew data every 5 min.
    } 
  }

  async function getDataOnly(chart, url, sunrise=true, autoUpdate=true, animation=true) {

    try {
      console.log("fetching "+url+"?FROM="+timeFrom+"&TO="+timeTo);
      const response = await fetch(url+"?FROM="+timeFrom+"&TO="+timeTo);
      if (!response.ok) {
        console.log("err");
        throw new Error(`Response status: ${response.status}`);
      }

      chart.data = await response.json();
      if(sunrise){
        const response2 = await fetch("ajax/getSunrise.php?FROM="+timeFrom+"&TO="+timeTo);
        if (!response2.ok) {
          console.log("err");
          throw new Error(`Response status: ${response2.status}`);
        }
        chart.options.plugins.annotation.annotations = await response2.json();
      }
    } catch (error) {
      console.log(error.message);
    }
    if(autoUpdate){
      setTimeout(function () { getData(chart, url, sunrise,autoUpdate,animation) }, 5 * 60 * 1000); //renew data every 5 min.
    } 
  }

  async function getStats(elem_id, url) {
    try {
      console.log("fetching");
      const response = await fetch(url);
      if (!response.ok) {
        console.log("err");
        throw new Error(`Response status: ${response.status}`);
      }
      document.getElementById(elem_id).innerHTML = await response.text();
    } catch (error) {
      console.log(error.message);
    }
    setTimeout(function () { getData(chart, url, sunrise) }, 5 * 60 * 1000); //renew data every 5 min.
  }

  function powerToString(power) {
    if (Math.abs(power) > 999) {
      power = power / 1000
      return power.toPrecision(3) + " kW"
    } else {
      return Math.round(power) + " W"
    }

  }

  function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
    var angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0;

    return {
      x: centerX + (radius * Math.cos(angleInRadians)),
      y: centerY + (radius * Math.sin(angleInRadians))
    };
  }

  function getRBGComponent(colRange, minCol, valRange, minVal, val) {
    return Math.round(((val - minVal) / valRange) * colRange + minCol)
      .toString(16)
      .toUpperCase()
      .padStart(2, '0');
  }

  function assignColor(minCol, maxCol, minVal, maxVal, val) {
    var color = "";
    var minR = parseInt(minCol.substring(1, 3), 16);
    var maxR = parseInt(maxCol.substring(1, 3), 16);
    var minG = parseInt(minCol.substring(3, 5), 16);
    var maxG = parseInt(maxCol.substring(3, 5), 16);
    var minB = parseInt(minCol.substring(5, 7), 16);
    var maxB = parseInt(maxCol.substring(5, 7), 16);
    var valsRange = maxVal - minVal;
    var rangeG = maxG - minG;
    var rangeR = maxR - minR;
    var rangeB = maxB - minB;
    if (val > maxVal)
      val = maxVal;
    else if (val < minVal)
      val = minVal;

    color = '#'
      + getRBGComponent(rangeR, minR, valsRange, minVal, val)
      + getRBGComponent(rangeG, minG, valsRange, minVal, val)
      + getRBGComponent(rangeB, minB, valsRange, minVal, val);
    return color;
  }

  function describeArc(x, y, radius, startAngle, endAngle) {
    if (endAngle > 288) {
      endAngle = 288;
    }
    var start = polarToCartesian(x, y, radius, endAngle);
    var end = polarToCartesian(x, y, radius, startAngle);
    var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";
    var d = [
      "M", start.x, start.y,
      "A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
    ].join(" ");
    return d;
  }

  

  function updateValuesWeather(){
    var div=document.getElementById("windDir");
    div.style.transform = "rotate("+(90+Number(mqttData["weatherStation/windDeg"]))+"deg)";
    document.getElementById("windSpd").innerHTML = mqttData["weatherStation/avgWindspeed"];
    document.getElementById("humidity").innerHTML = mqttData["weatherStation/hum"];
    document.getElementById("temp").innerHTML = mqttData["weatherStation/tempAmb"];
    document.getElementById("windDirGust").style.transform = "rotate("+(90+Number(mqttData["weatherStation/gustDeg"]))+"deg)";
    document.getElementById("windGust").innerHTML = mqttData["weatherStation/maxgust"];
    document.getElementById("ambPress").innerHTML = Math.round(mqttData["weatherStation/qff"]*10)/10;
  }