<script lang="ts">
	import { Star, StarHalf } from "lucide-svelte";

	interface Props {
		value?: number;
		name?: string;
	}

	const maxV = 5;

	let { value = $bindable(), name }: Props = $props();

	let ctrl: HTMLElement | null = $state(null);
	let w = $state(0);
	let h = $state(0);

	$effect(() => {
		if (ctrl) {
			ctrl.style.width = `${w}px`;
			ctrl.style.height = `${h}px`;
		}
	});

	let hovering = $state(false);
	let valueHover = $state(0);

	let displayVal = $derived(hovering ? valueHover : (value ?? 0));
	let items = $derived.by(() => {
		const full = Number.isInteger(displayVal);
		return Array.from({ length: maxV }, (_, i) => i + 1).map((index) => ({
			index,
			state:
				index <= Math.ceil(displayVal)
					? full || index != Math.ceil(displayVal)
						? "active"
						: "partial"
					: "inactive",
		}));
	});

	function calcSliderPos(e: MouseEvent) {
		return (e.offsetX / (e.target as HTMLElement).clientWidth) * maxV;
	}

	function onclick() {
		value = valueHover;
	}

	function onmouseout() {
		hovering = false;
		valueHover = 0;
	}

	function onmousemove(e: MouseEvent) {
		hovering = true;
		valueHover = Math.ceil(calcSliderPos(e) * 2) / 2;
	}
</script>

<!-- svelte-ignore a11y_no_static_element_interactions -->
<!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
<!-- svelte-ignore a11y_mouse_events_have_key_events -->
<div class="rating-input" {onclick} {onmouseout}>
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="ctrl" {onmousemove} bind:this={ctrl}></div>
	<div class="cont m-1" bind:clientWidth={w} bind:clientHeight={h}>
		{#each items as item (item.index)}
			<div class="rating-item">
				{#if item.state === "inactive"}
					<Star fill="var(--interactive-normal)" />
				{:else if item.state === "active"}
					<Star fill="var(--interactive-accent)" />
				{:else if item.state === "partial"}
					<Star fill="var(--interactive-normal)" />
					<StarHalf fill="var(--interactive-accent)" />
				{/if}
			</div>
		{/each}
	</div>
</div>

<style lang="scss">
	.rating-input {
		cursor: pointer;

		.ctrl {
			position: absolute;
			z-index: 2;
		}

		.cont {
			display: flex;
		}

		:global(svg) {
			position: absolute;
			width: 100%;
			height: 100%;
		}

		.rating-item {
			position: relative;
			width: var(--size-4-16);
			height: var(--size-4-16);
		}
	}
</style>
