<script context="module">import { fly, scale } from "svelte/transition";
import { prefersReducedMotionStore } from "../../index.js";
import { dynamicTransition } from "../../internal/transitions.js";
</script>

<script

	generics="ListTransitionIn extends Transition = FlyTransition, ListTransitionOut extends Transition = FlyTransition, ChipTransitionIn extends Transition = ScaleTransition, ChipTransitionOut extends Transition = ScaleTransition"
>import { createEventDispatcher, onMount } from "svelte";
import { flip } from "svelte/animate";
const dispatch = createEventDispatcher();
export let input = "";
export let name;
export let value = [];
export let whitelist = [];
export let max = -1;
export let minlength = -1;
export let maxlength = -1;
export let allowUpperCase = false;
export let allowDuplicates = false;
export let validation = () => true;
export let duration = 150;
export let required = false;
export let chips = "variant-filled";
export let invalid = "input-error";
export let padding = "p-2";
export let rounded = "rounded-container-token";
export let regionChipWrapper = "";
export let regionChipList = "";
export let regionInput = "";
export let transitions = !$prefersReducedMotionStore;
export let listTransitionIn = fly;
export let listTransitionInParams = { duration: 150, opacity: 0, y: -20 };
export let listTransitionOut = fly;
export let listTransitionOutParams = { duration: 150, opacity: 0, y: -20 };
export let chipTransitionIn = scale;
export let chipTransitionInParams = { duration: 150, opacity: 0 };
export let chipTransitionOut = scale;
export let chipTransitionOutParams = { duration: 150, opacity: 0 };
const cBase = "textarea cursor-pointer";
const cChipWrapper = "space-y-4";
const cChipList = "flex flex-wrap gap-2";
const cInputField = "unstyled bg-transparent border-0 !ring-0 p-0 w-full";
let inputValid = true;
let chipValues = value?.map((val) => {
  return { val, id: Math.random() };
}) || [];
function resetFormHandler() {
  value = [];
}
let selectElement;
onMount(() => {
  if (!selectElement.form)
    return;
  const externalForm = selectElement.form;
  externalForm.addEventListener("reset", resetFormHandler);
  return () => {
    externalForm.removeEventListener("reset", resetFormHandler);
  };
});
function onInputHandler() {
  inputValid = true;
}
function validate() {
  if (!input)
    return false;
  input = input.trim();
  if (validation !== void 0 && !validation(input))
    return false;
  if (max !== -1 && value.length >= max)
    return false;
  if (minlength !== -1 && input.length < minlength)
    return false;
  if (maxlength !== -1 && input.length > maxlength)
    return false;
  if (whitelist.length > 0 && !whitelist.includes(input))
    return false;
  if (allowDuplicates === false && value.includes(input))
    return false;
  return true;
}
function addChip(event) {
  event.preventDefault();
  inputValid = validate();
  if (inputValid === false) {
    dispatch("invalid", { event, input });
    return;
  }
  input = allowUpperCase ? input : input.toLowerCase();
  value.push(input);
  value = value;
  chipValues.push({ val: input, id: Math.random() });
  chipValues = chipValues;
  dispatch("add", { event, chipIndex: value.length - 1, chipValue: input });
  input = "";
}
function removeChip(event, chipIndex, chipValue) {
  if ($$restProps.disabled)
    return;
  value.splice(chipIndex, 1);
  value = value;
  chipValues.splice(chipIndex, 1);
  chipValues = chipValues;
  dispatch("remove", { event, chipIndex, chipValue });
}
$:
  classesInvalid = inputValid === false ? invalid : "";
$:
  classesBase = `${cBase} ${padding} ${rounded} ${$$props.class ?? ""} ${classesInvalid}`;
$:
  classesChipWrapper = `${cChipWrapper} ${regionChipWrapper}`;
$:
  classesChipList = `${cChipList} ${regionChipList}`;
$:
  classesInput = `${cInputField} ${regionInput}`;
$:
  chipValues = value?.map((val, i) => {
    if (chipValues[i]?.val === val)
      return chipValues[i];
    return { id: Math.random(), val };
  }) || [];
</script>

<div class="input-chip {classesBase}" class:opacity-50={$$restProps.disabled}>
	<!-- NOTE: Don't use `hidden` as it prevents `required` from operating -->
	<div class="h-0 overflow-hidden">
		<select bind:this={selectElement} bind:value {name} multiple {required} tabindex="-1">
			<!-- NOTE: options are required! -->
			{#each value as option}<option value={option}>{option}</option>{/each}
		</select>
	</div>
	<!-- Chip Wrapper -->
	<div class="input-chip-wrapper {classesChipWrapper}">
		<!-- Input Field -->
		<form on:submit={addChip}>
			<input
				type="text"
				bind:value={input}
				placeholder={$$restProps.placeholder ?? 'Enter values...'}
				class="input-chip-field {classesInput}"
				on:input={onInputHandler}
				on:input
				on:focus
				on:blur
				disabled={$$restProps.disabled}
			/>
		</form>
		<!-- Chip List -->
		{#if chipValues.length}
			<div
				class="input-chip-list {classesChipList}"
				in:dynamicTransition|local={{ transition: listTransitionIn, params: listTransitionInParams, enabled: transitions }}
				out:dynamicTransition|local={{ transition: listTransitionOut, params: listTransitionOutParams, enabled: transitions }}
			>
				{#each chipValues as { id, val }, i (id)}
					<!-- Wrapping div required for FLIP animation -->
					<div animate:flip={{ duration }}>
						<button
							type="button"
							class="chip {chips}"
							on:click={(e) => {
								removeChip(e, i, val);
							}}
							on:click
							on:keypress
							on:keydown
							on:keyup
							in:dynamicTransition|local={{ transition: chipTransitionIn, params: chipTransitionInParams, enabled: transitions }}
							out:dynamicTransition|local={{ transition: chipTransitionOut, params: chipTransitionOutParams, enabled: transitions }}
						>
							<span>{val}</span>
							<span>✕</span>
						</button>
					</div>
				{/each}
			</div>
		{/if}
	</div>
</div>
