<script lang="ts">
	import Select from '$lib/components/Input/Select.svelte';
	import Input from '$lib/components/Input/Input.svelte';
	import { createEventDispatcher, onMount } from 'svelte';
	import { env } from '$env/dynamic/public';
	import { rulesShort } from '$lib/rules';
	import { RegisterSchema } from './schema';
	import { dev } from '$app/environment';

	const dispatch = createEventDispatcher();

	const modalTimeoutSeconds = dev ? 0 : 30;

	// eslint-disable-next-line @typescript-eslint/no-empty-function
	let checkInputs = () => {};
	let playertype = 'java';
	let firstnameInput: HTMLInputElement;
	let lastnameInput: HTMLInputElement;
	let birthdayInput: HTMLInputElement;
	let phoneInput: HTMLInputElement;
	let usernameInput: HTMLInputElement;
	let privacyInput: HTMLInputElement;
	let logsInput: HTMLInputElement;
	let rulesInput: HTMLInputElement;
	onMount(() => {
		checkInputs = () => {
			let allInputs = [
				firstnameInput,
				lastnameInput,
				birthdayInput,
				usernameInput,
				privacyInput,
				logsInput,
				rulesInput
			];
			if (!allInputs.every((v) => v.value || v.checked)) {
				inputsInvalidMessage = 'Bitte fülle alle erforderlichen Felder aus';
			} else {
				inputsInvalidMessage = null;
			}
		};
	});

	async function sendRegister() {
		// eslint-disable-next-line no-async-promise-executor
		registerRequest = new Promise<void>(async (resolve, reject) => {
			const parseResult = RegisterSchema.safeParse(
				Object.fromEntries(new FormData(document.forms[0]))
			);

			if (!parseResult.success) {
				reject(Error(parseResult.error.issues.map((i) => i.message).join('\n\n')));
				return;
			}

			const response = await fetch(`${env.PUBLIC_BASE_PATH}/register`, {
				method: 'POST',
				body: JSON.stringify(Object.fromEntries(new FormData(document.forms[0])))
			});
			if (response.ok) {
				dispatch('submit', {
					firstname: firstnameInput.value,
					lastname: lastnameInput.value,
					birthday: birthdayInput.valueAsDate,
					phone: phoneInput.value,
					username: usernameInput.value,
					edition: playertype == 'java' ? 'Java (PC)' : 'Bedrock (Konsolen und Handys)'
				});
				resolve();
			} else if (response.status < 500) {
				reject(Error((await response.json()).message));
			} else {
				reject(Error(`${response.statusText} (${response.status})`));
			}
		}).catch((e) => {
			errorMessage = (e as Error).message;
			registerRequest = null;
		});
	}

	let rulesAccepted = false;
	let rulesModal: HTMLDialogElement;
	let rulesModalSecondsOpened = 0;
	let rulesModalTimer: number | NodeJS.Timeout | undefined = undefined;

	let inputsInvalidMessage: string | null = 'Bitte fülle alle erforderlichen Felder aus';
	let registerRequest: Promise<void> | null = null;

	let errorMessage: string = '';
</script>

<h1 class="text-center text-3xl lg:text-5xl">Anmeldung</h1>
<form id="form" on:input={checkInputs} on:submit|preventDefault={sendRegister}>
	<div class="divider">Persönliche Angaben</div>
	<div class="mx-2 grid grid-cols-1 sm:grid-cols-2 gap-y-4">
		<Input
			id="firstname"
			name="firstname"
			type="text"
			required={true}
			bind:inputElement={firstnameInput}
		>
			<span slot="label">Vorname</span>
		</Input>
		<Input
			id="lastname"
			name="lastname"
			type="text"
			required={true}
			bind:inputElement={lastnameInput}
		>
			<span slot="label">Nachname</span>
		</Input>
		<Input
			id="birthday"
			name="birthday"
			type="date"
			required={true}
			bind:inputElement={birthdayInput}
		>
			<span slot="label">Geburtstag</span>
			<span slot="notice">Die Angabe hat keine Auswirkungen auf das Spielgeschehen</span>
		</Input>
		<Input
			id="telephone"
			name="telephone"
			type="tel"
			bind:inputElement={phoneInput}
			pattern={new RegExp(/^[+()\s/\d]+$/)}
		>
			<span slot="label">Telefonnummer</span>
			<p slot="notice">
				Diese nutzen wir, um Dich in der Whatsapp-Gruppe zuzuordnen und kontaktieren zu können.
				<br />
				<b>Die Angabe ist freiwillig, hilft den Administratoren jedoch sehr!</b>
			</p>
		</Input>
	</div>
	<div class="divider">Spiel</div>
	<div class="mx-2 grid grid-cols-1 sm:grid-cols-2 gap-y-4">
		<Input
			id="username"
			name="username"
			type="text"
			required={true}
			bind:inputElement={usernameInput}
		>
			<span slot="label">Minecraft-Spielername</span>
		</Input>
		<Select
			id="playertype"
			name="playertype"
			label="Edition"
			bind:value={playertype}
			required={true}
		>
			<option value="java">Java Edition (PC)</option>
			<option value="bedrock">Bedrock Edition (Konsolen und Handys)</option>
		</Select>
	</div>
	<div class="divider" />
	<div class="mx-2 grid gap-y-3 mb-6">
		<div class="flex gap-4">
			<Input
				id="privacy"
				name="privacy"
				type="checkbox"
				required={true}
				bind:inputElement={privacyInput}
			/>
			<label for="privacy">
				<span>
					Ich bin mit der Speicherung meiner in der Anmeldung angegebenen, persönlichen Daten
					einverstanden. Siehe <a class="link" href="https://mhsl.eu/id.html" target="_blank"
						>Datenschutz</a
					>
				</span>
				<span class="text-red-700">*</span>
			</label>
		</div>
		<div class="flex gap-4">
			<Input id="logs" name="logs" type="checkbox" required={true} bind:inputElement={logsInput} />
			<label for="logs">
				<span>
					Ich bin mit der Speicherung in Form von Logs aller meiner, beim Spielen anfallenden,
					persönlichen Daten durch den Server einverstanden
				</span>
				<span class="text-red-700">*</span>
				<br />
				<p class="text-[.75rem]">
					Dies betrifft jede Interaktion im Spiel und zugehörige Daten wie z.B. Chatnachrichten
					welche vom Minecraft Client an den Server übermittelt werden
				</p>
			</label>
		</div>
		<div class="flex gap-4">
			<Input
				id="rules"
				name="rules"
				type="checkbox"
				required={true}
				on:input={(e) => {
					if (!rulesAccepted) {
						e.detail.target.checked = false;
						rulesModal.show();
						rulesModalTimer = setInterval(() => rulesModalSecondsOpened++, 1000);
					}
				}}
				bind:inputElement={rulesInput}
			/>
			<label for="rules">
				Ich bin mit den <button
					class="link"
					on:click|preventDefault={() => {
						rulesModal.show();
						rulesModalTimer = setInterval(() => rulesModalSecondsOpened++, 1000);
					}}>Regeln</button
				>
				einverstanden und achte sie
				<span class="text-red-700">*</span>
			</label>
		</div>
	</div>
	<div
		class={inputsInvalidMessage !== null ? 'tooltip tooltip-top' : 'grid w-min'}
		data-tip={inputsInvalidMessage}
	>
		<div class="row-[1] col-[1]">
			<Input
				id="submit"
				type="submit"
				value="Anmeldung absenden"
				disabled={inputsInvalidMessage !== null || registerRequest !== null}
			/>
		</div>
		{#key registerRequest}
			{#if registerRequest}
				{#await registerRequest}
					<span
						class="relative top-[calc(50%-12px)] left-[calc(50%-12px)] row-[1] col-[1] loading loading-ring"
					/>
				{/await}
			{/if}
		{/key}
	</div>
</form>

<dialog
	class="modal"
	on:close={() => {
		clearInterval(rulesModalTimer);
		rulesModalTimer = undefined;
	}}
	bind:this={rulesModal}
>
	<form method="dialog" class="modal-box flex max-w-[95%] md:max-w-[90%] lg:max-w-[75%]">
		<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
		<div class="overflow-auto mt-5">
			<div class="mb-4">
				<div class="collapse collapse-arrow">
					<input type="checkbox" autocomplete="off" checked />
					<div class="collapse-title">
						<p>0. Vorwort</p>
					</div>
					<div class="collapse-content">
						<p>{rulesShort.header}</p>
						<p class="mt-1 text-[.75rem]">{rulesShort.footer}</p>
					</div>
					<span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600" />
				</div>
				{#each rulesShort.sections as section, i}
					<div class="collapse collapse-arrow">
						<input type="checkbox" autocomplete="off" />
						<div class="collapse-title">
							<p>{i + 1}. {section.title}</p>
						</div>
						<div class="collapse-content">
							<p>{section.content}</p>
						</div>
					</div>
					<span class="block w-full h-[1px] mx-auto mb-1 bg-gray-600" />
				{/each}
			</div>
			<!-- svelte-ignore a11y-no-static-element-interactions a11y-click-events-have-key-events -->
			<div
				class="relative w-min"
				title={rulesModalSecondsOpened < modalTimeoutSeconds
					? `Regeln können in ${Math.max(
							modalTimeoutSeconds - rulesModalSecondsOpened,
							0
						)} Sekunden akzeptiert werden`
					: ''}
				on:click={() => {
					if (rulesModalSecondsOpened < modalTimeoutSeconds) {
						errorMessage =
							'Bitte lies die Regeln aufmerksam durch. Du kannst erst in einigen Sekunden fortfahren.';
					}
				}}
			>
				<div class="absolute top-0 left-0 h-full w-full overflow-hidden rounded-lg">
					<div
						style="width: {Math.min((rulesModalSecondsOpened / modalTimeoutSeconds) * 100, 100)}%"
						class="h-full bg-base-300"
					/>
				</div>
				<Input
					id="rules-accept"
					type="submit"
					value="Akzeptieren"
					disabled={rulesModalSecondsOpened < modalTimeoutSeconds}
					containerClass="bg-transparent z-[1] relative"
					on:click={() => {
						rulesAccepted = true;
						rulesInput.checked = true;
						checkInputs();
					}}
				/>
			</div>
		</div>
	</form>
	<form method="dialog" class="modal-backdrop bg-[rgba(0,0,0,.3)]">
		<button>close</button>
	</form>
</dialog>

{#if errorMessage}
	<dialog class="modal" on:close={() => setTimeout(() => (errorMessage = ''), 200)} open>
		<form method="dialog" class="modal-box z-50">
			<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
			<h3 class="font-bold text-2xl">Achtung</h3>
			<p class="py-4 whitespace-pre-line">{errorMessage}</p>
		</form>
		<form method="dialog" class="modal-backdrop bg-[rgba(0,0,0,.2)]">
			<button>close</button>
		</form>
	</dialog>
{/if}
