<!--
    Usage:

    <px-flip :states="['select', 'interact']" :current="'select'">
        <template :state="state">
            <div :class="bem('container', { state })">
                <div data-pxflip>...</div>
                <div data-pxflip>...</div>
            </div>
        </template>
    </px-flip>
-->

<template>
    <div>
        <!-- in the component -->
        <slot name="default" :state="currentValue">
            <!-- fallback -->
        </slot>
    </div>
</template>

<script>
import { gsap } from 'gsap';
import { Flip } from 'gsap/Flip';

/**
 * Note that this component generally needs to use css instead of inline styles in order to work
 * properly because the animation will overwrite inline styles while transitioning.
 */
export default {
    name: 'px-flip',
    props: {
        states: { type: Array, default: null },
        current: { type: String, default: null },
        autoSelectFirstState: { type: Boolean, default: true },
        otherProps: { type: String, default: 'opacity,color,backgroundColor' },
        selector: { type: String, default: '[data-flip]' },
        targets: { default: null },
        duration: { type: Number, default: 0.5 },
        ease: { type: String, default: 'circ.out' },
        absolute: { type: Boolean, default: false },
    },
    data() {
        return { currentValue: this.current };
    },
    watch: {
        currentValue(nv) {
            this.$emit('update:current', nv);
        },

        async current(nv) {
            const targetElements = this.targets || this.$el.querySelectorAll(this.selector);

            // save initial state
            const state = Flip.getState(targetElements, { props: this.otherProps, absolute: true });

            // make state changes
            this.currentValue = nv;

            await this.$nextTick();
            // animate from the old state to the new one
            // animate from the previous state to the current one:

            Flip.from(state, {
                duration: this.duration,
                ease: this.ease,
                absolute: this.absolute,
            });
        },
    },
    mounted() {
        gsap.registerPlugin(Flip);

        if (!this.currentValue && this.autoSelectFirstState && this.states.length) {
            this.currentValue = this.states[0];
        }
    },
    methods: {
        nextState() {
            if (this.states) {
                const index = this.states.indexOf(this.currentValue);
                if (index >= 0) {
                    this.currentValue = this.states[(index + 1) % this.states.length];
                }
            }
        },
        toggle() {
            this.nextState();
        },
    },
};
</script>
