<script>"use strict";
import Icon from "./Icon.svelte";
import { slide } from "svelte/transition";
import { createEventDispatcher, onMount } from "svelte";
const dispatch = createEventDispatcher();
export let label = "";
export let buttonText = "Select one...";
export let items = [];
export let header = void 0;
export let type = "default";
export let transition = { duration: 200, delay: 50 };
export let selectedOptions = [];
export let closeOnSelect = false;
export let disabled = false;
let isOpen = false;
let dropdownElement;
let buttonElement;
const buttonId = `dropdown-${Math.random().toString(36).substr(2, 9)}`;
const menuId = `${buttonId}-menu`;
$: displayText = getDisplayText(selectedOptions);
function getDisplayText(selectedOptions2) {
  if (selectedOptions2.length === 1) {
    return selectedOptions2[0]?.label ?? buttonText;
  }
  if (selectedOptions2.length > 1) {
    return selectedOptions2.map((opt) => opt.label).join(", ");
  }
  return buttonText;
}
function toggleDropdown() {
  if (!disabled) {
    isOpen = !isOpen;
  }
}
function closeDropdown() {
  isOpen = false;
}
function sortSelectedOptions(options) {
  return [...options].sort((a, b) => {
    const ai = items.findIndex((item) => areItemsEqual(item, a));
    const bi = items.findIndex((item) => areItemsEqual(item, b));
    return ai - bi;
  });
}
function selectOption(option) {
  const isSingleSelect = type === "default" || type === "radio";
  if (isSingleSelect) {
    selectedOptions = [option];
    if (closeOnSelect) {
      closeDropdown();
    }
  } else {
    const isSelected = selectedOptions.some(
      (opt) => opt.value != null && option.value != null ? opt.value === option.value : opt.label === option.label
    );
    if (isSelected) {
      let newSelectedOptions = selectedOptions.filter(
        (opt) => opt.value != null && option.value != null ? opt.value !== option.value : opt.label !== option.label
      );
      selectedOptions = sortSelectedOptions(newSelectedOptions);
    } else {
      selectedOptions = sortSelectedOptions([...selectedOptions, option]);
    }
  }
  dispatch("change", selectedOptions);
}
function isItemSelected(item, selected) {
  if (Array.isArray(selected)) {
    return selected.some((opt) => areItemsEqual(opt, item));
  } else if (selected) {
    return areItemsEqual(selected, item);
  }
  return false;
}
function areItemsEqual(a, b) {
  if (a.value != null && b.value != null) return a.value === b.value;
  if (a.label != null && b.label != null) return a.label === b.label;
  return false;
}
function handleKeydown(event) {
  if (disabled) return;
  if (!isOpen) {
    if (event.key === "Enter" || event.key === " " || event.key === "ArrowDown") {
      event.preventDefault();
      toggleDropdown();
    }
    return;
  }
  switch (event.key) {
    case "Escape":
      event.preventDefault();
      closeDropdown();
      buttonElement.focus();
      break;
    case "Tab":
      closeDropdown();
      break;
  }
}
function handleClickOutside(event) {
  if (dropdownElement && !dropdownElement.contains(event.target)) {
    closeDropdown();
  }
}
onMount(() => {
  document.addEventListener("click", handleClickOutside);
  return () => {
    document.removeEventListener("click", handleClickOutside);
  };
});
</script>

{#if label}
	<label for={buttonId} class="block text-4xl font-semibold text-stone-950 mb-2">{label}</label>
{/if}

<div class="relative select-none" bind:this={dropdownElement}>
	<button
		bind:this={buttonElement}
		id={buttonId}
		type="button"
		class="focus:outline-none rounded-lg text-2xl px-4 py-2 text-center items-center border flex justify-between w-full"
		class:cursor-pointer={!disabled && items.length > 0}
		class:opacity-50={disabled}
		on:click={toggleDropdown}
		on:keydown={handleKeydown}
		{disabled}
		aria-haspopup="true"
		aria-expanded={isOpen}
		aria-controls={menuId}
		aria-label={label || 'Dropdown menu'}
	>
		<span
			class="text-stone-400 font-regular"
			class:font-medium={selectedOptions.length > 0}
			class:text-stone-600={selectedOptions.length > 0}
			class:group-hover:underline={selectedOptions.length > 0}
		>
			{displayText}
		</span>

		{#if items.length > 0 && !disabled}
			<Icon
				iconName="chevron-down"
				size="sm"
				className="transform transition-transform duration-500 {isOpen ? 'rotate-180' : ''}"
			/>
		{/if}
	</button>

	{#if isOpen}
		<div
			id={menuId}
			class="z-10 flex flex-col bg-white divide-y divide-gray-100 rounded-lg shadow-md absolute top-12 left-0 right-0"
			transition:slide={transition}
			role="menu"
			aria-labelledby={buttonId}
		>
			{#if header}
				<div class="py-3 px-4 text-lg flex flex-col text-stone-800">
					<span class="font-bold">{header.title}</span>
					<span class="font-regular">{header.subtitle}</span>
				</div>
			{/if}

			{#if type === 'default'}
				<ul class="w-full">
					{#each items as item}
						<li>
							<!-- If your item has href, we are considering -->
							<!-- that you are expecting to to be redirected -->
							{#if item.href}
								<div class="p-1">
									<a
										href={item.href}
										class="rounded px-4 py-2 flex gap-x-2 text-2xl font-regular text-stone-600"
										class:text-stone-600={!item.destructive}
										class:text-rose-600={item.destructive}
										class:hover:text-stone-950={!item.destructive}
										class:hover:bg-rose-50={item.destructive}
										class:hover:bg-stone-50={!item.destructive}
										role="menuitem"
									>
										{#if item.icon}
											<Icon iconName={item.icon} color={item.destructive ? 'rose' : 'stone'} />
										{/if}
										{item.label}
									</a>
								</div>
								<!-- If its a item with label and value -->
							{:else if item.value != null}
								<li role="none">
									<div class="p-1">
										<button
											type="button"
											class="rounded px-4 py-2 flex gap-x-2 text-2xl font-regular text-stone-600 w-full text-left hover:bg-base-100"
											class:bg-blue-50={isItemSelected(item, selectedOptions)}
											role="menuitem"
											on:click={() => selectOption(item)}
										>
											{#if item.icon}
												<Icon iconName={item.icon} color={item.destructive ? 'rose' : 'stone'} />
											{/if}
											<span class:text-blue-600={isItemSelected(item, selectedOptions)}>
												{item.label}
											</span>
										</button>
									</div>
								</li>
							{:else if item.divider}
								<div class="border-t border-stone-200"></div>
							{/if}
						</li>
					{/each}
				</ul>
			{:else if type === 'checkbox'}
				<ul class="p-3 space-y-3 text-sm text-gray-700 w-full">
					{#each items as item, i}
						<li>
							{#if item.label}
								<div class="flex items-center">
									<input
										id={`checkbox-item-${buttonId}-${i}`}
										type="checkbox"
										class="w-4 h-4 text-blue-600 bg-primary-bg border-stone-300 rounded-sm focus:ring-offset-1 focus:ring-sky-600"
										checked={isItemSelected(item, selectedOptions)}
										on:change={() => selectOption(item)}
									/>
									<label
										for={`checkbox-item-${buttonId}-${i}`}
										class="ms-2 text-2xl font-regular text-stone-600 w-full cursor-pointer"
									>
										{item.label}
									</label>
								</div>
							{:else if item.divider}
								<div class="border-t border-stone-200"></div>
							{/if}
						</li>
					{/each}
				</ul>
			{:else if type === 'radio'}
				<ul class="p-3 space-y-3 text-sm text-gray-700 w-full">
					{#each items as item, i}
						<li>
							{#if item.label}
								<div class="flex items-center">
									<input
										id={`radio-item-${buttonId}-${i}`}
										name={`dropdown-radio-${buttonId}`}
										type="radio"
										checked={isItemSelected(item, selectedOptions)}
										on:change={() => selectOption(item)}
									/>
									<label
										for={`radio-item-${buttonId}-${i}`}
										class="ms-2 text-2xl font-regular text-stone-600 w-full"
									>
										{item.label}
									</label>
								</div>
							{:else if item.divider}
								<div class="border-t border-stone-200"></div>
							{/if}
						</li>
					{/each}
				</ul>
			{:else if type === 'toggle'}
				<ul class="p-3 space-y-3 text-sm text-gray-700 w-full">
					{#each items as item, i}
						<li>
							{#if item.label}
								<div class="flex p-2 rounded">
									<label class="inline-flex items-center w-full cursor-pointer">
										<input
											type="checkbox"
											value=""
											class="sr-only peer"
											checked={isItemSelected(item, selectedOptions)}
											on:change={() => selectOption(item)}
											aria-describedby={`toggle-desc-${buttonId}-${i}`}
										/>
										<div
											class="relative w-8 h-4 bg-base-400 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-blue-600 peer-focus:ring-offset-1 rounded-full peer peer-checked:after:translate-x-full peer-checked:bg-blue-600 after:content-[''] after:absolute after:top-[2px] after:start-[2px] peer-checked:after:start-[6px] after:bg-white after:rounded-full after:h-3 after:w-3 after:transition-all dark:border-gray-500"
										></div>
										<span
											id={`toggle-desc-${buttonId}-${i}`}
											class="ms-3 text-2xl font-regular text-stone-600">{item.label}</span
										>
									</label>
								</div>
							{:else if item.divider}
								<div class="border-t border-stone-200"></div>
							{/if}
						</li>
					{/each}
				</ul>
			{/if}
		</div>
	{/if}
</div>
