const api_url =
  window.location.protocol +
  "//" +
  window.location.hostname +
  ":" +
  window.location.port;

Object.prototype.disable = function () {
  var that = this;
  for (var i = 0, len = that.length; i < len; i++) {
    that[i].disabled = true;
  }
  return that;
};

Object.prototype.enable = function () {
  var that = this;
  for (var i = 0, len = that.length; i < len; i++) {
    that[i].disabled = false;
  }
  return that;
};

function init_main() {
  refresh_interval = register(refresh);

  refresh();
  document.addEventListener("visibilitychange", () => {
    if (document.hidden) {
      clearInterval(refresh_interval);
    } else {
      refresh();
      refresh_interval = register(refresh);
    }
  });
}

function init_pid() {
  refresh_gains();
  document.addEventListener("visibilitychange", () => {
    if (!document.hidden) {
      refresh_gains();
    }
  });
}

function init_shutoff() {
  refresh_shutoff();
  document.addEventListener("visibilitychange", () => {
    if (!document.hidden) {
      refresh_shutoff();
    }
  });
}

function init_info() {
  refresh_interval = register(refresh_info);

  refresh_info();
  document.addEventListener("visibilitychange", () => {
    if (document.hidden) {
      clearInterval(refresh_interval);
    } else {
      refresh_info();
      refresh_interval = register(refresh_info);
    }
  });
}

function init_regulator() {
  refresh_interval = register(refresh_regulator_state);

  refresh_regulator_state();
  document.addEventListener("visibilitychange", () => {
    if (document.hidden) {
      clearInterval(refresh_interval);
    } else {
      refresh_regulator_state();
      refresh_interval = register(refresh_regulator_state);
    }
  });
}

function register(func) {
  return setInterval(func, 5000);
}

function flash() {
  fetch(api_url + "/flash", { method: "POST" });
}

var is_automatic_control;
var current_min_rate;
var current_max_rate;

const delay = (time) => {
  return new Promise((resolve) => setTimeout(resolve, time));
};

function set_minimum() {
  var set_button = document.getElementById("set-minimum");
  var number_input = document.getElementById("min-rate");
  if (!isNaN(number_input.value)) {
    set_button.disabled = true;
    number_input.disabled = true;
    fetch(api_url + "/set-min/" + number_input.value, { method: "POST" }).then(
      async (response) => {
        let delayres = await delay(100);
        refresh_buttons();
      }
    );
  }
}

function change_min() {
  var set_button = document.getElementById("set-minimum");
  var number_input = document.getElementById("min-rate");
  set_button.disabled = number_input.value == current_min_rate;
}

function set_maximum() {
  var set_button = document.getElementById("set-maximum");
  var number_input = document.getElementById("max-rate");
  if (!isNaN(number_input.value)) {
    set_button.disabled = true;
    number_input.disabled = true;
    fetch(api_url + "/set-max/" + number_input.value, { method: "POST" }).then(
      async (response) => {
        let delayres = await delay(100);
        refresh_buttons();
      }
    );
  }
}

function change_max() {
  var set_button = document.getElementById("set-maximum");
  var number_input = document.getElementById("max-rate");
  set_button.disabled = number_input.value == current_max_rate;
}

function set_proportional() {
  var set_button = document.getElementById("set-proportional");
  var number_input = document.getElementById("proportional-gain");
  if (!isNaN(number_input.value)) {
    set_button.disabled = true;
    number_input.disabled = true;
    fetch(api_url + "/pid-settings/proportional/" + number_input.value, {
      method: "POST",
    }).then(async (response) => {
      let delayres = await delay(100);
      refresh_gains();
    });
  }
}

function set_derivative() {
  var set_button = document.getElementById("set-derivative");
  var number_input = document.getElementById("derivative-gain");
  if (!isNaN(number_input.value)) {
    set_button.disabled = true;
    number_input.disabled = true;
    fetch(api_url + "/pid-settings/derivative/" + number_input.value, {
      method: "POST",
    }).then(async (response) => {
      let delayres = await delay(100);
      refresh_gains();
    });
  }
}

function set_shutoff_voltage() {
  var set_button = document.getElementById("set-shutoff-voltage");
  var number_input = document.getElementById("shutoff-voltage");
  if (!isNaN(number_input.value)) {
    set_button.disabled = true;
    number_input.disabled = true;
    fetch(api_url + "/shutoff/voltage/" + number_input.value, {
      method: "POST",
    }).then(async (response) => {
      let delayres = await delay(100);
      refresh_shutoff();
    });
  }
}

function set_shutoff_time() {
  var set_button = document.getElementById("set-shutoff-time");
  var number_input = document.getElementById("shutoff-time");
  if (!isNaN(number_input.value)) {
    set_button.disabled = true;
    number_input.disabled = true;
    fetch(api_url + "/shutoff/time/" + number_input.value, {
      method: "POST",
    }).then(async (response) => {
      let delayres = await delay(100);
      refresh_shutoff();
    });
  }
}

function set_regulator_state() {
  var set_button = document.getElementById("set-regulator-state");
  var state_input = document.getElementById("regstate");

  set_button.disabled = true;
  state_input.disabled = true;

  fetch(api_url + "/set-regulator-state/" + state_input.value, {
    method: "POST",
  }).then(async (response) => {
    let delayres = await delay(300);
    refresh_regulator_state();
  });
}

function set_load_divisor() {
  var set_button = document.getElementById("set-load-divisor");
  var number_input = document.getElementById("load-divisor");
  if (!isNaN(number_input.value)) {
    set_button.disabled = true;
    number_input.disabled = true;
    fetch(api_url + "/pid-settings/load_divisor/" + number_input.value, {
      method: "POST",
    }).then(async (response) => {
      let delayres = await delay(100);
      refresh_gains();
    });
  }
}

function disable_automatic_control() {
  if (is_automatic_control) {
    document.getElementById("control-disabled").checked = true;
    document.body.classList.add("loading");

    fetch(api_url + "/disable-control", { method: "POST" }).then(
      async (response) => {
        let delayres = await delay(100);
        refresh_buttons();
      }
    );
  }
}

function enable_automatic_control() {
  if (!is_automatic_control) {
    document.getElementById("control-enabled").checked = true;
    document.body.classList.add("loading");
    fetch(api_url + "/enable-control", { method: "POST" }).then(
      async (response) => {
        let delayres = await delay(100);
        refresh_buttons();
      }
    );
  }
}

function update_control_buttons(data) {
  current_max_rate = data.max_rate;
  current_min_rate = data.min_rate;

  var number_input_min = document.getElementById("min-rate");
  if (number_input_min.disabled || number_input_min.value == "") {
    number_input_min.value = data.min_rate;
    number_input_min.disabled = false;
  }
  document.getElementById("set-minimum").disabled =
    number_input_min.value == current_min_rate;

  var number_input_max = document.getElementById("max-rate");
  if (number_input_max.disabled || number_input_max.value == "") {
    number_input_max.value = data.max_rate;
    number_input_max.disabled = false;
  }
  document.getElementById("set-maximum").disabled =
    number_input_max.value == current_max_rate;

  document.body.classList.remove("loading");
  is_automatic_control = data.control_enable;
  if (data.control_enable) {
    document.getElementById("control-enabled").checked = true;
  } else {
    document.getElementById("control-disabled").checked = true;
  }

  var control_selector = document.getElementById("control-selector");
  if (data.is_charging) {
    if (control_selector.classList.contains("disabled")) {
      control_selector.classList.remove("disabled");
    }
    document.getElementsByName("control").enable();
  } else {
    if (!control_selector.classList.contains("disabled")) {
      control_selector.classList.add("disabled");
    }
    document.getElementsByName("control").disable();
  }
}

function refresh_gains() {
  fetch(api_url + "/pid-settings/status")
    .then((response) => response.json())
    .then((json) => update_gains(json));
}

function update_gains(data) {
  var proportional_set_button = document.getElementById("set-proportional");
  var proportional_number_input = document.getElementById("proportional-gain");
  proportional_set_button.disabled = false;
  proportional_number_input.disabled = false;
  proportional_number_input.value = data.proportional_gain;
  var derivative_set_button = document.getElementById("set-derivative");
  var derivative_number_input = document.getElementById("derivative-gain");
  derivative_set_button.disabled = false;
  derivative_number_input.disabled = false;
  derivative_number_input.value = data.derivative_gain;
  var load_divisor_button = document.getElementById("set-load-divisor");
  var load_divisor_input = document.getElementById("load-divisor");
  load_divisor_button.disabled = false;
  load_divisor_input.disabled = false;
  load_divisor_input.value = data.load_divisor;
}

function refresh_shutoff() {
  fetch(api_url + "/shutoff/status")
    .then((response) => response.json())
    .then((json) => update_shutoff(json));
}

function refresh_regulator_state() {
  var set_button = document.getElementById("set-regulator-state");
  var state_input = document.getElementById("regstate");

  set_button.disabled = false;
  state_input.disabled = false;

  fetch(api_url + "/regulator-state")
    .then((response) => response.json())
    .catch(() => null)
    .then((json) => update_regulator_state(json));
}

function update_shutoff(data) {
  var voltage_set_button = document.getElementById("set-shutoff-voltage");
  var voltage_number_input = document.getElementById("shutoff-voltage");
  voltage_set_button.disabled = false;
  voltage_number_input.disabled = false;
  voltage_number_input.value = data.voltage;
  var time_set_button = document.getElementById("set-shutoff-time");
  var time_number_input = document.getElementById("shutoff-time");
  time_set_button.disabled = false;
  time_number_input.disabled = false;
  time_number_input.value = data.time;
}

function update_regulator_state(state) {
  console.log(state);
  if (state == null) {
    var cur = "Unknown";
  } else {
    var cur = state.regulator_state;
  }

  var current_state = document.getElementById("current-state");
  current_state.textContent = "Current state: " + cur;
}

function refresh_buttons() {
  fetch(api_url + "/control-state")
    .then((response) => response.json())
    .then((json) => update_control_buttons(json));
}

function refresh() {
  set_favicon(null);

  refresh_buttons();

  fetch(api_url + "/car-state")
    .then((response) => response.json())
    .then((json) => update_state(json));
}

function refresh_info() {
  set_favicon(null);

  fetch(api_url + "/car-state")
    .then((response) => response.json())
    .then((json) => update_info(json));
}

function update_info(state) {
  set_favicon(state.charge_state);

  var info_div = document.getElementById("info");
  while (info_div.childElementCount > 0) {
    info_div.removeChild(info_div.firstChild);
  }

  el = document.createElement("p");

  state_json = document.createElement("pre");
  state_json.appendChild(
    document.createTextNode(JSON.stringify(state, null, "\t"))
  );
  el.appendChild(state_json);
  info_div.appendChild(el);
}

function update_state(state) {
  set_favicon(state.charge_state);

  var info_div = document.getElementById("info");
  while (info_div.childElementCount > 0) {
    info_div.removeChild(info_div.firstChild);
  }

  el = document.createElement("p");

  var charging_state_info = "";

  switch (state.charge_state.charging_state) {
    case "Charging":
      charging_state_info =
        "charging at " + state.charge_state.charge_rate + "A";
      break;
    case "Stopped":
      charging_state_info = "charge stopped";
      break;
    case "Disconnected":
      charging_state_info = "disconnected";
      break;
  }

  if (state.location_data.home) {
    if (state.charge_state.charging_state == "Charging") {
      charging_state_info =
        "set at " +
        state.charge_state.charge_current_request +
        "A, " +
        charging_state_info;
    }
    charging_state_info = "At home; " + charging_state_info;
  } else {
    charging_state_info = "Not home; " + charging_state_info;
  }

  el.appendChild(document.createTextNode(charging_state_info));

  info_div.appendChild(el);
}

function set_favicon(charge_state) {
  let favicon = document.getElementById("favicon");

  favicon.setAttribute(
    "href",
    "data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>" +
      get_emoji(charge_state) +
      "</text></svg>"
  );
}

function get_emoji(charge_state) {
  if (charge_state == null) {
    return "âŗ";
  } else if (charge_state.charge_rate > 0) {
    return "🔌";
  } else if (charge_state.battery_level < 60) {
    return "đŸĒĢ";
  } else return "🔋";
}