<script>
	import { deserialize, enhance } from '$app/forms';
	import Alert from '$lib/components/ui/Alert.svelte';
	import Button from '$lib/components/ui/Button.svelte';
	import Modal from '$lib/components/ui/Modal/Modal.svelte';
	import ModalTitle from '$lib/components/ui/Modal/ModalTitle.svelte';
	import ModalContent from '$lib/components/ui/Modal/ModalContent.svelte';
	import ModalFooter from '$lib/components/ui/Modal/ModalFooter.svelte';
	import shortenFileSize from '$lib/helper/shortenFileSize.js';
	import Exclamation from '$lib/icons/Exclamation.svelte';

	export let form;

	let open = false;
	let inProgress = false;
	let vorgang = '';
	const code_len = 8;
	let zugangscode = Math.random().toString(36).slice(2, 2+code_len);
	let case_existing = undefined;
	let name = '';
	/** @type {?string}*/
	let etag = null;
	/** @type {?FileList} */
	let files = null;

	$: inProgress = form === null;

	/** @type {?Record<string,any>}*/
	let formErrors;

	async function validateForm() {
		let data = new FormData();
		data.append('vorgang', vorgang);
		data.append('name', name);
		data.append('zugangscode', zugangscode)
		const response = await fetch('?/validate', { method: 'POST', body: data });
		/** @type {import('@sveltejs/kit').ActionResult} */
		const result = deserialize(await response.text());

		let success = true;
		if (result.type === 'success') {
			formErrors = null;
		} else {
			if (result.type === 'failure' && result.data) formErrors = result.data;
			success = false;
		}

		console.log('File', files);
		if (!files?.length) {
			formErrors = { file: 'Sie haben keine Datei ausgewählt.', ...formErrors };
			success = false;
		}

		if (!(await check_valid_glb_file())) {
			formErrors = { file: 'Keine gültige .GLD-Datei', ...formErrors };
			success = false;
		}

		return success;
	}

	async function getUrl() {
		let data = new FormData();
		data.append('vorgang', vorgang);
		data.append('name', name);
		if (files?.length === 1) {
			data.append('type', files[0].type);
			data.append('fileName', files[0].name);
		}
		const response = await fetch('?/url', { method: 'POST', body: data });
		/** @type {import('@sveltejs/kit').ActionResult} */
		const result = deserialize(await response.text());
		if (result.type === 'success') return result.data?.url;

		return null;
	}

	/** @param {MouseEvent} event*/
	async function buttonClick(event) {
		if (!(await validateForm())) {
			event.preventDefault();
			return;
		}
		const url = await getUrl();
		console.log('URL', url);
		open = true;
		inProgress = true;

		fetch(url, { method: 'PUT', body: files[0] })
			.then((response) => {
				inProgress = false;
				etag = '123';
				console.log('SUCCESS', response);
			})
			.catch((err) => {
				inProgress = false;
				etag = null;
				console.log('ERROR', err);
			});
	}

	function uploadSuccessful() {
		console.log('reset');
		open = false;
		vorgang = '';
		name = '';
		files = null;
	}

	// `val` is hex string
	function swap_endian(val) {
		// from https://www.geeksforgeeks.org/bit-manipulation-swap-endianness-of-a-number/

		let leftmost_byte = (val & eval(0x000000FF)) >> 0;
		let left_middle_byte = (val & eval(0x0000FF00)) >> 8;
		let right_middle_byte = (val & eval(0x00FF0000)) >> 16;
		let rightmost_byte = (val & eval(0xFF000000)) >> 24;

		leftmost_byte <<= 24;
		left_middle_byte <<= 16;
		right_middle_byte <<= 8;
		rightmost_byte <<= 0;

		let res = (leftmost_byte | left_middle_byte | right_middle_byte | rightmost_byte)

		return res
	}


	async function check_valid_glb_file() {
		// GLD Header, magic value 0x46546C67, identifies data as binary glTF, 4 bytes
		// little endian!
		const GLD_MAGIC = 0x46546C67;

		// big endian!
		let file = files[0];
		let file_header = file.slice(0, 4)
		let header_bytes = await file_header.bytes()
		let file_header_hex = '0x' + header_bytes.toHex().toString();


		if (GLD_MAGIC == swap_endian(file_header_hex)) {
			return true;
		} else {
			return false;
		}

	}

	// return true or false
	async function case_exists(case_no) {
		console.log('--- fired')
		// ping `/(angemeldet)/view` with caseNumber in POST body
		let url = '/view'
		let data = new FormData();
		data.append('caseNumber', case_no);
		const response = await fetch(url, { method: 'POST', body: data })

		const code = response.status;

		console.log(`+++ ${response.redirected}`)

		if (code == 303) {
			return true;
		}

		return false;
	}

</script>

<div class="mx-auto max-w-2xl">
	<div class="flex flex-col items-center justify-center w-full">
		<h1 class="text-xl">Datei zu Vorgang hinzufügen</h1>
	</div>

	<div>
		<div class="space-y-12">
			<div class="border-b border-gray-900/10 pb-12">
				<p class="mt-8 text-sm leading-6 text-gray-600">
					This information will be displayed publicly so be careful what you share.
				</p>

				<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8">
					<div>
						<label for="vorgang" class="block text-sm font-medium leading-6 text-gray-900"
							><span class="flex"
								>{#if formErrors?.vorgang}
									<span class="inline-block mr-1"><Exclamation /></span>
								{/if} Vorgang</span
							></label
						>
						<div class="mt-2">
							<div
								class="flex rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-indigo-600"
							>
								<input
									bind:value={vorgang}
									type="text"
									name="vorgang"
									id="vorgang"
									autocomplete={vorgang}
									class="block flex-1 border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
									on:input={() => case_exists(vorgang)}
								/>
							</div>
						</div>
						{#if formErrors?.vorgang}
							<p class="block text-sm leading-6 text-red-900 mt-2">{formErrors.vorgang}</p>
						{/if}
					</div>

					<div>
						<label for="name" class="block text-sm font-medium leading-6 text-gray-900"
							><span class="flex"
								>{#if formErrors?.name}
									<span class="inline-block mr-1"><Exclamation /></span>
								{/if} Name</span
							></label
						>
						<div class="mt-2">
							<div
								class="flex rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-indigo-600"
							>
								<input
									bind:value={name}
									type="text"
									name="name"
									id="name"
									autocomplete={name}
									class="block flex-1 border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
								/>
							</div>
						</div>
						{#if formErrors?.name}
							<p class="block text-sm leading-6 text-red-900 mt-2">{formErrors.name}</p>
						{/if}
					</div>

					<div>
						<label for="zugangscode" class="block text-sm font-medium leading-6 text-gray-900"
							><span class="flex"
								>{#if formErrors?.zugangscode}
									<span class="inline-block mr-1"><Exclamation /></span>
								{/if} Zugangscode</span
							></label
						>
						<div class="mt-2">
							<div
								class="flex rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-indigo-600"
							>
								<input
									bind:value={zugangscode}
									type="text"
									name="zugangscode"
									id="zugangscode"
									class="block flex-1 border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
								/>
							</div>
						</div>
						{#if formErrors?.code}
							<p class="block text-sm leading-6 text-red-900 mt-2">{formErrors.code}</p>
						{/if}
					</div>

					<div class="col-span-full">
						<label for="file" class="block text-sm font-medium leading-6 text-gray-900"
							><span class="flex"
								>{#if formErrors?.file}
									<span class="inline-block mr-1"><Exclamation /></span>
								{/if} Datei</span
							></label
						>
						<div
							class="mt-2 flex justify-center rounded-lg border border-dashed border-gray-900/25 px-6 py-10"
						>
							<div class="text-center">
								<svg
									class="mx-auto h-12 w-12 text-gray-300"
									viewBox="0 0 24 24"
									fill="currentColor"
									aria-hidden="true"
								>
									<path
										fill-rule="evenodd"
										d="M1.5 6a2.25 2.25 0 012.25-2.25h16.5A2.25 2.25 0 0122.5 6v12a2.25 2.25 0 01-2.25 2.25H3.75A2.25 2.25 0 011.5 18V6zM3 16.06V18c0 .414.336.75.75.75h16.5A.75.75 0 0021 18v-1.94l-2.69-2.689a1.5 1.5 0 00-2.12 0l-.88.879.97.97a.75.75 0 11-1.06 1.06l-5.16-5.159a1.5 1.5 0 00-2.12 0L3 16.061zm10.125-7.81a1.125 1.125 0 112.25 0 1.125 1.125 0 01-2.25 0z"
										clip-rule="evenodd"
									/>
								</svg>
								<div class="mt-4 flex text-sm leading-6 text-gray-600">
									<label
										for="file"
										class="relative cursor-pointer rounded-md bg-white font-semibold text-indigo-600 focus-within:outline-none focus-within:ring-2 focus-within:ring-indigo-600 focus-within:ring-offset-2 hover:text-indigo-500"
									>
										<span>Wähle eine Datei aus</span>
										<input id="file" bind:files name="file" type="file" class="sr-only" />
									</label>
									<p class="pl-1">oder ziehe sie ins Feld</p>
								</div>
								<p class="text-xs leading-5 text-gray-600">GLB Dateien bis zu 1GB</p>
								{#if files?.length}
									<div class="flex justify-center text-xs">
										<p class="mx-2">Datei: <span class="font-bold">{files[0].name}</span></p>
										<p class="mx-2">
											Größe: <span class="font-bold">{shortenFileSize(files[0].size)}</span>
										</p>
									</div>
								{/if}
							</div>
						</div>
						{#if formErrors?.file}
							<p class="block text-sm leading-6 text-red-900 mt-2">{formErrors.file}</p>
						{/if}
					</div>
				</div>
			</div>

			<div class="mt-6 flex items-center justify-end gap-x-6">
				<button type="button" class="text-sm font-semibold leading-6 text-gray-900">Cancel</button>
				<Button
					on:click={buttonClick}
					class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
					>Save</Button
				>
			</div>
		</div>
	</div>

	<Modal {open}
		><ModalTitle>Upload</ModalTitle><ModalContent>
			{#if inProgress}
				<p class="py-2 mb-1">Upload läuft...</p>
			{:else if etag}
				<Alert class="w-full">Upload erfolgreich</Alert>
			{:else}
				<Alert class="w-full" type="error">Fehler beim Upload</Alert>
			{/if}
		</ModalContent>
		<ModalFooter><Button disabled={inProgress} on:click={uploadSuccessful}>Ok</Button></ModalFooter>
	</Modal>
</div>
