<script lang="ts">
	// *** Import Svelte core
	import { createEventDispatcher, onDestroy, onMount } from 'svelte';
	// import 'html5-qrcode';
	import { Html5Qrcode, Html5QrcodeScannerState, Html5QrcodeSupportedFormats } from 'html5-qrcode';

	// *** Import Aether core variables and functions
	import { api } from '$lib/api/api';
	import { ae_api } from '$lib/stores/ae_stores';

	// *** Import Aether core components
	// import Element_input from './element_input.svelte';
	// import ae from '/element_input.svelte';
	// import Input_element from '/element_input.svelte';

	// *** Import Aether module variables and functions

	// *** Import Aether module components

	// *** Export/Exposed variables and functions for component
	export let start_qr_scanner: boolean = true;
	export let show_pause_btn: boolean = false; // pause and resume buttons
	export let show_qr_manual_text_entry_option: boolean = false;
	export let show_qr_manual_badge_id_entry_option: boolean = false;
	export let show_qr_scan_result: boolean = true;

	export let qr_fps = 10;
	export let qr_viewfinder_width = 275; // 275 seems good... Need to not let the this be larger than the container which changes based on the width of the screen/window.
	export let qr_facing_mode = 'environment'; // environment, user, { exact: 'environment'}, { exact: 'user'}

	const dispatch = createEventDispatcher();

	// *** Set initial variables
	let scanning_status: string = 'not_started';
	let qr_scan_result: null | string = null;
	let qr_found_text: null | string = null;
	let qr_entered_text: null | string = null;
	let qr_entered_badge_id: null | string = null;
	let show_qr_manual_entry: null | boolean = null;
	let disable_submit_badge_id_btn: boolean = true;

	let user_media_status = 'not_requested';

	let debug_comment: string = 'Debugging QR Scanner';
	let debug_info: any;

	let html5_qr_code: any | null | string = null;

	// let qr_scan_cfg = { fps: 10, qrbox: 400 }; // default was 250 and using 300 when 600px
	let qr_scan_cfg = { fps: qr_fps, qrbox: qr_viewfinder_width }; // 275 seems good... Need to not let the this be larger than the container which changes based on the width of the screen/window.

	// const html5QrCode = new Html5Qrcode(
	//     'qr_scanner_viewfinder', { formatsToSupport: [ Html5QrcodeSupportedFormats.QR_CODE ] }
	// );

	onMount(() => {
		console.log('** Element Mounted: ** QR Scanner');

		// html5_qr_code = new Html5Qrcode(
		//     'qr_scanner_viewfinder', { formatsToSupport: [ Html5QrcodeSupportedFormats.QR_CODE ] }
		// );

		// navigator.mediaDevices.getUserMedia({video: true})
		// .then(get_user_media_success, get_user_media_error);
		// console.log('** Element Mounted: ** QR Scanner - getUserMedia in setTimeout');
	});

	onDestroy(async () => {
		console.log('** Element Destroyed: ** QR Scanner');

		qr_scan_result = null;
		qr_found_text = null;

		await handle_stop_qr_scanning();
	});

	var get_user_media_success = function (error: any) {
		console.log('Camera access allowed');
		user_media_status = 'allowed';

		debug_comment = 'Camera Access Allowed';
		debug_info = JSON.stringify(error);

		if (html5_qr_code) {
			console.log('html5_qr_code object found. Clearing and creating new Html5Qrcode...');
			debug_info = 'html5_qr_code object found. Clearing and creating new Html5Qrcode...';
			html5_qr_code.clear();
			// document.getElementById('qr_scanner_viewfinder').classList.remove('d_none');
		} else {
			console.log('html5_qr_code not found. Creating new Html5Qrcode...');
			debug_info = 'html5_qr_code not found. Creating new Html5Qrcode...';

			html5_qr_code = new Html5Qrcode('qr_scanner_viewfinder', {
				formatsToSupport: [Html5QrcodeSupportedFormats.QR_CODE]
			});
		}

		// html5_qr_code = new Html5Qrcode(
		//     'qr_scanner_viewfinder', { formatsToSupport: [ Html5QrcodeSupportedFormats.QR_CODE ] }
		// );

		debug_info = 'new Html5Qrcode for element id=qr_scanner_viewfinder';

		if (start_qr_scanner && 1 == 2) {
			console.log('Ready to start QR scanning! (after x500ms)');
			debug_comment = 'Starting QR after 500ms...';
			debug_info = 'Ready to start QR scanning! (after 2500ms)';
			setTimeout(() => {
				console.log('Inside QR scanning timeout after x500ms...');
				handle_start_qr_scanning_trust();
			}, 2500);
			console.log('Started QR scanning after x500ms...');
		}

		// let subject = 'Camera Access Allowed';
		// let message = error;
		// send_init_confirm_email(subject, message);

		console.log('Dispatching qr_camera');
		debug_info = 'Dispatching qr_camera';

		dispatch('qr_camera', {
			status: 'allowed'
		});
	};

	var get_user_media_error = function (error: any) {
		if (error.name == 'NotAllowedError') {
			console.log('Camera access not allowed!');
			user_media_status = 'denied';

			debug_comment = 'Camera Access Denied';
			debug_info = JSON.stringify(error);
			// alert('Error trying to start camera');
			// alert(error);

			let subject = 'Camera Access Denied';
			let message = error;
			send_init_confirm_email(subject, message);

			// dispatch('qr_camera', {
			//     status: 'denied',
			// });
		}
	};

	// $: if (start_qr_scanner && user_media_status == 'allowed' && (scanning_status == 'not_started' || scanning_status == 'paused')) {
	//     console.log('START QR SCANNING');
	//     handle_start_qr_scanning();
	// } else {
	//     // console.log('STOP QR SCANNING');
	//     // handle_stop_qr_scanning();
	// }

	// $: if (mounted && start_qr_scanner) {
	//     console.log('START QR SCANNING');
	//     handle_start_qr_scanning();
	// } else if (mounted && !start_qr_scanner) {
	//     console.log('STOP QR SCANNING');
	//     handle_stop_qr_scanning();
	// }

	async function handle_start_qr_scanning_trust() {
		console.log('*** handle_start_qr_scanning_trust() ***');

		qr_scan_result = null;
		qr_found_text = null;

		debug_comment = 'Starting trusting QR scanning...';

		debug_info = 'Just start!';
		await html5_qr_code.clear();
		html5_qr_code
			.start(
				{ facingMode: qr_facing_mode },
				qr_scan_cfg,
				handle_qr_scan_success,
				handle_qr_scan_error
			)
			.then((ignore: any) => {
				console.log('Scanning has started');
				scanning_status = 'scanning';

				debug_info = 'Scanning has started';

				// let subject = 'QR Scanning Started';
				// let message = ignore;
				// send_init_confirm_email(subject, message);

				return true;
			})
			.catch((err) => {
				console.log('There was an error while trying to start the QR scanner');
				scanning_status = 'start_error';

				debug_info = 'Error starting scanner: ' + JSON.stringify(err);

				// let subject = 'QR Scanning Start Error';
				// let message = err;
				// send_init_confirm_email(subject, message);

				// Error getting userMedia, error = NotReadableError: Could not start video source

				return false;
			});

		return true;
	}

	async function handle_stop_qr_scanning() {
		start_qr_scanner = false;

		if (!html5_qr_code) {
			console.log('html5_qr_code object found. Nothing to stop?');
			scanning_status = 'not_started';
			return false;
		}

		await html5_qr_code.stop();
		scanning_status = 'not_started';

		await html5_qr_code.clear();
		return true;
	}

	// Callback function for QrcodeSuccessCallback (decodedText: string, result: Html5QrcodeResult)
	function handle_qr_scan_success(decoded_text, decoded_result) {
		console.log(`*** handle_qr_scan_success() *** QR scanned = ${decoded_text}`, decoded_result);

		qr_scan_result = decoded_text; // NOTE: decoded_result is not currently used by html5-qrcode
		qr_found_text = decoded_text;

		dispatch('qr_scan_result', {
			result: qr_scan_result, // This text will need to be parsed to get more info.
			text: qr_found_text, // This text will need to be parsed to get more info.
			entry_method: 'QR'
		});

		// handle_pause_qr_scanning();
		handle_stop_qr_scanning();
	}

	// Callback function for QrcodeErrorCallback (errorMessage: string, error: Html5QrcodeError)
	// NOTE: Most of the time this is normal and not an actual error. It just did not find something to scan.
	function handle_qr_scan_error(qr_error_message, qr_code_error) {
		// console.log('*** handle_qr_scan_error() ***');

		if (qr_code_error.type) {
			console.log(`Error scanning code = ${qr_error_message}`, qr_code_error);
			return;
		}
	}

	$: if (
		qr_entered_badge_id &&
		qr_entered_badge_id.length >= 11 &&
		qr_entered_badge_id &&
		qr_entered_badge_id.length <= 14
	) {
		disable_submit_badge_id_btn = false;
	} else {
		disable_submit_badge_id_btn = true;
	}

	function handle_qr_manual_entry() {
		console.log('*** handle_qr_manual_entry() ***');

		if (qr_entered_text) {
			console.log(`QR entered text = ${qr_entered_text}`);
		} else if (qr_entered_badge_id) {
			console.log(`QR entered badge ID = ${qr_entered_badge_id}`);
			qr_entered_text = `OBJ:ot:event_badge,oi:${qr_entered_badge_id}`;
			console.log(`Parse to proper QR badge ID = ${qr_entered_text}`);
		}

		// html5_qr_code.stop().then((ignore) => {
		//     console.log('Scanning has stopped');
		//     document.getElementById('qr_scanner_viewfinder').classList.add('d_none');
		// }).catch((err) => {
		//     console.log('There was an error while trying to stop the scanning');
		// });

		qr_scan_result = qr_entered_text;

		dispatch('qr_scan_result', {
			result: qr_scan_result,
			entry_method: 'manual'
		});

		qr_scan_result = null;
		qr_entered_text = null;
	}

	function send_init_confirm_email(subject, message) {
		console.log(`*** send_init_confirm_email() *** ${subject}`);

		let to_email = 'scott.idem+skdev@oneskyit.com';

		// let origin_url = encodeURI(`${data.url.origin}`);

		let full_subject = `${subject} Aether QR Scanner Debugging`;

		let body_html = `
    <div>Scott,
    <p>This is an automatic debug email from the Aether QR scanner.</p>
    </div>

    <br>

    <div>
    Message:<br>
    <pre>
    ${JSON.stringify(message)}
    </pre>
    </div>
    `;

		api.send_email({
			api_cfg: $ae_api,
			from_email: 'noreply+ae_qr_debug@oneskyit.com',
			from_name: 'AE QR Debug',
			to_email: to_email,
			subject: full_subject,
			body_html: body_html
		});
	}
</script>

<section
	class="ae_element qr_scanner border-2 border-slate-500/10 space-y-2 flex flex-col gap-1 justify-center items-center min-w-full max-w-full"
	class:not_started={scanning_status == 'not_started'}
	class:paused={scanning_status == 'paused'}
	class:scanning={scanning_status == 'scanning'}
>
	<!-- <header>
        <h2>QR Scanner</h2>
    </header> -->

	<!-- <fieldset class=""> -->
	<!-- <legend class="d_none">QR Scanner:</legend> -->

	<div class="ae_container qr_scanning_container">
		<div class="ae_options flex flex-row justify-center items-center gap-1 m-1">
			<button
				type="button"
				on:click={() => {
					navigator.mediaDevices
						.getUserMedia({ video: true })
						.then(get_user_media_success, get_user_media_error);
				}}
				class="ae_btn__allow_camera btn btn-sm preset-tonal-primary"
			>
				<span class="fas fa-camera mx-1"></span>
				Allow Camera Access
			</button>

			<button
				type="button"
				on:click={() => {
					handle_start_qr_scanning_trust();
					// Select back camera or fail with `OverconstrainedError`.
					// html5_qr_code.start({ facingMode: { exact: "environment"} }, config, qrCodeSuccessCallback);
				}}
				class="ae_btn__start btn btn-sm preset-tonal-primary"
			>
				<span class="fas fa-qrcode mx-1"></span>
				Start Scanning
			</button>

			<!-- <button
                on:click={ () => {
                    html5_qr_code.start({ facingMode: { exact: "environment"} }, config, qrCodeSuccessCallback);
                }}
                class="ae_btn__resume btn btn-sm variant-soft-primary">
                <span class="fas fa-play"></span>
                Resume
            </button> -->

			{#if scanning_status == 'scanning'}
				<button
					on:click={handle_stop_qr_scanning}
					class="ae_btn__stop btn btn-sm preset-tonal-secondary"
				>
					<span class="fas fa-crosshairs fa-spin opacity-50 m-1"></span>
					<!-- <span class="fas fa-stop-circle m-1"></span> -->
					Stop
				</button>
			{/if}
		</div>

		<div
			id="qr_scanner_viewfinder"
			class="qr_scanner_viewfinder grow flex flex-col justify-center items-center"
			style=""
		></div>
		<!-- width: 600px -->
	</div>

	{#if show_qr_manual_text_entry_option}
		<div class="ae_container qr_manual_entry text_entry">
			{#if show_qr_manual_entry}
				<label for="entered_text" class="">Enter text</label>
				<input type="text" name="entered_text" id="entered_text" bind:value={qr_entered_text} />
				<button on:click={handle_qr_manual_entry} class="btn btn-md preset-tonal-warning"
					><span class="fas fa-paper-plane"></span> Submit Text</button
				>

				<div class="search_by_text">
					<input
						type="text"
						placeholder="Name or Email"
						label="Name or Email"
						value={search_query_str}
						focus={true}
						on:oninput={handle_oninput_search_query_str}
					/>
				</div>
			{:else}
				<button
					on:click={() => {
						handle_stop_qr_scanning();
						show_qr_manual_entry = true;
					}}
					class="btn btn-md preset-tonal-warning m-1"
				>
					<span class="fas fa-keyboard mx-1"></span> Enter Text
				</button>
			{/if}
		</div>
	{/if}

	{#if show_qr_manual_badge_id_entry_option}
		<div class="ae_container qr_manual_entry badge_id_entry">
			{#if show_qr_manual_entry}
				<form on:submit|preventDefault={() => handle_qr_manual_entry} class="flex">
					<!-- <label for="entered_badge_id" class="">Enter badge ID</label>
                    <input type="text" name="entered_badge_id" id="entered_badge_id" bind:value="{qr_entered_badge_id}"> -->

					<input
						bind:value={qr_entered_badge_id}
						type="text"
						name="entered_badge_id"
						id="entered_badge_id"
						required
						placeholder="Enter Badge ID"
						class="input max-w-52"
					/>

					<button
						type="submit"
						on:click={handle_qr_manual_entry}
						disabled={disable_submit_badge_id_btn}
						class="btn btn-md preset-tonal-primary border border-primary-500 m-1"
						class:btn_default={disable_submit_badge_id_btn}
						class:btn_primary={!disable_submit_badge_id_btn}
					>
						<span class="fas fa-paper-plane mx-1"></span> Submit Badge ID
					</button>
				</form>
			{:else}
				<button
					on:click={() => {
						handle_stop_qr_scanning();
						show_qr_manual_entry = true;
					}}
					class="btn btn-md preset-tonal-secondary m-1"
				>
					<span class="fas fa-keyboard mx-1"></span> Enter Badge ID
				</button>
			{/if}
		</div>
	{/if}

	{#if show_qr_scan_result && qr_scan_result}
		<div class="ae_container qr_scan_result">
			<span class="label">Raw Result:</span>
			<span id="qr_scan_result_value" class="value">{qr_scan_result}</span>
		</div>
	{/if}

	<!-- {debug_comment ?? 'Debugging QR Scanner'}
        {#if debug_info}
        <div class="ae_container debug_info">
            <span class="label">Debug Info:</span>
            <span class="value">{debug_info}</span>
        </div>
        {/if} -->
	<!-- </fieldset> -->

	<p>
		v2 - Try pressing the "Allow Camera Access" button and then the "Start Scanning" button if it
		does not start on its own. This fix is not perfect. A permanent solution is actively being
		worked on in the development version.
	</p>
</section>

<style>
	.not_started {
		background-color: hsla(0, 100%, 75%, 0.3);
		border-color: hsla(0, 100%, 75%, 0.6);
	}
	.paused {
		background-color: hsla(60, 100%, 75%, 0.3);
		border-color: hsla(60, 100%, 75%, 0.6);
	}
	.scanning {
		background-color: hsla(120, 100%, 75%, 0.3);
		border-color: hsla(120, 100%, 75%, 0.6);
	}

	.qr_scanner {
		/* outline: solid thin pink; */

		max-width: 100vw;

		/* overflow-x: scroll; */

		display: flex;
		flex-direction: column;
		/* flex-wrap: wrap; */

		justify-content: flex-start;
		align-items: center; /* center */
		align-content: stretch;
	}

	.ae_element.qr_scanner div.qr_scanner_viewfinder {
		/* max-width: 100vw; */
		/* contain: content; */
		/* contain: contain; */
	}

	.qr_scanner .qr_scanner_viewfinder {
		/* outline: dashed medium blue; */
		min-width: 400px;

		width: 100%;
		/* max-width: 100%; */
		max-width: 500px;
		/* max-width: 100vw; */
		/* outline: solid thin red; */

		contain: contain;
		overflow-x: scroll;
	}

	@media (max-width: 767px) {
		.qr_scanner .qr_scanner_viewfinder {
			/* outline: dashed medium red; */
			min-width: 80vw;
			/* width: 100%; */
			/* max-width: 100%; */
			/* max-width: 450px; */
			max-width: 100vw;

			margin: 0;
			padding: 0;
		}
	}
</style>
