<script lang="ts">
	import { createEventDispatcher, onMount } from 'svelte';

	import util from './utilities.js';

	// import Select_element_lu from './element_select_lu.svelte';

	/* *** BEGIN *** Core input settings */

	export let id_random: string = ''; // OSIT Aether specific
	export let obj_type: string = ''; // OSIT Aether specific
	export let obj_prop_name: string = ''; // OSIT Aether specific

	export let use_name_prefix: boolean = false;
	export let name: string = use_name_prefix ? `${obj_type}__${obj_prop_name}` : obj_prop_name;
	// console.log(name);
	export let id: string = `${obj_type}__${obj_prop_name}--${id_random}`; // Same as the value for "for"
	// console.log(id);

	export let value: null | boolean | number | string = null; // The current value of the property
	console.log(`Input name=${name} value=${value}`);
	export let default_value: null | boolean | number | string = null; // The default value for when value is ''
	// console.log('Default Value:', default_value);
	export let original_value: null | boolean | number | string = value; // The original value
	console.log('Original Value', original_value);
	export let data_type: string = typeof value; // boolean, number, string, json
	console.log('Data Type:', data_type);

	// hidden, text, email, date, number, select, checkbox, radio, textarea, etc
	export let type: string = 'text'; // Input type

	let set_input_type = (node) => {
		node.type = 'text';
	};
	let input_element_type_list = ['checkbox', 'date', 'email', 'hidden', 'number', 'text'];
	if (input_element_type_list.includes(type)) {
		set_input_type = (node) => {
			node.type = type;
		};
	} else {
	}

	console.log(`Input name=${name} value=${value} type=${type}`);

	export let disabled: boolean = false; // attribute format: disabled
	export let readonly: boolean = false; // attribute format: readonly="readonly"
	export let required: boolean = false; // attribute format: required="required"
	export let pattern: null | string = null;
	export let focus: boolean = false;

	/* *** END *** Core input settings */

	/* *** BEGIN *** Container content, layout, and behavior */

	// Input element specific label and placeholder
	export let label: string = '';
	export let label_date: string = 'Date';
	export let label_time: string = 'Time';

	export let placeholder: string = label;

	// Input description for container
	export let description: string = ''; // Description

	// Layout and style
	export let content_layout: string = ''; // Default empty is label wrap first, label_start, label_end, floating_input

	export let class_li: string[] = []; // Classes for the input element
	export let style: string = ''; // Style for the input element
	export let display: string = ''; // Default empty is inline. inline, block, inline-block, break (break after)

	export let label_class_li: string[] = [];
	export let label_style: string = '';
	export let label_display: string = ''; // Default empty is inline. inline, block, inline-block, break (break after)
	export let label_location: string = 'start'; // start, end

	export let description_location: string = 'end'; // start, end

	export let container_class_li: string[] = []; // Classes for the container element
	export let container_style: string = '';
	export let container_display: string = ''; // Default empty is div block. inline, block, inline-block, break (break after)

	export let multipart_class_li: string[] = [];

	export let input_mode: null | string = null; // This is for special/custom modes like a rich text editor or search.
	console.log(`Input input_mode=${input_mode}`);

	/* *** END *** Container content, layout, and behavior */

	/* *** BEGIN *** Input type specific */

	// For checkbox, radio, and select option
	export let option_li: any[] = []; // For checkbox, radio, and select inputs. Not specific to select options. List of key value pairs.
	export let option_none: boolean = false; // If set to true then it will add an option using the select_option_none_text value
	export let option_none_text: string = '-- Not Selected --'; // If set to true then it will add an option using the select_option_none_text value

	// For textarea
	export let size: number = null;
	export let rows: number = 3;
	export let cols: number = 80;
	if (type == 'textarea') {
		console.log(`Input textarea size=${size} rows=${rows} cols=${cols}`);
	}

	// For custom date_time. Not "date" or "time" input type only.
	export let date_time_tz: null | string = null;
	let value_datetime = null;
	let value_date = null;
	let value_time = null;

	if (type == 'date_time' && value) {
		console.log(`date_time value: ${value}`);
		value_datetime = new Date(value + 'Z'); // Append the Z so it knows it is UTC (YYY-MM-DDTHH:mm:ssZ)
		console.log(value_datetime);

		value_datetime = util.iso_datetime_formatter(value_datetime, 'datetime_iso');
		value_date = util.iso_datetime_formatter(value_datetime, 'date_iso');
		value_time = util.iso_datetime_formatter(value_datetime, 'time_iso');
		// value_date = value_datetime.toLocaleDateString();
		// value_date = value_datetime.toISOString();
		// value_time = value_datetime.toLocaleTimeString();
		// value_time = value_datetime.toISOString();
	} else if (type == 'date_time') {
		console.log('No datetime value passed');
	}
	if (type == 'date_time') {
		console.log(
			`Input date_time value_datetime=${value_datetime} value_date=${value_date} value_time=${value_time} date_time_tz=${date_time_tz}`
		);
	}

	/* *** END *** Input type specific */

	/* THIS NEEDS TO BE CLEANED UP */
	let multipart_style;
	let label_begin;
	let checkbox_none;
	let checked;
	let checkbox_none_text;
	let checkbox_li;
	let radio_option_class_li;
	let radio_none;
	let radio_none_text;
	let radio_li;
	let value_new_line;
	let select_option_none;
	let select_option_li_lu_name;
	let select_option_li;
	let select_option_none_text;
	/* ^^^ THIS NEEDS TO BE CLEANED UP ^^^ */

	const dispatch = createEventDispatcher();

	// type Input = {
	//   name: string;
	//   value: number;
	// };
	// let input: Input;

	/*
	 * container_element: span, div, section
	 * container_class_li: []
	 * content_layout: inline, break, bs_floating
	 * content_order: label_value_description, value_label_description, label_description_value
	 * label_class_li: []
	 * class_li: []
	 * start_desc: string
	 * end_desc: string
	 *
	 */

	onMount(() => {
		console.log(
			`** Element Mounted: ** Element Input v2: ${obj_type} ${obj_prop_name}; type=${data_type}; value=${value}`
		);

		if (input_mode == 'editor_basic_200') {
			rich_editor();
		}
	});

	// $: if (value) {
	//     console.log(`input name=${name} value=${value}`);
	//     console.log(typeof value);
	// } else if (typeof value === 'undefined') {
	//     console.log(`input name=${name} value=undefined; resetting to ''`);
	//     value = '';
	// }

	$: if (disabled) {
		disabled = true;
	} // else { disabled=false; }
	$: if (readonly) {
		readonly = true;
	} // else { readonly=false; }
	$: if (required) {
		required = true;
	} // else { required=true; }

	$: if (data_type) {
		console.log(`Input value data_type=${data_type}`);
	} else if (data_type == 'json') {
		console.log(`Need to convert JSON object to string.`);
		if (typeof value === 'object') {
			value = JSON.stringify(value);
			console.log(`Value as data type (${data_type}): ${value}`);
		} else {
			console.log('Value is not an object type');
			console.log(typeof value);
		}
	}

	// // input_mode options: null or '' assume 'text', 'none', 'text', 'tel', 'url', 'email', 'numeric', 'decimal', and 'search'
	// $: if (input_mode === null || input_mode == '') {
	//     input_mode = 'text';
	// } else if (input_mode == 'json') {
	// } else if (input_mode == 'editor_basic_200') {
	// }
	// console.log(`input_mode=${input_mode}`);

	$: if (container_display == '' || container_display == 'block') {
		console.log(`input name=${name} container_display=${container_display}`);
		// NOTE: Using a div will be displayed as block by default
	} else if (container_display == 'inline') {
		console.log(`input name=${name} container_display=${container_display}`);
		container_class_li.push('container_inline');
		container_style = 'display: inline;';
	} else if (container_display == 'inline-block') {
		console.log(`input name=${name} container_display=${container_display}`);
		container_class_li.push('container_inline_block');
		container_style = 'display: inline-block;';
	} else if (typeof container_display === 'undefined') {
		console.log(`input name=${name} container_display=${container_display}`);
	}

	$: if (content_layout == '' || content_layout == 'label_begin') {
		console.log(`input name=${name} content_layout=${content_layout}`);
		// label_begin = true;
	} else if (content_layout == 'label_end') {
		console.log(`input name=${name} content_layout=${content_layout}`);
		// label_begin = false;
	} else if (content_layout == 'floating_input') {
		console.log(`input name=${name} content_layout=${content_layout}`);
		// label_begin = false;

		if (type != 'date_time') {
			container_class_li.push('form-floating'); // set the container class list
		} else {
			multipart_class_li.push('form-floating'); // set the container with multi input parts class list
		}

		if (type === 'select') {
			class_li.push('form-select'); // set the select class list
		} else {
			console.log('Make form-control???');
			class_li.push('form-control'); // set the input, select, textarea class list
		}

		if (type === 'textarea') {
			let estimate_row_rem = rows + 5.5;
			style = `height: calc(2px + ${estimate_row_rem}rem);`;
		}
	} else if (typeof content_layout === 'undefined') {
		console.log(`input name=${name} content_layout=${content_layout}`);
	}

	// function handle_oninput_dispatch() {
	//     console.log(input);
	//     dispatch('oninput', {
	//         name: input.name,
	//         value: input.value,
	//     });
	// }

	function handle_oninput_dispatch(event) {
		console.log(event.target);
		console.log(value);
		dispatch('oninput', {
			name: event.target.name,
			value: event.target.value
		});
	}

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

		// let test_element = $('.editor_basic_200');
		// console.log(test_element);

		// let textarea_element = document.querySelector('.editor_basic_200');

		// let toolbar_element = document.querySelector('.quilljs_toolbar');
		// console.log(toolbar_element);

		let editor_element = document.querySelector('.quilljs_editor');
		console.log(editor_element);

		// var editor = new Quill(editor_element, {
		//     modules: {
		//         'multi-cursor': true,
		//         'toolbar': { container: '#quilljs_toolbar' },
		//         // 'link-tooltip': true,
		//     },
		//     placeholder: 'Text goes here',
		//     theme: 'snow'
		// });

		var editor = new Quill(editor_element, {
			modules: {
				'multi-cursor': true,
				toolbar: [
					[
						{
							header: [1, 2, false]
						}
					],
					['bold', 'italic', 'underline'],
					['image', 'code-block']
				]
				// 'link-tooltip': true,
			},
			placeholder: 'Text goes here',
			theme: 'snow'
		});

		/*
    textarea_element.summernote(
    {
        tabsize: 4,
        height: 200,
        toolbar: [
            ['cleaner',['cleaner']], // The Button
            ['edit', ['undo', 'redo']],
            ['font', ['bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', 'clear']],
            ['color', ['forecolor']],
            ['para', ['ul', 'ol', 'paragraph']],
            ['insert', ['link']],
            ['view', ['codeview', 'help']]
        ],
        cleaner:{
            action: 'both', // both|button|paste 'button' only cleans via toolbar button, 'paste' only clean when pasting content, both does both options.
            newline: '<br>', // Summernote's default is to use '<p><br></p>'
            notStyle: '', // Position of Notification
            icon: '<i class="fas fa-paste"></i>',
            keepHtml: true, // Remove all Html formats
            keepOnlyTags: ['<p>', '<br>', '<ul>', '<li>', '<b>', '<strong>','<i>', '<a>'], // If keepHtml is true, remove all tags except these
            keepClasses: false, // Remove Classes
            badTags: ['style', 'script', 'applet', 'embed', 'noframes', 'noscript', 'html'], // Remove full tags with contents
            badAttributes: ['style', 'start'], // Remove attributes from remaining tags
            limitChars: false, // 0/false|# 0/false disables option
            limitDisplay: 'none', // none|text|html|both
            limitStop: false // true/false
        }
    });
    */
	}
</script>

<div class="element element_input {container_class_li.join(' ')}" style={container_style}>
	{#if type === 'email' || type === 'date' || type === 'number' || type === 'tel' || type === 'text' || type === 'time' || type === 'url'}
		{#if content_layout == 'label_start' && label}
			<label for={id} class={label_class_li.join(' ')} style={label_style}>{label}</label>
		{/if}

		<input
			{id}
			{name}
			class={class_li.join(' ')}
			{style}
			use:set_input_type
			{placeholder}
			{size}
			{pattern}
			{readonly}
			{disabled}
			{required}
			inputmode={input_mode}
			data-id_random={id_random}
			data-obj_type={obj_type}
			data-obj_prop_name={obj_prop_name}
			use:util.set_focus={focus}
			on:input={handle_oninput_dispatch}
			bind:value
		/>

		{#if content_layout != 'label_start' && label}
			<label for={id} class={label_class_li.join(' ')} style={label_style}>{label}</label>
		{/if}

		<span>{description}</span>
	{:else if type === 'date_time'}
		{#if content_layout == 'label_start' && label}
			<span class={label_class_li.join(' ')} style={label_style}>{label}</span>
			<!-- <label for={id} class={label_class_li.join(' ')} style={label_style}>{label}</label> -->
		{/if}

		<div class="element_input multipart {multipart_class_li.join(' ')}" style={multipart_style}>
			{#if label_begin}
				<label for={`${id}_date`} class={label_class_li.join(' ')} style={label_style}
					>{label_date}</label
				>
			{/if}

			<input
				id={id + '_date'}
				name={name + '_date'}
				{style}
				class={class_li.join(' ')}
				type="date"
				value={value_date}
				{placeholder}
				{readonly}
				{disabled}
				{required}
				data-id_random={id_random}
				data-obj_type={obj_type}
				data-obj_prop_name={obj_prop_name}
				on:input={handle_oninput_dispatch}
			/>

			{#if !label_begin}
				<label for={`${id}_date`} class={label_class_li.join(' ')} style={label_style}
					>{label_date}</label
				>
			{/if}
		</div>

		<div class="element_input multipart {multipart_class_li.join(' ')}" style={multipart_style}>
			{#if label_begin}
				<label for={`${id}_time`} class={label_class_li.join(' ')} style={label_style}
					>{label_time}</label
				>
			{/if}

			<input
				id={id + '_time'}
				name={name + '_time'}
				{style}
				class={class_li.join(' ')}
				type="time"
				value={value_time}
				{placeholder}
				{readonly}
				{disabled}
				{required}
				data-id_random={id_random}
				data-obj_type={obj_type}
				data-obj_prop_name={obj_prop_name}
				on:input={handle_oninput_dispatch}
			/>

			{#if !label_begin}
				<label for={`${id}_time`} class={label_class_li.join(' ')} style={label_style}
					>{label_time}</label
				>
			{/if}
		</div>

		{#if content_layout != 'label_start' && label}
			<span class={label_class_li.join(' ')} style={label_style}>{label}</span>
			<!-- <label for={id} class={label_class_li.join(' ')} style={label_style}>{label}</label> -->
		{/if}

		<span>{description}</span>
	{:else if type === 'checkbox'}
		{#if checkbox_none}
			{#if !value}
				{(checked = 'checked')}
			{/if}
			<label
				>{checkbox_none_text}
				<input
					{name}
					type="checkbox"
					value=""
					{readonly}
					{disabled}
					{required}
					{checked}
					on:input={handle_oninput_dispatch}
				/>
			</label>
		{/if}
		{#if checkbox_li.length}
			{#if content_layout == 'label_start' && label}
				<span class="input_container_label label_begin">{label}</span>
			{/if}

			{#each Object.entries(checkbox_li) as [li_key, li_value]}
				{#if li_key.toString() === value.toString()}
					<label
						>{li_value}
						<input
							{name}
							type="checkbox"
							value={li_key}
							checked
							on:input={handle_oninput_dispatch}
						/>
					</label>
				{:else}
					<label
						>{li_value}
						<input {name} type="checkbox" value={li_key} on:input={handle_oninput_dispatch} />
					</label>
				{/if}
			{/each}

			{#if content_layout != 'label_start' && label}
				<span class="input_container_label label_end">{label}</span>
			{/if}
		{:else}
			{#if label_begin}
				<label for={id} class={label_class_li.join(' ')} style={label_style}>{label}</label>
			{/if}

			<input
				{id}
				{name}
				class={class_li.join(' ')}
				{style}
				type="checkbox"
				{value}
				{placeholder}
				{readonly}
				{disabled}
				{required}
				data-id_random={id_random}
				data-obj_type={obj_type}
				data-obj_prop_name={obj_prop_name}
				{checked}
				on:input={handle_oninput_dispatch}
			/>
		{/if}

		<span>{description}</span>
	{:else if type === 'radio'}
		{#if radio_none}
			{#if !value}
				{(checked = 'checked')}
			{/if}
			<label class={radio_option_class_li.join(' ')}
				>{@html radio_none_text}
				<input
					{name}
					type="radio"
					value=""
					{readonly}
					{disabled}
					{required}
					{checked}
					on:input={handle_oninput_dispatch}
				/>
			</label>
		{/if}
		{#if radio_li}
			{#if content_layout == 'label_start' && label}
				<span class="input_container_label label_begin">{label}:</span>
			{/if}

			<span class="input_container_radio_options">
				{#each Object.entries(radio_li) as [li_key, li_value]}
					{#if value === null}
						<!-- If null then no option should be selected. -->
						<label
							>{@html li_value}
							<input
								{name}
								type="radio"
								bind:group={value}
								value={li_key}
								on:input={handle_oninput_dispatch}
							/>
						</label>
					{:else if li_key.toString() === value.toString() || (li_key == 'true' && value == true) || (li_key == 'false' && value == false)}
						<label
							>{@html li_value}
							<input
								{name}
								type="radio"
								bind:group={value}
								value={li_key}
								checked
								on:input={handle_oninput_dispatch}
							/> Z
						</label>
					{:else}
						<label
							>{@html li_value}
							<input
								{name}
								type="radio"
								bind:group={value}
								value={li_key}
								on:input={handle_oninput_dispatch}
							/>
						</label>
					{/if}

					<!-- <label>{@html li_value}
                <input {name} type="radio" bind:group={value} value="{li_key}" on:input={handle_oninput_dispatch}>
            </label> -->
				{/each}
			</span>

			{#if !label_begin}
				<span class="input_container_label label_end">{label}:</span>
			{/if}
		{:else}
			{#if label_begin}
				<label for={id} class={label_class_li.join(' ')} style={label_style}>{@html label}</label>
			{/if}

			<input
				{id}
				{name}
				class={class_li.join(' ')}
				{style}
				type="radio"
				{value}
				{placeholder}
				{readonly}
				{disabled}
				{required}
				data-id_random={id_random}
				data-obj_type={obj_type}
				data-obj_prop_name={obj_prop_name}
				{checked}
				on:input={handle_oninput_dispatch}
			/>

			{#if !label_begin}
				<label for={id} class={label_class_li.join(' ')} style={label_style}>{@html label}</label>
			{/if}
		{/if}

		<span>{description}</span>
	{:else if type === 'textarea'}
		{#if label_begin}
			<label for={id} class={label_class_li.join(' ')} style={label_style}>{label}</label>
		{/if}

		{#if value_new_line}<br />{/if}
		<textarea
			{id}
			{name}
			class={class_li.join(' ')}
			{style}
			bind:value
			{placeholder}
			{readonly}
			{disabled}
			{required}
			{rows}
			{cols}
			data-id_random={id_random}
			data-obj_type={obj_type}
			data-obj_prop_name={obj_prop_name}
			on:input={handle_oninput_dispatch}
		></textarea>
		<!-- rows="" cols="" maxlength="" -->

		{#if !label_begin}
			<label for={id} class={label_class_li.join(' ')} style={label_style}>{label}</label>
		{/if}

		<span>{description}</span>
	{:else if type === 'hidden'}
		<input
			{id}
			{name}
			class={class_li.join(' ')}
			type="hidden"
			bind:value
			{placeholder}
			{readonly}
			{disabled}
			{required}
			data-id_random={id_random}
			data-obj_type={obj_type}
			data-obj_prop_name={obj_prop_name}
		/>
	{:else if type === 'select'}
		{#if label_begin}
			<label for={id} class={label_class_li.join(' ')} style={label_style}>
				{label}
				<!-- {#if value} <span class="label_select_value">{value}</span>{/if} -->
			</label>
		{/if}

		<select
			{id}
			{name}
			class={class_li.join(' ')}
			{style}
			{readonly}
			{disabled}
			{required}
			data-id_random={id_random}
			data-obj_type={obj_type}
			data-obj_prop_name={obj_prop_name}
			on:input={handle_oninput_dispatch}
		>
			{#if select_option_none}
				<option value="">{select_option_none_text}</option>
			{/if}
			{#if select_option_li_lu_name}
				<!-- <Select_element_lu lu_list_name={select_option_li_lu_name} params={select_option_li_lu_params} value_field_name={select_option_lu_value_field_name} text_field_name={select_option_lu_text_field_name} slct_value={value} /> -->
			{:else}
				{#each Object.entries(select_option_li) as [li_key, li_value]}
					{#if value === null}
						<!-- If null then no option should be selected. -->
						<option value={li_key}>
							{li_value}
						</option>
					{:else if li_key.toString() === value.toString()}
						<option value={li_key} selected>
							{li_value}
						</option>
					{:else}
						<option value={li_key}>
							{li_value}
						</option>
					{/if}
				{/each}
			{/if}
		</select>

		{#if !label_begin}
			<label for={id} class={label_class_li.join(' ')} style={label_style}>
				{label}
				{#if value}
					<span class="label_select_value">{value}</span>{/if}
			</label>
		{/if}

		<span>{description}</span>
	{/if}

	<slot name="more_html"></slot>
</div>

<style>
	.container_inline {
		display: inline;
	}
</style>
