<template>
    <component v-if="!asChild" :is="as" :class="cx('root', { orientation })" v-bind="attrs">
        <slot />
    </component>
    <slot v-else :a11yAttrs="a11yAttrs" :class="cx('root', { orientation })" />
</template>

<script>
import { cn } from '@primeuix/utils';
import InputColorSliderHandle from 'primevue/inputcolorsliderhandle';
import InputColorSliderTrack from 'primevue/inputcolorslidertrack';
import InputColorTransparencyGrid from 'primevue/inputcolortransparencygrid';
import { mergeProps } from 'vue';
import BaseInputColorSlider from './BaseInputColorSlider.vue';

export default {
    name: 'InputColorSlider',
    extends: BaseInputColorSlider,
    inheritAttrs: false,
    inject: ['$pcInputColor'],
    data() {
        return {
            isSliderDragging: false
        };
    },
    methods: {
        updateSliderValue(x, y, element) {
            if (!element || this.$pcInputColor.disabled || this.disabled) return;

            const rect = element.getBoundingClientRect();
            const rel = this.orientation === 'horizontal' ? (x - rect.left) / rect.width : 1 - (y - rect.top) / rect.height;
            const clamped = Math.max(0, Math.min(1, rel));
            const { min, max } = this.range;
            const value = min + clamped * (max - min);

            this.$pcInputColor.updateChannel(this.channel, value, null);
        },
        onSliderPointerDown(event) {
            if (event.button !== 0 || this.$pcInputColor.disabled || this.disabled) return;
            event.currentTarget.setPointerCapture?.(event.pointerId);
            this.isSliderDragging = true;
            this.updateSliderValue(event.clientX, event.clientY, event.currentTarget);
        },
        onSliderPointerMove(event) {
            if (!this.isSliderDragging) return;
            this.updateSliderValue(event.clientX, event.clientY, event.currentTarget);
        },
        onSliderPointerUp(event) {
            if (!this.isSliderDragging) return;
            event.currentTarget.releasePointerCapture?.(event.pointerId);
            this.isSliderDragging = false;
            this.$pcInputColor.emitValueChangeEnd(event);
        },
        onSliderKeyDown(event) {
            if (this.$pcInputColor.disabled || this.disabled) return;

            const isVertical = this.orientation === 'vertical';
            const allowed = isVertical ? ['ArrowUp', 'ArrowDown'] : ['ArrowLeft', 'ArrowRight'];

            if (!allowed.includes(event.key)) return;

            event.preventDefault();

            const { step, min, max } = this.range;
            const direction = isVertical ? (event.key === 'ArrowUp' ? 1 : -1) : event.key === 'ArrowRight' ? 1 : -1;
            const next = Math.min(Math.max(this.currentValue + direction * step, min), max);

            this.$pcInputColor.updateChannel(this.channel, next, event);
            this.$pcInputColor.emitValueChangeEnd(event);
        }
    },
    computed: {
        workingValue() {
            return this.$pcInputColor.getChannelColorValue(this.channel);
        },
        range() {
            return this.workingValue.getChannelRange(this.channel);
        },
        currentValue() {
            return this.workingValue.getChannelValue(this.channel);
        },
        handlePercent() {
            const { min, max } = this.range;

            if (max === min) return 0;

            return ((this.currentValue - min) / (max - min)) * 100;
        },
        handleStyle() {
            return this.orientation === 'vertical' ? { left: '50%', bottom: `${this.handlePercent}%`, transform: 'translate(-50%, 50%)' } : { top: '50%', left: `${this.handlePercent}%`, transform: 'translate(-50%, -50%)' };
        },
        cssVars() {
            const baseGradient = this.$pcInputColor.getChannelGradient(this.channel, this.orientation);
            const handleColor = this.$pcInputColor.getChannelColor(this.channel).toString('css');

            return {
                '--px-slider-background': baseGradient,
                '--px-slider-handle-background': handleColor
            };
        },
        attrs() {
            return mergeProps(this.a11yAttrs, this.ptmi('root'));
        },
        a11yAttrs() {
            return {
                style: this.cssVars,
                'data-channel': this.channel,
                'data-orientation': this.orientation,
                'data-p': this.dataP,
                onPointerdown: this.onSliderPointerDown,
                onPointermove: this.onSliderPointerMove,
                onPointerup: this.onSliderPointerUp
            };
        },
        dataP() {
            return cn({
                disabled: this.$pcInputColor.disabled || this.disabled,
                dragging: this.isSliderDragging,
                horizontal: this.orientation === 'horizontal',
                vertical: this.orientation === 'vertical'
            });
        }
    },
    components: {
        InputColorTransparencyGrid,
        InputColorSliderTrack,
        InputColorSliderHandle
    }
};
</script>
