import { Machine, EventObject, Service } from '@zag-js/core';
import { PropTypes, RequiredBy, DirectionProperty, CommonProperties } from '@zag-js/types';

type ThumbCollisionBehavior = "none" | "push" | "swap";
type ThumbAlignment = "contain" | "center";
interface ValueChangeDetails {
    value: number[];
}
interface FocusChangeDetails {
    focusedIndex: number;
    value: number[];
}
interface ValueTextDetails {
    value: number;
    index: number;
}
type ElementIds = Partial<{
    root: string;
    thumb: (index: number) => string;
    hiddenInput: (index: number) => string;
    control: string;
    track: string;
    range: string;
    label: string;
    valueText: string;
    marker: (index: number) => string;
}>;
interface SliderProps extends DirectionProperty, CommonProperties {
    /**
     * The ids of the elements in the slider. Useful for composition.
     */
    ids?: ElementIds | undefined;
    /**
     * The aria-label of each slider thumb. Useful for providing an accessible name to the slider
     */
    "aria-label"?: string[] | undefined;
    /**
     * The `id` of the elements that labels each slider thumb. Useful for providing an accessible name to the slider
     */
    "aria-labelledby"?: string[] | undefined;
    /**
     * The name associated with each slider thumb (when used in a form)
     */
    name?: string | undefined;
    /**
     * The associate form of the underlying input element.
     */
    form?: string | undefined;
    /**
     * The controlled value of the slider
     */
    value?: number[] | undefined;
    /**
     * The initial value of the slider when rendered.
     * Use when you don't need to control the value of the slider.
     */
    defaultValue?: number[] | undefined;
    /**
     * Whether the slider is disabled
     */
    disabled?: boolean | undefined;
    /**
     * Whether the slider is read-only
     */
    readOnly?: boolean | undefined;
    /**
     * Whether the slider is invalid
     */
    invalid?: boolean | undefined;
    /**
     * Function invoked when the value of the slider changes
     */
    onValueChange?: ((details: ValueChangeDetails) => void) | undefined;
    /**
     * Function invoked when the slider value change is done
     */
    onValueChangeEnd?: ((details: ValueChangeDetails) => void) | undefined;
    /**
     * Function invoked when the slider's focused index changes
     */
    onFocusChange?: ((details: FocusChangeDetails) => void) | undefined;
    /**
     * Function that returns a human readable value for the slider thumb
     */
    getAriaValueText?: ((details: ValueTextDetails) => string) | undefined;
    /**
     * The minimum value of the slider
     * @default 0
     */
    min?: number | undefined;
    /**
     * The maximum value of the slider
     * @default 100
     */
    max?: number | undefined;
    /**
     * The step value of the slider
     * @default 1
     */
    step?: number | undefined;
    /**
     * The step value of the slider when the `Shift` key is held, or the
     * `PageUp`/`PageDown` keys are used.
     * @default 10 * step
     */
    largeStep?: number | undefined;
    /**
     * The minimum permitted steps between multiple thumbs.
     *
     * `minStepsBetweenThumbs` * `step` should reflect the gap between the thumbs.
     *
     * - `step: 1` and `minStepsBetweenThumbs: 10` => gap is `10`
     * - `step: 10` and `minStepsBetweenThumbs: 2` => gap is `20`
     *
     * @default 0
     */
    minStepsBetweenThumbs?: number | undefined;
    /**
     * The orientation of the slider
     * @default "horizontal"
     */
    orientation?: "vertical" | "horizontal" | undefined;
    /**
     * The origin of the slider range. The track is filled from the origin
     * to the thumb for single values.
     * - "start": Useful when the value represents an absolute value
     * - "center": Useful when the value represents an offset (relative)
     * - "end": Useful when the value represents an offset from the end
     *
     * @default "start"
     */
    origin?: "start" | "center" | "end" | undefined;
    /**
     * The alignment of the slider thumb relative to the track
     * - `center`: the thumb will extend beyond the bounds of the slider track.
     * - `contain`: the thumb will be contained within the bounds of the track.
     *
     * @default "contain"
     */
    thumbAlignment?: "contain" | "center" | undefined;
    /**
     * The slider thumbs dimensions
     */
    thumbSize?: {
        width: number;
        height: number;
    } | undefined;
    /**
     * Controls how thumbs behave when they collide during pointer interactions.
     * - `none` (default): Thumbs cannot move past each other; excess movement is ignored.
     * - `push`: Thumbs push each other without restoring their previous positions when dragged back.
     * - `swap`: Thumbs swap places when dragged past each other.
     *
     * @default "none"
     */
    thumbCollisionBehavior?: "none" | "push" | "swap" | undefined;
}
type PropsWithDefault = "dir" | "min" | "max" | "step" | "largeStep" | "orientation" | "defaultValue" | "origin" | "thumbAlignment" | "minStepsBetweenThumbs" | "thumbCollisionBehavior";
type Computed = Readonly<{
    /**
     * @computed
     * Whether the slider thumb has been measured
     */
    hasMeasuredThumbSize: boolean;
    /**
     * @computed
     * Whether the slider is interactive
     */
    isInteractive: boolean;
    /**
     * @computed
     * Whether the slider is vertical
     */
    isVertical: boolean;
    /**
     * @computed
     * Whether the slider is horizontal
     */
    isHorizontal: boolean;
    /**
     * @computed
     * Whether the slider is in RTL mode
     */
    isRtl: boolean;
    /**
     * @computed
     * The percentage of the slider value relative to the slider min/max
     */
    valuePercent: number[];
    /**
     * @computed
     * Whether the slider is disabled
     */
    isDisabled: boolean;
}>;
interface Context {
    /**
     * The active index of the range slider. This represents
     * the currently dragged/focused thumb.
     */
    focusedIndex: number;
    /**
     * The value of the range slider
     */
    value: number[];
    /**
     * The size of the slider thumbs
     */
    thumbSize: Size | null;
}
interface SliderSchema {
    state: "idle" | "dragging" | "focus";
    props: RequiredBy<SliderProps, PropsWithDefault>;
    context: Context;
    refs: {
        /**
         * The offset from the thumb center when pointer down occurs.
         * Used to maintain constant offset during drag.
         */
        thumbDragOffset: {
            x: number;
            y: number;
        } | null;
        /**
         * The values when a thumb drag starts.
         * Used for swap collision behavior to determine swap direction.
         */
        thumbDragStartValue: number[] | null;
    };
    computed: Computed;
    event: EventObject;
    action: string;
    effect: string;
    guard: string;
}
type SliderService = Service<SliderSchema>;
type SliderMachine = Machine<SliderSchema>;
interface Size {
    width: number;
    height: number;
}
interface MarkerProps {
    value: number;
}
interface ThumbProps {
    index: number;
    name?: string | undefined;
}
interface DraggingIndicatorProps {
    index: number;
}
interface SliderApi<T extends PropTypes = PropTypes> {
    /**
     * The value of the slider.
     */
    value: number[];
    /**
     * Whether the slider is being dragged.
     */
    dragging: boolean;
    /**
     * Whether the slider is focused.
     */
    focused: boolean;
    /**
     * Function to set the value of the slider.
     */
    setValue: (value: number[]) => void;
    /**
     * Returns the value of the thumb at the given index.
     */
    getThumbValue: (index: number) => number;
    /**
     * Sets the value of the thumb at the given index.
     */
    setThumbValue: (index: number, value: number) => void;
    /**
     * Returns the percent of the thumb at the given index.
     */
    getValuePercent: (value: number) => number;
    /**
     * Returns the value of the thumb at the given percent.
     */
    getPercentValue: (percent: number) => number;
    /**
     * Returns the percent of the thumb at the given index.
     */
    getThumbPercent: (index: number) => number;
    /**
     * Sets the percent of the thumb at the given index.
     */
    setThumbPercent: (index: number, percent: number) => void;
    /**
     * Returns the min value of the thumb at the given index.
     */
    getThumbMin: (index: number) => number;
    /**
     * Returns the max value of the thumb at the given index.
     */
    getThumbMax: (index: number) => number;
    /**
     * Function to increment the value of the slider at the given index.
     */
    increment: (index: number) => void;
    /**
     * Function to decrement the value of the slider at the given index.
     */
    decrement: (index: number) => void;
    /**
     * Function to focus the slider. This focuses the first thumb.
     */
    focus: VoidFunction;
    getLabelProps: () => T["label"];
    getRootProps: () => T["element"];
    getValueTextProps: () => T["element"];
    getTrackProps: () => T["element"];
    getThumbProps: (props: ThumbProps) => T["element"];
    getHiddenInputProps: (props: ThumbProps) => T["input"];
    getRangeProps: () => T["element"];
    getControlProps: () => T["element"];
    getMarkerGroupProps: () => T["element"];
    getMarkerProps: (props: MarkerProps) => T["element"];
    getDraggingIndicatorProps: (props: DraggingIndicatorProps) => T["element"];
}

export type { DraggingIndicatorProps, ElementIds, FocusChangeDetails, MarkerProps, SliderApi, SliderMachine, SliderProps, SliderSchema, SliderService, ThumbAlignment, ThumbCollisionBehavior, ThumbProps, ValueChangeDetails, ValueTextDetails };
