<!--
    #VUE3 Done

    Creates a toggle button (a control with the appearance of a normal button that can be toggle
    between an on/off state).

    <px-toggle v-model:checked="isChecked" variant="sm" />
-->

<template>
    <button
        :class="[bem({ checked: checkedValue, icon: iconReady, ...variantsMap }), calcCheckedClass]"
        :role="ariaRole"
        :aria-checked="ariaChecked"
        :aria-expanded="ariaExpanded"
        :aria-controls="controls"
        v-bind="{ ...$props, ...$attrs }"
        @click="toggleChecked"
    >
        <span v-if="hasIcon" :class="bem('icon')">
            <PxIcon v-if="!!icon" v-bind="iconAttrs" :style="checkedVisibleStyle" />
            <PxIcon
                v-if="!!iconUnchecked"
                v-bind="iconUncheckedAttrs"
                :style="uncheckedVisibleStyle"
            />
        </span>

        <slot>
            <span :class="bem('label')">
                <span :style="checkedVisibleStyle">{{ label }}</span>
                <span :style="uncheckedVisibleStyle">{{ labelUnchecked }}</span>
            </span>
        </slot>

        <!-- <span
            v-if="hasIcon"
            :class="bem('icon')"
            :style="{
                opacity: iconOpacity,
                transform: iconTransform,
                width: cssPx(iconWidth),
            }"
        >
            <PxIcon ref="icon" @loaded="iconLoaded" v-bind="piconAttrs" />
        </span>
        <span
            :class="bem('content')"
            :style="{
                transform: contentTransform,
                paddingLeft: hasIcon ? cssEm(iconSize / 3 + 0.16) : null,
                paddingRight: hasIcon ? cssEm(iconSize / 3 + 0.16) : null,
            }"
        >
            <slot>
                {{ calcLabel }}
            </slot>
        </span> -->
    </button>
</template>

<script>
import PxBase from '../bases/PxBase.vue';
import PxBaseToggle from '../bases/PxBaseToggle.vue';
import PxButton from './PxButton.vue';
import { PxIconSrcOrAttrs, PxIcon } from './PxIcon.vue';

export default {
    name: 'px-toggle-button',
    mixins: [PxBase, PxBaseToggle],
    components: { PxIcon, PxButton },
    props: {
        /**
         * Label text to be displayed in the checked state in the default slot.
         */
        label: { type: String, default: null },

        /**
         * Label text to be displayed in the unchecked state in the default slot.
         */
        labelUnchecked: { type: String, default: null },

        /**
         * Icon to be displayed in the the checked state. If a string is provided, it will be
         * interpreted as the src of the icon. If an object is provided, it will be passed directly
         * to the icon component as props. See PxIcon for the full list of supported attributes.
         */
        icon: { type: [String, Object], default: null },

        /**
         * Icon to be displayed in the the unchchecked state. If a string is provided, it will be
         * interpreted as the src of the icon. If an object is provided, it will be passed directly
         * to the icon component as props. See PxIcon for the full list of supported attributes.
         */
        iconUnchecked: { type: [String, Object], default: null },

        /**
         * Whether space for the icon should be preserved in the layout even when the icon isn't
         * being rendered.
         */
        preserveIconSpace: { type: Boolean, default: false },

        /**
         *  (Accessibility) Mode of the toggle button (switch | expander)
         */
        mode: { type: String, default: 'switch' },

        /**
         * (Accessibility) id of the element that this toggle button controls
         */
        controls: { type: String, default: null },
    },
    computed: {
        iconAttrs() {
            return PxIconSrcOrAttrs(this.icon);
        },
        iconUncheckedAttrs() {
            return PxIconSrcOrAttrs(this.iconUnchecked);
        },
        hasBothLabels() {
            return !!this.label && !!this.labelUnchecked;
        },
        hasIcon() {
            return !!this.icon || !!this.iconUnchecked;
        },
        checkedVisibleStyle() {
            return this.checkedValue ? null : { opacity: 0 };
        },
        uncheckedVisibleStyle() {
            return this.checkedValue ? { opacity: 0 } : null;
        },

        // hasIcon() {
        //     return !!this.picon;
        // },
        // iconTransform() {
        //     if (this.hasIcon) {
        //         return this.checkedValue
        //             ? `scale(1) translateX(${this.cssEm(this.iconSize * 0.2)})`
        //             : `scale(1) translateX(${this.cssEm(this.iconSize * 0.4)})`;
        //     }
        //     return null;
        // },
        // contentTransform() {
        //     if (this.hasIcon) {
        //         return this.checkedValue ? `translateX(${this.cssEm(0.33)})` : `translateX(0)`;
        //     }
        //     return null;
        // },
        // iconOpacity() {
        //     return this.checkedValue ? 1 : 0;
        // },
        // calcLabel() {
        //     if (this.labelUnchecked && !this.checkedValue) {
        //         return this.labelUnchecked;
        //     }
        //     return this.label;
        // },
        isSwitch() {
            return this.mode === 'switch';
        },
        ariaRole() {
            return this.mode === 'expander' ? 'button' : 'switch';
        },
        ariaChecked() {
            if (!this.isSwitch) {
                return null;
            }

            return this.checked ? 'true' : 'false';
        },
        ariaExpanded() {
            if (this.isSwitch) {
                return null;
            }

            return this.checked ? 'true' : 'false';
        },
    },
    data() {
        return {
            iconReady: false,
            iconWidth: 0,
        };
    },
    methods: {
        iconLoaded() {
            setTimeout(() => {
                // used to enable transitions only after the icon is loaded (and avoid a "bounce" on load)
                this.iconWidth = this.$refs.icon.$el.getBoundingClientRect().width;
            });
        },
    },
};
</script>

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

@at-root {
    :root {
        // background for the entire table
        --px-toggle-button-gap: 0.33em;
        --px-toggle-button-icon-offset: -0.33em;
    }
}

.px-toggle-button {
    &--default {
        @include button();
    }

    & {
        gap: var(--px-toggle-button-gap);
    }

    &__icon,
    &__label {
        display: inline-grid;
        grid-template-rows: auto;
        grid-template-columns: auto;
        > * {
            grid-area: 1/1;
        }
    }

    &__icon {
        margin-inline-start: var(--px-toggle-button-icon-offset);
        justify-items: center;
        align-items: center;
    }

    // &__content {
    //     display: inline-flex;
    //     grid-template-rows: auto;
    //     grid-template-columns: auto;
    //     > span {
    //         display: inline-flex;
    //         align-items: center;
    //         justify-content: center;
    //         gap: var(--px-toggle-button-icon-gap);
    //         grid-area: 1/1;
    //     }
    // }

    // &__icon {
    //     position: relative;
    //     display: inline-flex;
    //     align-items: center;
    //     width: 0px;
    //     max-width: 0px;
    //     flex: none;
    //     left: 0;
    //     z-index: 1;

    //     .px-icon {
    //         left: 0;
    //         position: absolute;
    //         transform: translateX(-50%);
    //     }
    // }

    // default checked state
    &--checked.px-button--default:not(:disabled) {
        background-color: clr(select);
        box-shadow: none;
        &:hover {
            background-color: clr(select);
            box-shadow: none;
        }
    }

    // outline checked state
    &--checked.px-button--outline:not(:disabled) {
        background-color: clr(accent, 0.15);
    }

    &--icon & {
        &__icon,
        &__content {
            @include transition(transform opacity);
        }
    }
}
</style>
