const urlParams = new URLSearchParams(window.location.search);

// TODO: cut-n-pasted from pycontrol
const by_key_to_by_lang = d => {
	let ret = {};
	for (const [k, v] of Object.entries(d)) {
		for (const [kk, vv] of Object.entries(v)) {
			if (!(kk in ret)) {
				ret[kk] = {};
			}
			ret[kk][k] = vv;
		}
	}
	return ret;
}

// TODO: cut-n-pasted from pycontrol (and edited)
const _fmt = (s, vals) => {
	return s.replace(/{(.*?)}/g, (_match, k) => ((vals && vals[k] != undefined) ? _fmt(vals[k], vals) : "!"+k+"!"));
}

const _mat_is_selected = (mat, name, name_long) => {
	// i had to disable the following "smart" logic because in skanska's new dispatch the long name is non-unique and this kept selecting multiple materials (effectively selecting the last one) -> so let's just consider (short) name to be the primary key for now
	if (mat.name == name) {
		return true;
	}
	/*
	// try exact match first
	if (mat.name == name && mat.name_long == name_long) {
		return true;
	}
	// then non-exact
	if (mat.name == name || mat.name_long == name_long) {
		return true;
	}
	// TODO: should we try a cross-match (name<=>name_long) as well?
	*/
	return false;
}

const save_new_placement = (vnode, saver) => {
	k = vnode.state.data.k;  // TODO: get rid of this
	const d = vnode.state.data;
	// TODO: the following is ugly - just send the entire material structure, not just individual attributes (same for the backend side)
	const x = {
		type: d.material_type,
		name: d._mat_name,
		name_long: d._mat_name_long,
		subtype: d._mat_subtype,
		silo_minor: d.silo_minor,
		substitution: d.substitution,
	};
	saver(x);
}

// TODO: put this inside of the component
const on_change_material = (vnode, e, saver) => {
	console.log("on_change_material", e.target.value, vnode.state.data);
	const idx = e.target.value != "" ? parseInt(e.target.value) : null;
	// TODO: the following is ugly - just save the entire material structure, not just individual attributes (same for the backend side)
	vnode.state.data._mat_name = idx != null ? vnode.state.data._possible_materials[idx].name : null;
	vnode.state.data._mat_name_long = idx != null ? vnode.state.data._possible_materials[idx].name_long : null;
	vnode.state.data._mat_subtype = idx != null ? vnode.state.data._possible_materials[idx].subtype : null;
	console.log(vnode.state.data);
	save_new_placement(vnode, saver);
}

// TODO: put this inside of the component
const on_change_silo_minor = (vnode, e, saver) => {
	console.log("on_change_silo_minor", e.target.value, vnode.state.data);
	vnode.state.data.silo_minor = e.target.value != "" ? parseInt(e.target.value) : null;
	console.log(vnode.state.data);
	save_new_placement(vnode, saver);
}

// TODO: put this inside of the component
const on_change_substitution = (vnode, e, saver) => {
	console.log("on_change_substitution", e.target.value, vnode.state.data);
	vnode.state.data.substitution = e.target.checked;
	console.log(vnode.state.data);
	save_new_placement(vnode, saver);
}

// TODO: find a proper name
// TODO: move to component
const the_big_saver = (vnode, d) => {
	m.request({url: "./save_new_placement/"+k, method: "POST", body: d}).then(data => {
		console.log("saved, new data is", data);
		vnode.state.data = data;
	});
}

const PlaceListItem = {
	oninit: vnode => {
		vnode.state.data = vnode.attrs.data;
	},
	view: vnode => {
		const d = vnode.attrs.data;
		const saver = vnode.attrs.saver;
		const fmt = vnode.attrs.fmt;
		const title = fmt(d.title);
		let _pos_mats = [{id: null, text: "", selected: 1}];
		d._possible_materials.forEach((x, idx) => {
			_pos_mats.push({
				id: idx,
				text: x.name+" ("+x.name_long+")",
				selected: _mat_is_selected(x, d._mat_name, d._mat_name_long),
			});
		})
		let _pos_silos = [{id: null, text: "", selected: 1}];
		d._possible_minor_silos.forEach((x, _idx) => {
			_pos_silos.push({
				text: x,
				selected: x == d.silo_minor,
			});
		})
		return m("tr."+d.material_type, [
			m("td", {title: title}, title),  // TODO: why the tooltip?
			m("td", m("select", {style: {width: "200px"}, onchange: e => on_change_material(vnode, e, saver)}, _pos_mats.map(x => m("option", {value: x.id, selected: x.selected, disabled: d._is_minor_silo}, x.text)))),
			//m("td", {title: fmt("{silo_minor}")}, fmt("{silo_minor_abbrev}:")),
			m("td", m("select", {style: {width: "50px"}, onchange: e => on_change_silo_minor(vnode, e, saver)}, _pos_silos.map(x => m("option", {selected: x.selected, disabled: d._is_minor_silo}, x.text)))),
			//m("td", {title: fmt("{substitution}")}, fmt("{substitution_abbrev}:")),
			m("td", m("input", {type: "checkbox", checked: d.substitution, disabled: d._is_minor_silo, onchange: e => on_change_substitution(vnode, e, saver)})),
		]);
	}
}

const PlaceList = {
	oninit: vnode => {
		console.log("init");
		vnode.state.data = [];
		m.request({url: "./get_fill_data", method: "GET"}).then(data => {
			console.log("GOT", data);
			vnode.state.data = data;
		});
	},
	view: vnode => {
		const fmt = vnode.attrs.fmt;
		return m("table", [
			m("tr", [
				m("th"),
				m("th"),
				m("th", {title: fmt("{silo_minor}")}, fmt("{silo_minor_abbrev}")),
				m("th", {title: fmt("{substitution}")}, fmt("{substitution_abbrev}")),
			]),
			...vnode.state.data.map(x => m(PlaceListItem, {data: x, saver: d => the_big_saver(vnode, d), fmt: fmt})),
		]);
	}
}

const Main = {
	view: vnode => {
		return m("", [
			m(PlaceList, {filt: vnode.state.filt, fmt: vnode.attrs.fmt}),
		]);
	}
}

// TODO: cut-n-pasted from pymanager (and edited)
const Language = {
	oninit: vnode => {
		vnode.state.lang = vnode.attrs.lang || "cs";
		console.log("lang is", vnode.state.lang);
		vnode.state.lang_d = {};
		m.request("./captions").then(data => {
			console.log("got lang data", data);
			vnode.state.lang_d = by_key_to_by_lang(data)[vnode.state.lang];
		});
	},
	view: vnode => {
		const fmt = (x) => _fmt(x, vnode.state.lang_d);
		return m(vnode.attrs.the_child, {fmt: fmt});  // TODO: find a better way than "the_child"
	}
}

m.mount(document.getElementById("content"), {"view": () => m(Language, {lang: urlParams.get("lang"), the_child: Main})});
