var chart = null
var chart2 = null
function initCharts() {
  chart = c3.generate({
    bindto: '#humidity-temp',
    data: {
      x: 'time',
      columns: [
        ['time', 1, 2, 3, 4],
        ['temp', 24, 24.5, 24.3, 24.6],
        ['humidity', 83.1, 99.5, 74.3, 84.6],
      ],
      axes: {
        temp: 'y',
        humidity: 'y2'
      }
    },
    axis: {
      x: {
        tick: {
          format: (x) => new Date(x).toISOString()
        }
      },
      y2: {
        show: true
      }
    },
    zoom: {
      enabled: true
    }
  })
  chart2 = c3.generate({
    bindto: '#volts',
    data: {
      x: 'time',
      columns: [
        ['time', 1, 2, 3, 4],
        ['voltage', 24, 24.5, 24.3, 24.6],
        ['voltage2', 24, 24.5, 24.3, 24.6],
      ],
      axes: {
        voltage: 'y',
        voltage2: 'y',
      }
    },
    axis: {
      x: {
        tick: {
          format: (x) => new Date(x).toISOString()
        }
      },
    },
    zoom: {
      enabled: true
    }
  })
}

var max_interval_millis = 5*60*1000
var decimation_rate = 1

var cur_time_millis = 0
var time = []
var temp = []
var humd = []
var volts = []
var volts2 = []

function status(msg) {
  document.getElementById('status').textContent = msg
}

var autoupdate = true
var chart_updater = null

async function updateCharts() {
  status("loading data...")
  const latest = await fetch("/api/latest")
  const last_time_millis = await latest.json()
  if (last_time_millis > cur_time_millis) {
    // we need to collect more data to catch up
    // time is in milliseconds so we divide by 1000
    var diff = (last_time_millis - cur_time_millis) / 1000
    // worst case load only the last two weeks of data
    diff = Math.min(diff, max_interval_millis/1000)
    var path = "/api/last/weeks/"
    var offset = diff
    if (diff < 60) {
      path = "/api/last/seconds/"
      offset = Math.ceil(diff)
    } else if (diff < 60*60) {
      path = "/api/last/minutes/"
      offset = Math.ceil(diff/60)
    } else if (diff < 24*60*60) {
      path = "/api/last/hours/"
      offset = Math.ceil(diff/(60*60))
    } else if (diff < 7*24*60*60) {
      path = "/api/last/days/"
      offset = Math.ceil(diff/(24*60*60))
    } else {
      path = "/api/last/weeks/"
      offset = Math.ceil(diff/(7*24*60*60))
    }
    const new_data = await fetch(path + offset)
    const new_data_json = await new_data.json()
    // copy the data into the arrays
    new_data_json.sort((a, b) => a.t - b.t)
    new_data_json.forEach((v) => {
      var last_time = time[time.length-1]
      if (time.length == 0) {
        last_time = 0
      }
      if (v.t > last_time) {
        time.push(v.t)
        temp.push(v.temp)
        humd.push(v.hum)
        volts.push(v.hv)
        volts2.push(v.hv2)
      }
    })
    // truncate all the lists as necessary
    // using the time array to determine the splicing points
    cur_time_millis = time[time.length - 1]
    const min_time = cur_time_millis - max_interval_millis

    var slice_idx = 0
    for (var i = 0; i < time.length; i++) {
      if (time[i] >= min_time) {
        slice_idx = i
        break
      }
    }
    //console.log("slice idx ", slice_idx)

    temp = temp.slice(slice_idx)
    humd = humd.slice(slice_idx)
    volts = volts.slice(slice_idx)
    volts2 = volts2.slice(slice_idx)
    time = time.slice(slice_idx)

    const temp_d = temp.filter((_, idx) => (idx % decimation_rate) == 0)
    const humd_d = humd.filter((_, idx) => (idx % decimation_rate) == 0)
    const volts_d = volts.filter((_, idx) => (idx % decimation_rate) == 0)
    const volts2_d = volts2.filter((_, idx) => (idx % decimation_rate) == 0)
    const time_d = time.filter((_, idx) => (idx % decimation_rate) == 0)

    chart.load({
      columns: [
        ["time"].concat(time_d),
        ["temp"].concat(temp_d),
        ["humidity"].concat(humd_d),
      ]
    })
    chart2.load({
      columns: [
        ["time"].concat(time_d),
        ["voltage"].concat(volts_d),
        ["voltage2"].concat(volts2_d),
      ]
    })
    status("charts updated")
  }

  if (autoupdate) {
    chartupdater()
  }
}

const sleep = (ms) => new Promise(r => setTimeout(r, ms))
var chart_update_millis = 2000

async function chartupdater() {
  if (chart_updater) return
  chart_updater = true

  try {
    while (autoupdate) {
      await sleep(chart_update_millis)
      // wait at least two seconds to avoid wasting a lot of bandwidth
      const resp = await fetch("/api/update")
      updateCharts()
    }
  } finally {
    chart_updater = false
  }
}

var status_updater = false
async function updateStatus() {
  const status_resp = await fetch("/api/status")
  const status = await status_resp.json()
  //console.log(status)
  const humidifier_state = (status.humidifier ? "on" : "off")
  const manual_mode_state = (status.manual_mode ? "on" : "off")
  //console.log(humidifier_state)
  document.getElementById("device-status").textContent = "connected: " +
    status.connected + ", manual mode: " + manual_mode_state + ", humidifier: "
    + humidifier_state

  if (autoupdate) {
    waitThenUpdateStatus()
  }
}

async function waitThenUpdateStatus() {
  if (status_updater) return
  status_updater = true
  try {
    while (autoupdate) {
      await fetch("/api/status_update")
      updateStatus()
    }
  } finally {
    status_updater = false
  }
}

async function testAdminMode() {
  const msg = JSON.stringify({
    auth: "password",
    data: {
      set_params: {
        name: "target_lower",
        value: 0.87
      }
    }
  })
  await fetch("/api/admin", {
    method: "POST",
    body: msg
  })
}

window.onload = () => {
  initCharts()
  updateCharts()
  updateStatus()

  document.getElementById('update').addEventListener('click', (e) => {
    updateCharts()
    updateStatus()
  })
  document.getElementById('autoupdate').addEventListener('click', (e) => {
    autoupdate = document.getElementById('autoupdate').checked
  })
  document.getElementsByName('decim').forEach((elem) => {
    elem.addEventListener('click', (e) => {
      if (elem.checked) {
        decimation_rate = parseInt(elem.value)
      }
    })
  })
  document.getElementsByName('update').forEach((elem) => {
    elem.addEventListener('click', (e) => {
      if (elem.checked) {
        chart_update_millis = parseInt(elem.value)
      }
    })
  })

  document.getElementsByName('duration').forEach((elem) => {
    elem.addEventListener('click', (e) => {
      const old_millis = max_interval_millis
      if (elem.checked) {
        max_interval_millis = parseInt(elem.value)*1000*60
        if (max_interval_millis != old_millis) {
          // reset the chart data to force a reload on the next update
          cur_time_millis = 0
          time = []
          temp = []
          humd = []
          volts = []
          volts2 = []
        }
      }
    })
  })

  /*
  document.getElementById('test-admin').addEventListener('click', (e) => {
    testAdminMode()
  })
  */
}