<!DOCTYPE html>
<title>Camera Trips</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<style>
body { font-family: sans-serif; line-height: 1.5em; }
input, button, select { font-size: 100%; }
form {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 0.5em 1ch;
}
input[type="number"] { width: 5ch; }
#trip-lens { width: 100%; }
#lens-length { width: 7ch; }
#lens-aperture { width: 8ch; }
</style>

<section id="rolls">
<h1>Rolls</h1>
<ul>
</ul>

<form>
<label for="roll-body">Camera:</label>
<select id="roll-body" class="body" required>
</select>
<label for="roll-film">Film:</label>
<input id="roll-film" list="films" required>
<button type="button" onclick="loadRoll()">Load</button>
</form>

<datalist id="films">
	<option>Harman Phoenix 200</option>
	<option>Ilford HP5 Plus 400</option>
	<option>Shanghai Color 400</option>
	<option>Fomapan Action 400</option>
</datalist>
</section>

<section id="trips">
<h1>Trips</h1>

<form>
<label for="trip-date">Date:</label>
<input id="trip-date" type="date" required>
<label for="trip-body">Camera:</label>
<select id="trip-body" class="body" onchange="setTripBody()" required>
</select>
<label for="trip-lens">Lens:</label>
<select id="trip-lens" required>
</select>
<label for="trip-film">Film:</label>
<input id="trip-film" readonly required>
<label for="trip-first">Exposures:</label>
<span>
<input id="trip-first" type="number" required min="0" max="36">
–
<input id="trip-last" type="number" required min="0" max="36">
</span>
<label for="trip-note">Note:</label>
<input id="trip-note">
<button type="button" onclick="addTrip()">Record</button>
</form>

<ul>
</ul>
</section>

<section id="bodies">
<h1>Cameras</h1>
<ul>
</ul>

<form>
	<label for="body-name">Name:</label>
	<input id="body-name" required>
	<label for="body-mount">Mount:</label>
	<input id="body-mount" list="mounts" required>
	<button type="button" onclick="addBody()">Add</button>
</form>

<datalist id="mounts">
	<option>Contax/Yashica</option>
	<option>M42</option>
</datalist>
</section>

<section id="lenses">
<h1>Lenses</h1>
<ul>
</ul>

<form>
	<label for="lens-name">Name:</label>
	<input id="lens-name" required>
	<label for="lens-length">Focal length:</label>
	<span><input id="lens-length" required pattern="[0-9-]+">mm</span>
	<label for="lens-aperture">Aperture:</label>
	<span>ƒ/<input id="lens-aperture" required pattern="[0-9.-]+"></span>
	<label for="lens-mount">Mount:</label>
	<input id="lens-mount" list="mounts" required>
	<button type="button" onclick="addLens()">Add</button>
</form>
</section>

<script>
let bodies = JSON.parse(localStorage.getItem("bodies")) || [];
let lenses = JSON.parse(localStorage.getItem("lenses")) || [];
let rolls = JSON.parse(localStorage.getItem("rolls")) || {};
let trips = JSON.parse(localStorage.getItem("trips")) || [];
let nextId = +localStorage.getItem("nextId") || 1;

document.getElementById("trip-date").valueAsDate = new Date();

function setBodies() {
	localStorage.setItem("bodies", JSON.stringify(bodies));
	let ul = document.querySelector("#bodies > ul");
	let selects = document.querySelectorAll("select.body");
	ul.innerHTML = "";
	selects.forEach(select => select.innerHTML = "");
	for (body of bodies) {
		let li = document.createElement("li");
		li.appendChild(document.createTextNode(`${body.name} (${body.mount})`));
		ul.appendChild(li);
		for (select of selects) {
			let option = document.createElement("option");
			option.appendChild(document.createTextNode(body.name));
			select.appendChild(option);
		}
	}
}
setBodies();

function endashify(str) {
	return str.replaceAll("-", "–");
}
function lensString(lens) {
	return `
		${lens.name}
		${endashify(lens.focalLength)}mm
		ƒ/${endashify(lens.aperture)}
	`;
}

function setLenses() {
	localStorage.setItem("lenses", JSON.stringify(lenses));
	let ul = document.querySelector("#lenses > ul");
	ul.innerHTML = "";
	for (lens of lenses) {
		let li = document.createElement("li");
		li.appendChild(document.createTextNode(`
			${lensString(lens)} (${lens.mount})
		`));
		ul.appendChild(li);
	}
}
setLenses();

function setRolls() {
	localStorage.setItem("rolls", JSON.stringify(rolls));
	let ul = document.querySelector("#rolls > ul");
	ul.innerHTML = "";
	for (body in rolls) {
		let roll = rolls[body];
		let li = document.createElement("li");
		li.appendChild(document.createTextNode(`
			${body}: ${roll.film} (${roll.used}/${roll.exposures})
		`));
		if (roll.used == roll.exposures) {
			li.style.textDecoration = "line-through";
		}
		ul.appendChild(li);
	}
}
setRolls();

function setTrips() {
	localStorage.setItem("trips", JSON.stringify(trips));
	let ul = document.querySelector("#trips > ul");
	ul.innerHTML = "";
	for (let rollId = nextId - 1; rollId > 0; --rollId) {
		let rollTrips = trips.filter(trip => trip.rollId == rollId);
		if (rollTrips.length == 0) continue;
		let rollLi = document.createElement("li");
		rollLi.appendChild(document.createTextNode(`
			${rollTrips[0].film} (${rollTrips[0].body})
		`));
		let rollUl = document.createElement("ul");
		for (trip of rollTrips) {
			let li = document.createElement("li");
			li.appendChild(document.createTextNode(`
				${trip.date}:
				${trip.firstExposure}–${trip.lastExposure}
			`));
			li.appendChild(document.createElement("br"));
			li.appendChild(document.createTextNode(trip.lens));
			if (trip.note) {
				li.appendChild(document.createElement("br"));
				li.appendChild(document.createTextNode(`“${trip.note}”`));
			}
			rollUl.appendChild(li);
		}
		rollLi.appendChild(rollUl);
		ul.appendChild(rollLi);
	}
}
setTrips();

function setTripBody() {
	let bodyName = document.getElementById("trip-body").value;
	let body = bodies.find(body => body.name == bodyName);
	let select = document.getElementById("trip-lens");
	select.innerHTML = "";
	for (lens of lenses.filter(lens => lens.mount == body.mount)) {
		let option = document.createElement("option");
		option.appendChild(document.createTextNode(lensString(lens)));
		select.appendChild(option);
	}
	let roll = rolls[body.name];
	document.getElementById("trip-film").value = roll.film;
	let next = (roll.used > 0 ? roll.used + 1 : roll.used);
	document.getElementById("trip-first").value = next;
	document.getElementById("trip-last").value = next;
}
setTripBody();

function clearForm(form) {
	let inputs = form.querySelectorAll("input");
	for (input of inputs) {
		input.value = null;
	}
}

function addBody() {
	let form = document.querySelector("#bodies > form");
	if (!form.checkValidity()) return;
	let name = document.getElementById("body-name").value;
	let mount = document.getElementById("body-mount").value;
	bodies.push({ name, mount });
	setBodies();
	clearForm(form);
}

function addLens() {
	let form = document.querySelector("#lenses > form");
	if (!form.checkValidity()) return;
	let name = document.getElementById("lens-name").value;
	let focalLength = document.getElementById("lens-length").value;
	let aperture = document.getElementById("lens-aperture").value;
	let mount = document.getElementById("lens-mount").value;
	lenses.push({ name, focalLength, aperture, mount });
	setLenses();
	clearForm(form);
}

function loadRoll() {
	let form = document.querySelector("#rolls > form");
	if (!form.checkValidity()) return;
	let body = document.getElementById("roll-body").value;
	let film = document.getElementById("roll-film").value;
	rolls[body] = { id: nextId++, film, used: 0, exposures: 36 };
	localStorage.setItem("nextId", nextId);
	setRolls();
	clearForm(form);
	setTripBody();
}

function addTrip() {
	let form = document.querySelector("#trips > form");
	if (!form.checkValidity()) return;
	let date = document.getElementById("trip-date").value;
	let body = document.getElementById("trip-body").value;
	let lens = document.getElementById("trip-lens").value;
	let film = document.getElementById("trip-film").value;
	let firstExposure = +document.getElementById("trip-first").value;
	let lastExposure = +document.getElementById("trip-last").value;
	let note = document.getElementById("trip-note").value;
	let trip = {
		date, body, lens, film, rollId: rolls[body].id,
		firstExposure, lastExposure, note
	};
	trips.push(trip);
	rolls[body].used = lastExposure;
	setTrips();
	setRolls();
	document.getElementById("trip-date").valueAsDate = new Date();
	document.getElementById("trip-note").value = "";
	setTripBody();
}

</script>