<template>
    <div
        :class="bem()"
        :style="{
            '--px-color-panel-hsl': hslStr,
            '--px-color-panel-hsla': hslaStr,
            '--px-color-panel-hsla-transparent': hslaTransparentStr,
            '--px-color-panel-hsl-hue': hueStr,
            '--px-color-panel-contrast': contrastStr,
        }"
    >
        <div ref="satval" :class="[bem('satval'), satValPanelClass]">
            <div
                :class="bem('sel', { satval: true })"
                :style="{
                    left: cssPcnt(s),
                    top: cssPcnt(1 - v),
                }"
            ></div>
        </div>
        <div :class="bem('sliders')">
            <div :class="[bem('hue'), hueSliderClass]" ref="hue">
                <div
                    :class="bem('sel', { hue: true })"
                    :style="{
                        left: cssPcnt(h / 360),
                    }"
                ></div>
            </div>
            <div v-if="alphaEnabled" :class="[bem('alpha'), alphaSliderClass]" ref="alpha">
                <div
                    :class="bem('sel', { alpha: true })"
                    :style="{
                        left: cssPcnt(a),
                    }"
                ></div>
            </div>
        </div>
        <div :class="bem('swatch')"></div>
        <PxIconButton
            v-if="eyedropperEnabled && eyedropperSupported"
            :class="[bem('eyedropper'), eyedropperClass]"
            @click="setColorFromEyedropper"
            :src="EyeDropperSvg"
            :size="0.85"
        />
    </div>
</template>

<script>
import Drag from '../utils/drag.js';
import PxBaseColor from '../bases/PxBaseColor.vue';
import PxIconButton from './PxIconButton.vue';
import EyeDropperSvg from '../assets/icons/eyedropper.svg?url';

export default {
    name: 'px-color-panel',
    mixins: [PxBaseColor],
    components: { PxIconButton },
    props: {
        hueSliderClass: { type: String, default: '' },
        alphaSliderClass: { type: String, default: '' },
        satValPanelClass: { type: String, default: '' },
        eyedropperClass: { type: String, default: '' },
        eyedropperEnabled: { type: Boolean, default: true },
        eyedropperIcon: { type: String, default: EyeDropperSvg },
        swatchVisible: { type: Boolean, default: true },
    },

    data() {
        return {
            EyeDropperSvg,
        };
    },

    // watch: {},
    mounted() {
        if (this.$refs.satval) {
            this.satvalDrag = new Drag(this.$refs.satval, {
                startThreshold: 0,
                lock: null,
                onStart: this.onSatvalDrag,
                onDrag: this.onSatvalDrag,
                excludeSelector: this.dragExcludeSelector,
            });
        }

        if (this.$refs.hue) {
            this.hueDrag = new Drag(this.$refs.hue, {
                startThreshold: 0,
                lock: null,
                onStart: this.onHueDrag,
                onDrag: this.onHueDrag,
                excludeSelector: this.dragExcludeSelector,
            });
        }

        if (this.alphaEnabled && this.$refs.alpha) {
            this.alphaDrag = new Drag(this.$refs.alpha, {
                startThreshold: 0,
                lock: null,
                onStart: this.onAlphaDrag,
                onDrag: this.onAlphaDrag,
                excludeSelector: this.dragExcludeSelector,
            });
        }
    },
    beforeUnmount() {
        if (this.satvalDrag) {
            this.satvalDrag.destroy();
        }

        if (this.hueDrag) {
            this.hueDrag.destroy();
        }

        if (this.alphaDrag) {
            this.alphaDrag.destroy();
        }
    },
    methods: {
        onSatvalDrag(e) {
            this.s = Math.max(0, Math.min(1, e.elementXPos));
            this.v = Math.max(0, Math.min(1, 1 - e.elementYPos));
        },
        onHueDrag(e) {
            this.h = 360 * Math.max(0, Math.min(1, e.elementXPos));
        },
        onAlphaDrag(e) {
            this.a = Math.max(0, Math.min(1, e.elementXPos));
        },
    },
};
</script>

<style lang="scss">
@use '../styles/px.scss' as *;

@at-root {
    :root {
        --px-color-panel-aspect: 1;
        --px-color-panel-gap: 0.5em;
        --px-color-panel-radius: 0.5em;
        --px-color-panel-slider-height: 0.5em;
    }
}

.px-color-panel {
    width: 20em;
    display: flex;
    flex-direction: column;
    aspect-ratio: var(--px-color-panel-aspect);
    gap: var(--px-color-panel-gap) 0;

    // prettier-ignore
    @include grid-art(
        (
            'auto   | #(0, 1fr) |',
            'satval | satval    | #(0,1fr)',
            'swatch | sliders   | auto',
        )
    );

    &__satval {
        grid-area: satval;
        flex: 1;
        position: relative;
        display: block;
        width: 100%;
        border-radius: var(--px-color-panel-radius);

        background-image:
            linear-gradient(rgba(0, 0, 0, 0), #000),
            linear-gradient(90deg, #fff, var(--px-color-panel-hsl-hue));
    }

    &__sliders {
        grid-area: sliders;
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: var(--px-color-panel-gap);
    }

    &__hue,
    &__alpha {
        position: relative;
        display: block;
        width: 100%;
        height: 0.66em;
        border-radius: var(--px-color-panel-radius);
        flex: none;
        align-self: center;
    }

    &__hue {
        grid-area: hue;
        background-image: linear-gradient(90deg, red, yellow, lime, aqua, blue, fuchsia, red);
    }

    &__alpha {
        grid-area: alpha;

        @include checkered-background(
            $width: 0.25em,
            $color: rgba(black, 0.1),
            $color-alt: transparent
        );

        @include after() {
            @include abs();
            border-radius: inherit;
            background-image: linear-gradient(
                to right,
                var(--px-color-panel-hsla-transparent) 0%,
                var(--px-color-panel-hsl) 100%
            );
        }
    }

    &__sel {
        position: absolute;
        top: 100%;
        left: 100%;
        transform: translate(-50%, -50%);
        width: 1px;
        height: 1px;
        width: 0.66em;
        height: 0.66em;
        background-color: var(--px-color-panel-hsl);
        border: 1px solid white;
        border-radius: 50%;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
        z-index: 1;

        &:hover {
            z-index: 2;
        }

        &--hue {
            top: 50%;
            background-color: var(--px-color-panel-hsl-hue);
        }

        &--alpha {
            top: 50%;
            background-color: var(--px-color-panel-hsla);
        }
    }

    &__swatch {
        grid-area: swatch;
        aspect-ratio: 1;
        border-radius: 50%;
        background-color: var(--px-color-panel-hsla);
        margin-inline-end: var(--px-color-panel-gap);
        border: 1px solid rgba(black, 0.1);
        min-height: 1.66em;
    }

    &__eyedropper {
        grid-area: swatch;
        margin-inline-end: var(--px-color-panel-gap);
        color: var(--px-color-panel-contrast);
        aspect-ratio: 1;
    }
}
</style>
