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_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 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_pid_length() {
	var set_button = document.getElementById("set-pid-length");
	var number_input = document.getElementById("pid-length");
	if (!isNaN(number_input.value)) {
		set_button.disabled = true;
		number_input.disabled = true;
		fetch(api_url + "/pid-settings/loop_time_seconds/" + 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(1000);
				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(1000);
				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_at_home) {
		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 pid_length_button = document.getElementById("set-pid-length");
	var pid_length_input = document.getElementById("pid-length");
	pid_length_button.disabled = false;
	pid_length_input.disabled = false;
	pid_length_input.value = data.loop_time_seconds;
}

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 "🔋";
}