<!--
    Component: ComboControl
    Provides multiple ways to change certain value
    - via Increase/Decrease buttons
    - via Slider
    - via Input
-->
<script lang="ts">
import type { TypographyControl } from '$shared/lib';
import { Button } from '$shared/shadcn/ui/button';
import { Root as ButtonGroupRoot } from '$shared/shadcn/ui/button-group';
import { Input } from '$shared/shadcn/ui/input';
import {
    Content as PopoverContent,
    Root as PopoverRoot,
    Trigger as PopoverTrigger,
} from '$shared/shadcn/ui/popover';
import { Slider } from '$shared/shadcn/ui/slider';
import {
    Content as TooltipContent,
    Root as TooltipRoot,
    Trigger as TooltipTrigger,
} from '$shared/shadcn/ui/tooltip';
import MinusIcon from '@lucide/svelte/icons/minus';
import PlusIcon from '@lucide/svelte/icons/plus';
import type { ChangeEventHandler } from 'svelte/elements';
import IconButton from '../IconButton/IconButton.svelte';

interface ComboControlProps {
    /**
     * Text for increase button aria-label
     */
    increaseLabel?: string;
    /**
     * Text for decrease button aria-label
     */
    decreaseLabel?: string;
    /**
     * Text for control button aria-label
     */
    controlLabel?: string;
    /**
     * Control instance
     */
    control: TypographyControl;
}

const {
    control,
    decreaseLabel,
    increaseLabel,
    controlLabel,
}: ComboControlProps = $props();

// Local state for the slider to prevent infinite loops
// svelte-ignore state_referenced_locally - $state captures initial value, $effect syncs updates
let sliderValue = $state(Number(control.value));

// Sync sliderValue when external value changes
$effect(() => {
    sliderValue = Number(control.value);
});

const handleInputChange: ChangeEventHandler<HTMLInputElement> = event => {
    const parsedValue = parseFloat(event.currentTarget.value);
    if (!isNaN(parsedValue)) {
        control.value = parsedValue;
    }
};

/**
 * Handle slider value change.
 * The Slider component passes the value as a number directly.
 */
const handleSliderChange = (newValue: number) => {
    control.value = newValue;
};
</script>

<TooltipRoot>
    <ButtonGroupRoot class="bg-transparent border-none shadow-none">
        <TooltipTrigger class="flex items-center">
            <IconButton
                onclick={control.decrease}
                disabled={control.isAtMin}
                aria-label={decreaseLabel}
                rotation="counterclockwise"
            >
                {#snippet icon({ className })}
                    <MinusIcon class={className} />
                {/snippet}
            </IconButton>
            <PopoverRoot>
                <PopoverTrigger>
                    {#snippet child({ props })}
                        <Button
                            {...props}
                            variant="ghost"
                            class="hover:bg-white/50 hover:font-bold bg-white/20 border-none duration-150 will-change-transform active:scale-95 cursor-pointer"
                            size="icon"
                            aria-label={controlLabel}
                        >
                            {control.value}
                        </Button>
                    {/snippet}
                </PopoverTrigger>
                <PopoverContent class="w-auto p-4">
                    <div class="flex flex-col items-center gap-3">
                        <Slider
                            min={control.min}
                            max={control.max}
                            step={control.step}
                            value={sliderValue}
                            onValueChange={handleSliderChange}
                            type="single"
                            orientation="vertical"
                            class="h-48"
                        />
                        <Input
                            value={control.value}
                            onchange={handleInputChange}
                            min={control.min}
                            max={control.max}
                            class="w-16 text-center"
                        />
                    </div>
                </PopoverContent>
            </PopoverRoot>

            <IconButton
                aria-label={increaseLabel}
                onclick={control.increase}
                disabled={control.isAtMax}
                rotation="clockwise"
            >
                {#snippet icon({ className })}
                    <PlusIcon class={className} />
                {/snippet}
            </IconButton>
        </TooltipTrigger>
    </ButtonGroupRoot>
    {#if controlLabel}
        <TooltipContent>
            {controlLabel}
        </TooltipContent>
    {/if}
</TooltipRoot>
