/* globals Chart:false, feather:false */

//var ctx = document.getElementById('myChart')
//var mainContent = document.getElementById('mainContent')

class BlueWeatherDashboard {

  constructor() {
    // cunstruct xmlhttp
    this.initDone = false
    this.blueweather = new BlueWeather()

    this.params = {
      loc: 1,
      page: -1,
      maxVals: 100,
      range: {
        from: "",
        to: ""
      }
    }

    this.restoreParms(this.params)

    this.loadDashboard(this.params)
    this.initDone = true
  }

  loadDashboard() {
    window.history.pushState("object or string", "Title", this.buildUrl({ "params": JSON.stringify(this.params) }));

    this.setTimeRange(this.params.from, this.params.to, false, false)

    // page: -1 for dashboard or sensor id
    var mainContent = document.getElementById('mainContent')
    var loader = document.getElementById('loader')

    mainContent.style = "opacity: 0;"
    loader.style = "position: absolute; left: 50%; opacity: 1;"
    //mainContent.classList.remove("opacity-animated");

    var page = this.params.page

    if (this.initDone) {
      document.getElementById("navbarPage" + page + "Link").classList.add("active")
    }

    this.blueweather.getLocationData(this.params.loc, { from: this.params.range.from, to: this.params.range.to }, this.params.maxVals, true, function (locationData) {
      // refresh sensors list
      dashboard.loadSensors(locationData)

      // set acive page in navbar
      document.getElementById("navbarPage" + page + "Link").classList.add("active")

      if (page === -1) {
        dashboard.setPageTitle("Dashboard")

        // create widget row
        var firstRow = document.createElement("div")
        firstRow.classList.add("card-deck")

        // create table
        var tableContainer = document.createElement("div")
        tableContainer.style = "overflow-x:auto;margin-top:20px;"
        var table = document.createElement("table")
        tableContainer.appendChild(table)
        table.classList.add("table", "table-hover")

        // create forst row of table
        var tableHead = document.createElement("thead")
        table.appendChild(tableHead)
        tableHead.innerHTML = "<tr><th>Sensor</th><th>Minimum</th><th>Maximum</th><th>Average</th></tr>"
        var tableBody = document.createElement("tbody")
        table.appendChild(tableBody)

        for (var i = 0; i < locationData.sensors.length; i++) {
          var sensor = locationData.sensors[i]

          // get the valuetype of the current sensor
          var valueType;

          for (var s = 0; s < locationData.valuetypes.length; s++) {
            var thisValType = locationData.valuetypes[s]
            if (parseInt(thisValType.id) === parseInt(sensor.valuetypeid)) {
              valueType = thisValType;
              break;
            }
          }

          // get all relevant  meassurement values
          var vals = []
          var sum = 0
          var min = undefined
          var max = undefined
          var avg = 0

          for (s = 0; s < locationData["measvalues"].length; s++) {
            var thisValue = locationData["measvalues"][s]
            if (parseInt(thisValue['sensorid']) === parseInt(sensor.id)) {
              vals.push(thisValue)
              if (parseFloat(thisValue.measvalue) < min || min === undefined) {
                min = parseFloat(thisValue.measvalue)
              }
              if (parseFloat(thisValue.measvalue) > max || max === undefined) {
                max = parseFloat(thisValue.measvalue)
              }
            }
          }

          for (s = 0; s < vals.length; s++) {
            avg += vals[s].measvalue / vals.length
          }

          if (vals.length < 1) {
            continue
          }

          vals.sort(function (a, b) {
            return b.timestamp - a.timestamp
          })

          // create table col
          var tableRow = document.createElement("tr")
          tableRow.innerHTML = "<td>" + sensor.sensorname + " (" + valueType.valuetype + ", " + valueType.valueunit + ")" + "</td><td>" + min + "</td><td>" + max + "</td><td>" + (Math.round((avg) * 100) / 100) + "</td>"
          tableBody.appendChild(tableRow)

          // - create widget card -
          var latestVal = vals[0]

          // create card
          var thisWidget = document.createElement("div")
          thisWidget.classList.add("card")

          // create header
          var thisHeader = document.createElement("div")
          thisHeader.classList.add("card-header")
          thisHeader.innerHTML = sensor.sensorname + " (" + valueType.valuetype + ")"
          thisWidget.appendChild(thisHeader)

          // create body
          var thisBody = document.createElement("div")
          thisBody.classList.add("card-body")
          thisWidget.appendChild(thisBody)

          // create footer
          var thisFooter = document.createElement("div")
          thisFooter.classList.add("card-footer")
          // fill footer
          var thisUpdateTime = document.createElement("small")
          thisUpdateTime.classList.add("text-muted")
          var lastUpdated = new Date(latestVal.timestamp * 1000)
          thisUpdateTime.innerHTML = "last updated " + (lastUpdated.getDate() === new Date().getDate() ? "today" : lastUpdated.getFullYear + "-" + lastUpdated.getMonth() + "-" + lastUpdated.getDate()) + " at " + lastUpdated.getHours() + ":" + lastUpdated.getMinutes()
          thisFooter.appendChild(thisUpdateTime)
          thisWidget.appendChild(thisFooter)

          // - create widget body -
          var displayProperties = JSON.parse(valueType.displayproperty).widget

          switch (displayProperties.type) {
            case "doughnut":
              // the widget is gauge-like
              var thisChart = document.createElement("canvas")
              thisChart.id = "chartOf" + sensor.sensorname

              var chartData = {
                datasets: [
                  {
                    label: sensor.sensorname + " (" + valueType.valuetype + ")",
                    data: [
                      parseInt(latestVal.measvalue),
                      100 - parseInt(latestVal.measvalue)
                    ]
                  }
                ],
                labels: false
              }

              Object.assign(chartData.datasets[0], displayProperties.properties)

              dashboard.createPercentCircle(thisChart, chartData)

              thisBody.appendChild(thisChart)

              break
            case "text":
              // the widget is pure text
              thisWidget.classList.add("text-center")
              thisBody.innerHTML = '<div class="flexFont"><h1 style="font-size: 100%;">' + latestVal.measvalue + valueType.valueunit + '</h1></div>'

              //thisBody.innerHTML = '<svg viewBox="0 0 56 18"><text x="0" y="15">Fit Meeeeeeeeeeee</text></svg>'
              break
          }

          firstRow.appendChild(thisWidget)
        }



        mainContent.innerHTML = "";
        mainContent.appendChild(firstRow)
        mainContent.appendChild(tableContainer)
      }
      else if (page !== -1) {
        mainContent.innerHTML = ""
        dashboard.loadDiagram(mainContent, locationData, page)
      }

      loader.style = "position: absolute; left: 50%; opacity: 0;"
      mainContent.classList.add("opacity-animated");
      mainContent.style = "opacity: 1;"
      flexFont();
    })
  }

  restoreParms(defaults = {}) {
    this.params = Object.assign(defaults, JSON.parse(this.findGetParameter("params")))
  }

  updateParams(newParams) {
    if (newParams.page !== this.params.page && this.initDone) {
      document.getElementById("navbarPage" + this.params.page + "Link").classList.remove("active")
    }

    Object.assign(this.params, newParams)

    window.history.pushState("object or string", "Title", this.buildUrl({ "params": JSON.stringify(this.params) }));
    this.loadDashboard()
  }

  setTimeRange(from = "", to = "", offset = true, autoReload = true) {
    // offset: if true the gien times will be substracted from the current time to get the target time
    this.blueweather.log("changing time range; form: " + from + "; to: " + to + "; (now is: " + new Date().getTime() + ")", 3)

    if (offset) {
      if (from !== "") {
        from = new Date().getTime() / 1000 - from
      }

      if (to !== "") {
        to = new Date().getTime() / 1000 - parseInt(to)
      }
    }
    else {
      if (from !== "") {
        from = parseInt(from)
      }
      if (to !== "") {
        to = parseInt(to)
      }
    }

    var tmpFrom = from
    var tmpTo = to

    if (tmpFrom === "") {
      tmpFrom = Math.round(new Date().getTime() / 1000 - 60 * 60 * 24)
    }

    if (tmpTo === "") {
      tmpTo = Math.round(new Date().getTime() / 1000)
    }

    var dateFromString = this.getDateTimeString(tmpFrom, tmpTo - tmpFrom)
    var dateToString = this.getDateTimeString(tmpTo, tmpTo - tmpFrom)

    dropdownMenuButton.innerHTML = "<span data-feather=\"calendar\"></span> " + dateFromString + " - " + dateToString
    feather.replace()


    if (this.initDone && autoReload) {
      this.updateParams({ range: { to: to, from: from } })
    }

  }

  loadSensors(locationData) {

    var sensorsList = document.getElementById("sensorsList")
    sensorsList.innerHTML = ""

    for (var i = 0; i < locationData.sensors.length; i++) {
      var sensor = locationData.sensors[i]
      console.log("parsing sensor ")
      var valueType;

      for (var v = 0; v < locationData['valuetypes'].length; v++) {
        var thisValType = locationData['valuetypes'][v]
        if (parseInt(thisValType.id) === parseInt(sensor.valuetypeid)) {
          valueType = thisValType;
          break;
        }
      }

      var currentHTML = sensorsList.innerHTML
      sensorsList.innerHTML = currentHTML +
        "<li class=\"nav-item\"><a class=\"nav-link\" id=\"navbarPage" + sensor["id"] + "Link\" href=\"#\" onclick=\"dashboard.updateParams({page: " + sensor["id"] + "})\"><span data-feather=\""+ valueType['valuetype'] +"\"></span>" + sensor["sensorname"] + "</a></li>"
    }

    feather.replace()
  }

  loadDiagram(parentId, locationData, sensorId) {
    if (typeof (parentId) === "string") {
      var mainContent = document.getElementById(parentId)
    }
    else {
      var mainContent = parentId
    }

    // get all relevant  meassurement values
    var vals = []

    for (var i = 0; i < locationData["measvalues"].length; i++) {
      var thisValue = locationData["measvalues"][i]
      if (parseInt(thisValue['sensorid']) === sensorId) {
        vals.push(thisValue)
      }
    }

    // get the current sensor
    var sensor;

    for (i = 0; i < locationData['sensors'].length; i++) {
      var thisSensor = locationData['sensors'][i]
      if (parseInt(thisSensor.id) === sensorId) {
        sensor = thisSensor;
        break;
      }
    }

    // get the value type
    var valueType;

    for (i = 0; i < locationData['valuetypes'].length; i++) {
      var thisValType = locationData['valuetypes'][i]
      if (parseInt(thisValType.id) === parseInt(sensor.valuetypeid)) {
        valueType = thisValType;
        break;
      }
    }

    // build chart data array
    var chartData = {
      data: [],
      datasets: [
        {
          label: sensor.sensorname + " (" + valueType.valuetype + ")",
          yAxisID: 'yAxis',
          showLine: true,
          data: vals
        }
      ],
      range: locationData.range
    }



    for (i = 0; i < vals.length; i++) {
      chartData.data.push({ x: vals[i]["timestamp"], y: vals[i]["measvalue"] })
    }

    Object.assign(chartData.datasets[0], JSON.parse(valueType.displayproperty)["chart"]["properties"])
    Object.assign(chartData.datasets[0], { data: chartData.data, pointRadius: chartData.data.length > 500 ? 0 : 3 })

    mainContent.innerHTML = "<canvas class=\"my-4 w-100\" id=\"myChart\"></canvas>"
    this.setPageTitle(sensor.sensorname + " (" + valueType.valuetype + ")")

    //blueweather.log("creating chart with data: " + JSON.stringify(chartData), 3)

    this.createDiagram("myChart", chartData)
  }

  // --------------------
  // - helper functions -
  // --------------------

  createPercentCircle(canvasElement, data) {
    var randomScalingFactor = function () {
      return Math.round(Math.random() * 100);
    };
    var ctx = canvasElement//document.getElementById(canvasId)

    var chartData = data
    var chartOptions = {
      responsive: true,
      circumference: Math.PI,
      rotation: Math.PI,
      legend: {
        position: 'top',
      },
      animation: {
        animateScale: true,
        animateRotate: true
      }
    }


    var myChart = new Chart(ctx, {
      type: 'doughnut',
      data: chartData,
      options: chartOptions
    })

  }

  createDiagram(canvasId, data) {
    // Graphs
    var ctx = document.getElementById(canvasId)
    // eslint-disable-next-line no-unused-vars

    var chartData = {
      //labels: time,
      datasets: data.datasets
    };

    var chartOptions = {
      responsive: true,
      maintainAspectRatio: false,
      scales: {
        yAxes: [
          {
            id: 'yAxis',
            type: 'linear',
            position: 'left',
          }
        ],

        xAxes: [{
          ticks: {
            min: parseInt(data.range.from),
            max: parseInt(data.range.to),
            beginAtZero: false,
            stepSize: (data.range.to - data.range.from) / 10,
            userCallback: function (label, index, labels) {
              var d = new Date(parseInt(label) * 1000);
              var datestr = "";

              var to = data.range.to
              var from = data.range.from

              if (to === "") {
                to = new Date().getTime()
              }

              var range = data.range.to - data.range.from

              if (range <= 60 * 60 * 24) {
                // covers one day or less
                datestr = ("0" + d.getHours()).slice(-2) + ":" +
                  ("0" + d.getMinutes()).slice(-2) + ":" +
                  ("0" + d.getSeconds()).slice(-2)
              }
              else if (range <= 60 * 60 * 24 * 31) {
                // covers one month or less

                datestr = ("0" + d.getDate()).slice(-2) + "-" +
                  ("0" + (d.getMonth() + 1)).slice(-2) + " " +
                  ("0" + d.getHours()).slice(-2) + ":" +
                  ("0" + d.getMinutes()).slice(-2) + ":" +
                  ("0" + d.getSeconds()).slice(-2)
              }
              else {
                // covers more than a month

                datestr =
                  d.getFullYear() + "-" +
                  ("0" + d.getDate()).slice(-2) + "-" +
                  ("0" + (d.getMonth() + 1)).slice(-2)
              }


              return datestr;
            }
          },

          scaleLabel: {
            display: true,
            labelString: 'time'
          }
        }],
      },

      tooltips: {
        callbacks: {
          label: function (tooltipItem, data) {

            var label = [data.datasets[tooltipItem.datasetIndex].label || ''];

            if (label) {
              label[0] += ': ';
            }

            label[0] += Math.round(tooltipItem.yLabel * 100) / 100;

            var time = Math.round(tooltipItem.xLabel * 100) / 100;

            var d = new Date(time * 1000);
            var datestr =
              d.getFullYear() + "-" +
              ("0" + d.getDate()).slice(-2) + "-" +
              ("0" + (d.getMonth() + 1)).slice(-2) + " " +
              ("0" + d.getHours()).slice(-2) + ":" +
              ("0" + d.getMinutes()).slice(-2) + ":" +
              ("0" + d.getSeconds()).slice(-2)
              ;

            label.push("Time: " + datestr);

            return label;
          }
        }
      }

    };

    var myChart = new Chart(ctx, {
      type: 'scatter',
      data: chartData,
      options: chartOptions
    })
  }

  getDateTimeString(unixTime, range = 0) {

    if (Math.abs(unixTime - new Date().getTime() / 1000) <= 60) {
      return "now"
    }

    var d = new Date(parseInt(unixTime) * 1000);
    var datestr = ""
    if (range <= 60 * 60 * 24 * 31) {
      // covers one month or less

      datestr =
        ("0" + d.getDate()).slice(-2) + "-" +
        ("0" + (d.getMonth() + 1)).slice(-2) + " " +
        ("0" + d.getHours()).slice(-2) + ":" +
        ("0" + d.getMinutes()).slice(-2)
    }
    else {
      // covers more than a month

      datestr =
        d.getFullYear() + "-" +
        ("0" + d.getDate()).slice(-2) + "-" +
        ("0" + (d.getMonth() + 1)).slice(-2)
    }

    return datestr
  }

  setPageTitle(title) {
    document.getElementById("titleH1").innerHTML = title
  }

  findGetParameter(parameterName) {
    var result = null,
      tmp = [];
    location.search
      .substr(1)
      .split("&")
      .forEach(function (item) {
        tmp = item.split("=");
        if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
      });
    return result;
  }

  buildUrl(params) {
    var basepath = window.location.href.split("?")[0]

    basepath += "?"

    for (var param in params) {
      basepath += param + "=" + params[param] + "&"
    }

    return basepath
  }

  whichTransitionEvent() {
    var t;
    var el = document.createElement('fakeelement');
    var transitions = {
      'transition': 'transitionend',
      'OTransition': 'oTransitionEnd',
      'MozTransition': 'transitionend',
      'WebkitTransition': 'webkitTransitionEnd'
    }

    for (t in transitions) {
      if (el.style[t] !== undefined) {
        return transitions[t];
      }
    }
  }
}

flexFont = function () {
  var divs = document.getElementsByClassName("flexFont");
  for (var i = 0; i < divs.length; i++) {
    var relFontsize = divs[i].offsetWidth * 0.2;
    divs[i].style.fontSize = relFontsize + 'px';
  }
};
flexFont();
window.onload = function (event) {
  flexFont();
};
window.onresize = function (event) {
  flexFont();
};
feather.replace()
dashboard = new BlueWeatherDashboard()