<template>
    <div :class="bem()">
        <div :class="['px-clock__time', 'mode-' + mode, { hovering: isHovering }]">
            <div class="px-clock__hour" @click="mode = 'hours'">
                <span>{{ displayHour }}</span>
            </div>
            <div class="px-clock__sep">:</div>
            <div class="px-clock__min" @click="mode = 'minutes'">
                <span>{{ displayMinute }}</span>
            </div>
            <div class="px-clock__period" @click="togglePeriod">
                <div>
                    <span :class="{ 'is-selected': selectedPeriod === 'AM' }">AM</span>
                    <span :class="{ 'is-selected': selectedPeriod === 'PM' }">PM</span>
                </div>
            </div>
        </div>
        <div
            ref="clock"
            :data-hour="hourNumber"
            :data-minute="minuteNumber"
            :data-hover="hoverNumber"
            :class="['px-clock__clock', 'mode-' + mode]"
        >
            <div class="px-clock__hand-hour-hover"></div>
            <div class="px-clock__hand-min-hover"></div>

            <div class="px-clock__hand-hour-shadow"></div>
            <div class="px-clock__hand-hour"></div>

            <div
                class="px-clock__hand-min"
                :style="{
                    transform: `rotate(${minuteDegrees})`,
                }"
            ></div>
            <div class="px-clock__numbers">
                <div
                    v-for="(num, index) in numbers"
                    :key="index"
                    class="px-clock__number"
                    @click="select(num)"
                    @mouseenter="mouseenter(num)"
                    @mouseleave="mouseleave(num)"
                    tabindex="0"
                >
                    <span>{{ toClockNumber(num) }}</span>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import PxBaseDate from '../bases/PxBaseDate.vue';
export default {
    name: 'px-clock',
    mixins: [PxBaseDate],
    props: {
        date: { type: Date, default: null },
    },
    data: function () {
        return {
            mode: 'hours', // 'minutes'
            numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
            hoverNumber: -1,
        };
    },
    watch: {
        mode() {
            // require the user to the move the mouse again before we show hover
            // after switching between minutes/hours (slightly less confusing ux)
            this.hoverNumber = -1;
        },
    },
    computed: {
        // a number (1-12) representing the clock's hour hand number
        hourNumber() {
            return this.dateValue ? this.dateValue.getHours() % 12 || 12 : 12;
        },

        // a number (1-12) representing the clock's minute hand number
        minuteNumber() {
            return this.dateValue ? Math.round(this.dateValue.getMinutes() / 5) || 12 : 12;
        },

        // css friendly string representing the angle of the minute hand
        minuteDegrees() {
            let d = this.dateValue ? Math.round(this.dateValue.getMinutes()) * 6 || 360 : 360;
            return d + 'deg';
        },

        // the display version of the selected hour
        displayHour() {
            if (this.isHovering && this.mode === 'hours') {
                return this.hoverNumber;
            } else {
                if (!this.dateValue) {
                    return '12';
                }
                return this.hourNumber; // unless we add 24 hour support, this is the same as hourNumber
            }
        },

        // the display version of the selected minute
        displayMinute() {
            if (this.isHovering && this.mode === 'minutes') {
                return this.hoverNumber % 12 < 2
                    ? '0' + (this.hoverNumber % 12) * 5
                    : this.hoverNumber * 5;
            } else {
                if (!this.dateValue) {
                    return '00';
                }
                const m = this.dateValue.getMinutes();
                return m < 10 ? '0' + m : m;
            }
        },

        // the period (AM or PM)
        selectedPeriod() {
            if (!this.dateValue) {
                return 'AM';
            }
            return this.dateValue.getHours() < 12 ? 'AM' : 'PM';
        },

        isHovering() {
            return this.hoverNumber > -1;
        },
    },
    methods: {
        toClockNumber(num) {
            if (this.mode === 'hours') {
                return num;
            } else {
                return num % 12 < 2 ? '0' + (num % 12) * 5 : num * 5;
            }
        },
        select(num) {
            let d = this.dateValue ? this.dateValue : new Date(new Date().toDateString());

            if (this.mode == 'hours') {
                let h = this.selectedPeriod === 'PM' ? (num % 12) + 12 : num % 12;
                this.dateValue = new Date(d.setHours(h));
                setTimeout(() => {
                    this.mode = 'minutes';
                }, 400);
            } else {
                this.dateValue = new Date(d.setMinutes((num % 12) * 5));
                setTimeout(() => {
                    this.mode = 'hours';
                }, 400);
            }
        },
        togglePeriod() {
            let h = this.dateValue.getHours();

            if (this.selectedPeriod === 'AM') {
                this.dateValue = new Date(this.dateValue.setHours(h + 12));
            } else {
                this.dateValue = new Date(this.dateValue.setHours(h - 12));
            }
        },
        setMode(mode) {
            this.mode = mode;
        },
        mouseenter(num) {
            clearTimeout(this.timeout);
            this.hoverNumber = num;
        },
        mouseleave() {
            clearTimeout(this.timeout);
            this.timeout = setTimeout(() => {
                this.hoverNumber = -1;
            }, 100);
        },
    },
};
</script>

<style lang="scss">
@use '../styles/px.scss' as *;
@use '@thinkpixellab-public/px-styles/src/modules/controls' as *;

.px-clock {
    @include control-reset();
    $clock-color: white;
    $num-size: 2.25em;

    $hour-color: accent();
    $hour-hover: mix($hour-color, $clock-color, 10%);
    $hour-width: 4px;
    $hour-height: 25%;

    $min-color: adjust-color(accent(), $hue: 60deg);
    $min-hover: mix($min-color, $clock-color, 10%);
    $min-width: 2px;
    $min-height: 33%;

    width: 12em;

    &__clock {
        width: 100%;
        background-color: $clock-color;
        aspect-ratio: 1;
        border-radius: 50%;
        position: relative;
        @include no-select();
    }

    &__hand-hour,
    &__hand-hour-hover,
    &__hand-hour-shadow,
    &__hand-min,
    &__hand-min-hover {
        @include abs;
        &::before,
        &::after {
            content: '';
            display: block;
            position: absolute;
        }
        &::before {
            border-radius: 50%;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
        &::after {
            bottom: 50%;
            left: 50%;
            transform: translateX(-50%);
        }
    }

    &__hand-hour-shadow,
    &__hand-hour-hover,
    &__hand-hour {
        &::before {
            width: $hour-width + 4px;
            height: $hour-width + 4px;
            background-color: $hour-color;
        }
        &::after {
            height: $hour-height;
            width: $hour-width;
            background-color: $hour-color;
            border-radius: $hour-width * 0.5;
        }
    }

    &__hand-hour-hover {
        &::before,
        &::after {
            background-color: $hour-hover;
        }
    }

    &__hand-hour-shadow {
        margin-top: 3px;
        &::before {
            background-color: rgba(black, 0.5);
            box-shadow: 0px 0px 4px black;
            opacity: 0.25;
        }
        &::after {
            background-color: rgba(black, 0.5);
            box-shadow: 0px 0px 4px black;
            opacity: 0.25;
        }
    }

    &__hand-min,
    &__hand-min-hover {
        &::before {
            width: $min-width + 2px;
            height: $min-width + 2px;
            background-color: $min-color;
        }
        &::after {
            height: $min-height;
            width: $min-width;
            background-color: $min-color;
            border-radius: $min-width * 0.5;
        }
    }

    &__hand-min-hover {
        &::before,
        &::after {
            background-color: $min-hover;
        }
    }

    // clock numbers

    &__number {
        width: $num-size;
        height: $num-size;
        margin-top: $num-size * -0.5;
        margin-left: $num-size * -0.5;

        position: absolute;
        top: 50%;
        left: 50%;
        border-radius: 50%;
        cursor: pointer;

        //@include transition-props((background-color, color), $dur: 50ms);
        @for $n from 1 through 12 {
            &:nth-child(#{$n}) {
                transform: rotate(#{30 * $n}deg) translateY(-4.75em);
                span {
                    width: 100%;
                    text-align: center;
                    line-height: $num-size;
                    display: block;
                    transform: rotate(-#{30 * $n}deg);
                }
            }
        }
        &:focus {
            outline: none;
            // background-color: $hour-hover;
            // color: $hour-color;
        }
    }

    // clock hands
    .px-clock__hand-min,
    .px-clock__hand-hour,
    .px-clock__hand-hour-shadow {
        transition: transform 400ms $ease-out-cubic;
    }

    &__clock {
        @for $n from 1 through 12 {
            &[data-minute='#{$n}'] {
                .px-clock__hand-min {
                    transform: rotate(#{30 * $n}deg);
                }
            }
            &[data-hour='#{$n}'] {
                .px-clock__hand-hour-shadow,
                .px-clock__hand-hour {
                    transform: rotate(#{30 * $n}deg);
                }
            }
        }
    }

    // clock hover states

    .px-clock__hand-hour-hover,
    .px-clock__hand-min-hover {
        opacity: 0;
    }

    @mixin clock-hover($hand-sel, $col, $hov) {
        @for $n from 1 through 12 {
            &[data-hover='#{$n}'] {
                .px-clock__number:nth-child(#{$n}) {
                    background-color: $hov;
                    color: $col;
                }
                #{$hand-sel} {
                    opacity: 1;
                    transform: rotate(#{30 * $n}deg);
                }
            }
        }
    }

    &__clock.mode-hours {
        @include clock-hover('.px-clock__hand-hour-hover', $hour-color, $hour-hover);
    }
    &__clock.mode-minutes {
        @include clock-hover('.px-clock__hand-min-hover', $min-color, $min-hover);
    }

    // text version of time display

    &__time {
        @include no-select();
        margin-top: 1rem;
        display: flex;
        font-size: 2em;
        justify-content: center;
        align-items: center;
        margin-bottom: 0.5em;
        position: relative;
        z-index: 10;
    }

    &__time & {
        &__hour,
        &__min,
        &__period {
            line-height: 1.1;
            height: 1.1em;
            display: block;
            position: relative;
            white-space: normal;
            padding: 0 0.1em;
            border-radius: 3px;
            box-sizing: border-box;
            cursor: pointer;
            @include transition((background-color, color), $dur: 100ms);
        }
        &__hour,
        &__min {
            span {
                white-space: nowrap;
                display: block;
                @include abs(0, 0.1em, 0, 0.1em);
            }
        }

        &__sep {
            line-height: 1;
            border-bottom: 3px solid transparent;
        }

        &__hour {
            text-align: right;
            &::before {
                // derive a fixed size from this
                content: '10';
                color: transparent;
            }
            &:hover {
                background-color: rgba($hour-color, 0.1);
                color: $hour-color;
            }
        }

        &__min {
            text-align: center;
            &::before {
                // derive a fixed size from this
                content: '00';
                color: transparent;
            }
            &:hover {
                background-color: rgba($min-color, 0.1);
                color: $min-color;
            }
        }

        &__hour::after {
            background-color: $hour-color;
        }

        &__min::after {
            background-color: $min-color;
        }

        &__period {
            > div {
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                height: 100%;
            }
            span {
                line-height: 1;
                font-size: 0.4em;
                font-weight: 800;
                display: block;
                opacity: 0.33;
                &.is-selected {
                    opacity: 1;
                }
            }
        }

        &__period:hover {
            background-color: rgba($hour-color, 0.1);
            color: $hour-color;
        }
    }

    &__time.mode-hours.hovering {
        .px-clock__hour {
            background-color: rgba($hour-color, 0.1);
            color: $hour-color;
            // border-color: $app-fg;
            // border-bottom-left-radius: 0;
            // border-bottom-right-radius: 0;

            // border-color: $hour-color;
            // border-bottom-left-radius: 0;
            // border-bottom-right-radius: 0;
        }
    }

    &__time.mode-minutes.hovering {
        .px-clock__min {
            background-color: rgba($min-color, 0.1);
            color: $min-color;
            // border-color: $min-color;
            // border-bottom-left-radius: 0;
            // border-bottom-right-radius: 0;
        }
    }

    // adjust colors for minute mode
}
</style>
