---
import LoggedIn from '../../layouts/LoggedIn.astro';
import locationManager from '../../lib/classes/managers/LocationManager';
import { Planet } from '../../lib/classes/managers/PlanetManager';
import SystemManager from '../../lib/classes/managers/SystemManager';
import { getAllFleetByUser } from '../../lib/db/fleet';
import { getAllShips } from '../../lib/db/ships';
import { getUserSpyReports } from '../../lib/db/users';
import { getName } from '../../lib/utils/langDriver';

const { token, user, lang } = Astro.locals;
const active: SystemManager | Planet = Astro.locals.active;

const activeId = active instanceof SystemManager ? active.data._id : active._id;
const ships = await getAllShips();
const url = Astro.url.origin;

if(Astro.request.method === "POST") {
	const form = await Astro.request.formData();

	const cargo: Array<{ id: string, amount: number }> = [];
	
	form.forEach((v, k) => {
		if(k.match(/cargo\[\d\]\[id\]/)) {
			const amount = parseInt(form.get(`${k.substring(0, k.indexOf("]"))}][amount]`)?.toString() ?? "0");
			
			if(amount === 0 || isNaN(amount)) return;
			
			cargo.push({
				id: v.toString(),
				amount
			});
		}
	});

	const destination = form.get('mission') === "EXPEDITION" || form.get('mission') === "COLONIZE" ?
		form.get('toSystem') ?
			form.get('destination-system')?.toString() :
			form.get('destination-sector')?.toString()
		:
		form.get('toSystem') ?
			form.get('destination-system')?.toString() :
			form.get('destination-planet')?.toString();

	const fleetData = {
		source: active instanceof SystemManager ? active.data._id : active._id,
		destination,
		mission: form.get('mission')?.toString() ?? "NULL",
		ships: ships.map(ship => {
			const amount = parseInt(form.get(`ship-amount-${ship.id}`)?.toString() ?? "0");
			if(amount === 0) return null;
			return {
				id: ship.id,
				amount
			}
		}).filter(s => s !== null),
		cargo
	}
	const response = await fetch(`${Astro.url.origin}/api/fleet/send`, {
		method: 'POST',
		headers: {
			'Content-Type': 'application/json',
			'Authorization': `Bearer ${token}`
		},
		body: JSON.stringify(fleetData)
	});

	console.log(await response.json());
	
	return Astro.redirect('/game/fleet');
}

await locationManager.updateFleet();

const fleet = (await getAllFleetByUser(user.id)).filter(f => new Date().getTime() - f.arrivalTime.getTime() < 0);
fleet.sort((a, b) => a.departureTime.getTime() - b.departureTime.getTime());

const galaxies = locationManager.galaxies;

let own = 0;
let friendly = 0;
let enemy = 0;

for(const f of fleet) {
	const source = locationManager.findId(f.source);
	if(source !== null) {
		if(source instanceof SystemManager) {
			if(source.data.ownedBy.id.equals(user.id)) own++;
			else if(!f.returning) enemy++;
		} else {
			if(source.system.data.ownedBy.id.equals(user.id)) own++;
			else if(!f.returning) enemy++;
		}
	}
}

const discoveredSectors = await getUserSpyReports(user.id);

const sectorsList = galaxies.map(galaxy => {
	return {
		_id: galaxy._id,
		name: galaxy.name,
		sectors: galaxy.sectors.map(sector => {
			return {
				_id: sector._id,
				name: sector.name,
				systems: sector.systems.map(system => {
					const discovered = discoveredSectors.find(s => s.systemId.equals(system.data._id));
					if(!discovered && !system.data.ownedBy.id.equals(user.id)) return {
						_id: system.data._id,
						name: `${system.data.name} (not discovered)`,
						planets: []
					}

					return {
						_id: system.data._id,
						name: system.data.name,
						planets: system.planets.map(planet => {
							return {
								_id: planet._id,
								name: planet.name
							}
						})
					}
				})
			}
		})
	}
});
---
<LoggedIn id="fleet" title="Fleet">
	<label for="fleet-toggle">
		<input type="checkbox" id="fleet-toggle">
		<div class="fleet-status">
			<h2>Fleet status ({fleet.length} total | {own} own | {friendly} friendly | {enemy} enemy)</h2>
			<ul>
				{fleet.map(f => {
					const source = locationManager.findId(f.source);
					const destination = locationManager.findId(f.destination);

					return (<li>
					<div class="ship-cards">
						<span style={`${source instanceof SystemManager && "color:red;"}`}>{(source instanceof SystemManager ? source.data.name : source?.name) ?? "?"}</span> =&gt; <span style={`${destination instanceof SystemManager && "color:red;"}`}>{(destination instanceof SystemManager ? destination.data.name : destination?.name) ?? "?"}</span> | {f.mission}{f.returning ? " (R)" : ""}<br />
						Containing: {f.ships.map(s => {
							const ship = ships.find(ship => ship.id === s.id);
							return `${getName(lang, 'ships', s.id)} x${s.amount}`;
						}).join(', ')} <br />
						Cargo: {typeof f.cargo === "undefined" || f.cargo.length === 0 ? <>None</> : f.cargo.map(c => `${c.amount} ${getName(lang, 'resources', c.id)}`).join(', ')} <br />
						Departured at: {f.departureTime.toISOString()} <br />
						Arrives: {f.arrivalTime.toISOString()} ({Math.floor((f.arrivalTime.getTime() - new Date().getTime()) / 1000)}) <br />
						<button class="revert" style={`${f.returning && "display: none;"}`} data-id={f._id.toString()}>Revert</button>
					</div>
				</li>)
				})}
			</ul>
		</div>
	</label>
	<div class="fleet-send-container">
		<form method="post" id="send-fleet">
			<h1>Sending fleet from {active instanceof SystemManager ? active.data.name : active.name}</h1>
			<hr />
			<h2>Ships</h2>
			<div class="fleet-send-ships">
				{active.ships.ships.map(ship => <div class="fleet-ship-card">
					<h3>{getName(lang, 'ships', ship.data.id)} - {ship.amount}</h3>
					<input type="number" value="0" min="0" max={ship.amount} id={ship.data.id} name={`ship-amount-${ship.data.id}`} class="ship-amount-inputs" />
				</div>)}
			</div>
			<hr />
			<h2>Mission</h2>
			<label for="attack"><input type="radio" name="mission" value="ATTACK" id="attack" required />Attack</label>
			<label for="transport"><input type="radio" name="mission" value="TRANSPORT" id="transport" />Transport</label>
			<label for="transfer"><input type="radio" name="mission" value="TRANSFER" id="transfer" />Transfer</label>
			<label for="expedition"><input type="radio" name="mission" value="EXPEDITION" id="expedition" />Expedition</label>
			<label for="spy"><input type="radio" name="mission" value="SPY" id="spy" />Spying</label>
			<label for="colonize"><input type="radio" name="mission" value="COLONIZE" id="colonize" />Colonize</label>
			<label><input type="checkbox" name="toSystem" />Send to system</label>
			<hr />
			<h2>Send to</h2>
			<div class="fleet-destination">
				<div>
					<h3>Galaxy</h3>
					<select id="destination-galaxy" name="destination-galaxy">
						{galaxies.map(galaxy => <option value={galaxy._id.toString()}>{galaxy.name}</option>)}
					</select>
				</div>
				<div>
					<h3>Sector</h3>
					<select id="destination-sector" name="destination-sector"></select>	
				</div>
				<div>
					<h3>System</h3>
					<select id="destination-system" name="destination-system"></select>
					<div id="destination-system-error"></div>
				</div>
				<div>
					<h3>Planet</h3>
					<select id="destination-planet" name="destination-planet"></select>
					<div id="destination-planet-error"></div>	
				</div>
			</div>
			<hr />
			<h2>Cargo</h2>
			<div id="cargo-available">
				Solid: <span id="available-solid">0</span><br />
				Liquid: <span id="available-liquid">0</span><br />
				Gas: <span id="available-gas">0</span><br />
			</div>
			<div class="cargo-container" id="cargo-container">
				<div class="cargo-item">
					<select name="cargo[0][id]" class="select">
						<option value="coal">Coal</option>
						<option value="iron">Iron</option>
						<option value="gold">Gold</option>
						<option value="water">Water</option>
						<option value="sulfuric-acid">Sulfuric Acid</option>
						<option value="liquid-nitrogen">Liquid Nitrogen</option>
						<option value="hydrogen">Hydrogen</option>
						<option value="oxygen">Oxygen</option>
						<option value="helium-3">Helium-3</option>
					</select>
					<input type="number" name="cargo[0][amount]" class="input" />
					<button type="button" class="cargo-sendall" name="cargo[0][all]">All</button>
				</div>
			</div>
			<div id="cargo-add-new">Add new +</div>
			<hr />
			<h2>Fuel consumption</h2>
			<div>Base usage from ships: <span id="fuel-consumption">0</span></div>
			<div>Distance: <span id="fuel-consumption-distance">0</span></div>
			<div><span id="fuel-consumption-required">0</span> hydrogen will be added to cargo as fuel</div>
			<hr />
			<h2>Estimates</h2>
			<div>Fleet will arrive at destination at: <span id="arrival-time"></span></div>
			<div>Fleet will return at: <span id="return-time"></span></div>
			<hr />
			<button type="submit">Send fleet</button>
		</form>
	</div>
</LoggedIn>

<style>
* {
	color: white;
}

.ship-cards {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	row-gap: 40px;
	column-gap: 2%;
}

#ship-modal-background {
	display: none;
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: rgba(0, 0, 0, 0.5);
	z-index: 100;
}

#ship-modal-details {
	display: none;
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 80%;
	max-width: 800px;
	background: rgba(0, 0, 0, 0.9);
	border-radius: 8px;
	padding: 1rem;
	z-index: 101;
}

.fleet-status {
	margin-top: 40px;
	background-color: gray;
	border-radius: 10px;
	padding: 2px;
}

.fleet-status ul {
	list-style-type: none;
	padding: 0;
	opacity: 0;
	max-height: 0;
	overflow: hidden;
	transition-property: max-height;
	transition-duration: 0.5s;
	transition-timing-function: ease;
}

#fleet-toggle {
	position: absolute;
 	top: -9999px;
	left: -9999px;
}

label { 
	-webkit-appearance: push-button;
	-moz-appearance: button; 
	margin: 60px 0 10px 0;
	cursor: pointer;
}

#fleet-toggle:checked ~ .fleet-status ul {
	opacity: 1;
	height: auto;
	max-height: 1000px;
}

.fleet-send-container {
	margin-top: 40px;
	background-color: gray;
	border-radius: 10px;
	padding: 2px;
}

.fleet-send-ships {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	row-gap: 40px;
	column-gap: 2%;
	margin-top: 40px;
}

.fleet-ship-card {
	background-color: gray;
	border-radius: 10px;
	padding: 2px;
}

.fleet-ship-card h3 {
	margin: 0;
}

.fleet-ship-card input {
	width: 10rem;
	color: black;
}

.fleet-destination {
	display: flex;
	flex-direction: row;
	column-gap: 5%;
}

.fleet-destination select {
	width: 10rem;
	height: 3rem;
	color: black;
	background-color: darkgray;
}

.cargo-add-new {
	background-color: #aaaaaa;
	border-radius: 10px;
	padding: 2px;
	width: fit-content;
	color: black;
}

.select, .input {
	color: black;
}
</style>
<script define:vars={{ lang, sectorsList, url, ships, activeId }}>
	const revertButtons = document.querySelectorAll('.revert');
	const destinationGalaxy = document.getElementById('destination-galaxy');
	const destinationSector = document.getElementById('destination-sector');
	const destinationSystem = document.getElementById('destination-system');
	const destinationPlanet = document.getElementById('destination-planet');
	const toSystemCheckbox = document.querySelector('input[name="toSystem"]');
	const sendAllButtons = document.querySelectorAll('.cargo-sendall');
	const shipInputs = document.querySelectorAll('.ship-amount-inputs');
	const sendFleetForm = document.getElementById('send-fleet');

	if(!revertButtons || !destinationGalaxy || !destinationSector || !destinationSystem || !destinationPlanet || !toSystemCheckbox || !sendAllButtons || !shipInputs || !sendFleetForm) {
		console.error('Could not find all elements');
		return;
	};

	revertButtons.forEach(revBut => revBut.addEventListener('click', async evt => {
		await fetch(`${url}/api/fleet/revert`, {
			method: 'POST',
			headers: {
				'Content-Type': 'application/json'
			},
			body: JSON.stringify({
				id: evt.target.dataset.id
			})
		});

		window.location.reload();
	}));
	
	destinationGalaxy.addEventListener('change', () => {
		const galaxy = sectorsList.find(galaxy => galaxy._id === destinationGalaxy.value);
		if(!galaxy) return;

		destinationSector.innerHTML = '';
		for(const sector of galaxy.sectors) {
			const opt = document.createElement('option');
			opt.value = sector._id;
			opt.innerText = sector.name;
			destinationSector.appendChild(opt);
		}

		if(destinationSector.children.length === 0) {
			const opt = document.createElement('option');
			opt.value = '';
			opt.innerText = 'No sectors';
			destinationSector.appendChild(opt);
		}

		destinationSector.dispatchEvent(new Event('change'));
	});

	destinationSector.addEventListener('change', () => {
		const galaxy = sectorsList.find(galaxy => galaxy._id === destinationGalaxy.value);
		if(!galaxy) return;

		const sector = galaxy.sectors.find(sector => sector._id === destinationSector.value);
		if(!sector) return;

		destinationSystem.innerHTML = '';
		document.getElementById('destination-system-error').innerHTML = '';
		for(const system of sector.systems) {
			const opt = document.createElement('option');
			opt.value = system._id;
			opt.innerText = system.name;
			destinationSystem.appendChild(opt);
		}

		if(destinationSystem.children.length === 0) {
			const opt = document.createElement('option');
			opt.value = '';
			opt.innerText = 'No systems';
			destinationSystem.appendChild(opt);
			
			document.getElementById('destination-system-error').innerHTML = "No systems";
		}

		destinationSystem.dispatchEvent(new Event('change'));
	});

	destinationSystem.addEventListener('change', () => {
		const galaxy = sectorsList.find(galaxy => galaxy._id === destinationGalaxy.value);
		if(!galaxy) return;

		const sector = galaxy.sectors.find(sector => sector._id === destinationSector.value);
		if(!sector) return;

		const system = sector.systems.find(system => system._id === destinationSystem.value);
		if(!system) {
			destinationPlanet.innerHTML = '';
			const opt = document.createElement('option');
			opt.value = '';
			opt.innerText = 'No planets';
			destinationPlanet.appendChild(opt);
			document.getElementById('destination-planet-error').innerHTML = "No planets";
			return;
		}

		destinationPlanet.innerHTML = '';
		document.getElementById('destination-planet-error').innerHTML = '';
		
		for(const planet of system.planets) {
			const opt = document.createElement('option');
			opt.value = planet._id;
			opt.innerText = planet.name;
			destinationPlanet.appendChild(opt);
		}

		if(destinationPlanet.children.length === 0) {
			const opt = document.createElement('option');
			opt.value = '';
			opt.innerText = 'No planets';
			destinationPlanet.appendChild(opt);
		}

		destinationPlanet.dispatchEvent(new Event('change'));
	});

	destinationPlanet.addEventListener('change', calculateDistance);

	destinationGalaxy.dispatchEvent(new Event('change'));

	toSystemCheckbox.addEventListener('change', () => {
		destinationPlanet.disabled = toSystemCheckbox.checked;
		calculateDistance();
	});

	sendAllButtons.forEach(button => {
		button.addEventListener('click', () => handleAllClick(button));
	});

	const addNew = document.getElementById('cargo-add-new');
	addNew.addEventListener('click', () => {
		const cargoContainer = document.querySelector('.cargo-container');
		const cargoItem = document.createElement('div');
		cargoItem.classList.add('cargo-item');

		const selectMenu = document.createElement('select');
		selectMenu.name = `cargo[${cargoContainer.children.length}][id]`;
		selectMenu.classList.add('select');
		for(const res of ['coal', 'iron', 'gold', 'water', 'sulfuric-acid', 'liquid-nitrogen', 'hydrogen', 'oxygen', 'helium-3']) {
			const opt = document.createElement('option');
			opt.value = res;
			opt.innerText = res;
			selectMenu.appendChild(opt);
		}
		cargoItem.appendChild(selectMenu);

		const input = document.createElement('input');
		input.type = 'number';
		input.name = `cargo[${cargoContainer.children.length}][amount]`;
		input.classList.add('input');
		cargoItem.appendChild(input);

		const button = document.createElement('button');
		button.type = 'button';
		button.addEventListener('click', () => handleAllClick(button));
		button.classList.add('cargo-sendall');
		button.name = `cargo[${cargoContainer.children.length}][all]`;
		button.innerText = 'All';
		cargoItem.appendChild(button);

		cargoContainer.appendChild(cargoItem);
	});

	shipInputs.forEach(input => {
		input.addEventListener('input', () => {
			const fuelConsumption = Array.from(shipInputs).reduce((acc, cur) => {
				const ship = ships.find(ship => ship.id === cur.id);
				if(!ship) return acc;

				return acc + ship.fuelConsumption * parseInt(cur.value);
			}, 0);

			document.getElementById('fuel-consumption').innerText = fuelConsumption;

			const availableSolid = Array.from(shipInputs).reduce((acc, cur) => {
				const ship = ships.find(ship => ship.id === cur.id);
				if(!ship) return acc;

				return acc + ship.capacity.solid * parseInt(cur.value);
			}, 0);
			const availableLiquid = Array.from(shipInputs).reduce((acc, cur) => {
				const ship = ships.find(ship => ship.id === cur.id);
				if(!ship) return acc;

				return acc + ship.capacity.liquid * parseInt(cur.value);
			}, 0);
			const availableGas = Array.from(shipInputs).reduce((acc, cur) => {
				const ship = ships.find(ship => ship.id === cur.id);
				if(!ship) return acc;

				return acc + ship.capacity.gas * parseInt(cur.value);
			}, 0);

			document.getElementById('available-solid').innerText = availableSolid;
			document.getElementById('available-liquid').innerText = availableLiquid;
			document.getElementById('available-gas').innerText = availableGas;
			
			calculateRequiredFuel();
		});
	});

	sendFleetForm.addEventListener('submit', evt => {
		evt.preventDefault();

		// at least one ship
		if(Array.from(shipInputs).reduce((acc, cur) => acc + parseInt(cur.value), 0) === 0) {
			alert('You need to send at least one ship');
			return;
		}

		// source === destination
		const destinationId = document.querySelector('input[name="toSystem"]').checked ? document.getElementById('destination-system').value : document.getElementById('destination-planet').value;
		if(destinationId === activeId) {
			alert('Source and destination cannot be the same');
			return;
		}

		// check fuel
		const requiredFuel = parseInt(document.getElementById('fuel-consumption-required').innerText);
		const storedFuel = parseInt(document.getElementById('resource-hydrogen').dataset.resAmount);

		if(storedFuel < requiredFuel) {
			alert('Not enough fuel in storage');
			return;
		}

		const cargoSolidStored = Array.from(document.getElementById('cargo-container').children).reduce((acc, cur) => {
			const resId = cur.children.item(0).value;
			if(resId === "coal" || resId === "iron" || resId === "gold") {
				const amount = cur.children.item(1).value === "" ? 0 : parseInt(cur.children.item(1).value);
				return acc + amount;
			}
			return acc;
		}, 0);

		const cargoLiquidStored = Array.from(document.getElementById('cargo-container').children).reduce((acc, cur) => {
			const resId = cur.children.item(0).value;
			if(resId === "water" || resId === "sulfuric-acid" || resId === "liquid-nitrogen") {
				const amount = cur.children.item(1).value === "" ? 0 : parseInt(cur.children.item(1).value);
				return acc + amount;
			}
			return acc;
		}, 0);

		const cargoGasStored = Array.from(document.getElementById('cargo-container').children).reduce((acc, cur) => {
			const resId = cur.children.item(0).value;
			if(resId === "hydrogen" || resId === "oxygen" || resId === "helium-3") {
				const amount = cur.children.item(1).value === "" ? 0 : parseInt(cur.children.item(1).value);
				return acc + amount;
			}
			return acc;
		}, 0);

		const cargoSolidCapacity = document.getElementById('available-solid').innerText;
		const cargoLiquidCapacity = document.getElementById('available-liquid').innerText;
		const cargoGasCapacity = document.getElementById('available-gas').innerText;

		if(cargoSolidStored > cargoSolidCapacity) {
			alert('Not enough solid capacity in ships');
			return;
		}

		if(cargoLiquidStored > cargoLiquidCapacity) {
			alert('Not enough liquid capacity in ships');
			return;
		}

		if(cargoGasStored > cargoGasCapacity) {
			alert('Not enough gas capacity in ships');
			return;
		}
		
		if((cargoGasStored + requiredFuel) > cargoGasCapacity) {
			alert('Not enough gas capacity in ships for fuel');
			return;
		}

		// add hydrogen to cargo
		// const hydrogenInCargo = Array.from(document.getElementById('cargo-container').children).find(c => c.children.item(0).value === "hydrogen")?.children.item(1).value ?? 0;
		// const formData = new FormData(evt.target);

		sendFleetForm.submit();
	});

	async function calculateDistance() {
		const source = activeId;
		const destination = document.querySelector('input[name="toSystem"]').checked ? document.getElementById('destination-system').value : document.getElementById('destination-planet').value;
		
		if(!source || !destination) return;

		const response = await fetch(`${url}/api/fleet/getDistance?source=${source}&destination=${destination}`);
		const data = await response.json();

		if(data.error) {
			document.getElementById('fuel-consumption-distance').innerText = "Error";
			return;
		}

		const distance = data.distance;

		document.getElementById('fuel-consumption-distance').innerText = distance;
		document.getElementById('arrival-time').innerText = new Date(new Date().getTime() + distance * 1000).toLocaleString();
		document.getElementById('return-time').innerText = new Date(new Date().getTime() + distance * 1000 * 2).toLocaleString();

		calculateRequiredFuel();
	}

	function calculateRequiredFuel() {
		const fuelConsumption = parseInt(document.getElementById('fuel-consumption').innerText);
		const distance = parseInt(document.getElementById('fuel-consumption-distance').innerText);

		if(isNaN(fuelConsumption) || isNaN(distance)) {
			document.getElementById('fuel-consumption-required').innerText = "Error";
			return;
		}

		if(distance === 0) {
			document.getElementById('fuel-consumption-required').innerText = 0;
			return;
		}

		const requiredFuel = Math.ceil(Math.log(fuelConsumption * distance) / Math.log(1.01));

		document.getElementById('fuel-consumption-required').innerText = requiredFuel;
	}

	function handleAllClick(button) {
		const avaliableResources = [];
		for(const resItem of document.querySelectorAll('.resourcebar-item')) {
			avaliableResources.push({
				id: resItem.dataset.resId,
				amount: parseInt(resItem.dataset.resAmount)
			});
		}

		const resourceId = button.parentElement.children.item(0).value;
		const amount = avaliableResources.find(res => res.id === resourceId)?.amount ?? 0;

		button.parentElement.children.item(1).value = amount;
	}
</script>