<!--
    Describe this component...
-->
<template>
    <div :class="bem()">
        <transition-group :class="bem('group')" name="px-background-fader__fade" tag="div">
            <div
                v-for="background in backgrounds"
                :key="background.id"
                :class="bem('background')"
                :style="{
                    transitionDuration: duration ? duration + 's' : null,
                }"
            >
                <slot name="background" v-bind="background">
                    <div
                        :class="[background.value, ...backgroundClassArray]"
                        :style="backgroundStyle"
                    />
                </slot>
                <slot name="default" />
            </div>
        </transition-group>
    </div>
</template>

<script>
export default {
    name: 'px-background-fader',
    props: {
        /** A background items can be anything. This will be made available to the background slot
         * and the slot can render accordingly. The default slot assumes that the background is a
         * class names and creates a div and sets the class. When the background is set, we will
         * crossfade between the contents of the two slots. */
        background: { default: null },

        /** An additional class that gets applied to the background element in the default slot. */
        backgroundClass: { default: 'px-background-fader__bg' },

        /** Value for the style property that gets applied to the background element in th default slot */
        backgroundStyle: { default: null },

        /**
         * The duration of the fade animation in seconds.
         */
        duration: { type: Number, default: 0 },
    },
    data() {
        const backgroundId = 0;
        const backgrounds = this.background ? [{ id: backgroundId, value: this.background }] : [];
        return {
            backgrounds,
            backgroundId,
            fadeLeaveDelay: this.duration ? this.duration : '',
        };
    },

    computed: {
        backgroundClassArray() {
            if (Array.isArray(this.backgroundClass)) {
                return this.backgroundClass;
            }
            return [this.backgroundClass];
        },
        fadeLeaveDelayCalc() {
            if (this.fadeLeaveDelay !== null) {
                return this.fadeLeaveDelay + 's';
            }
            return '--fade-leave-delay-def';
        },
    },
    watch: {
        background(nv, ov) {
            if (this.compareItems(nv, ov)) {
                return;
            }

            this.fadeLeaveDelay = ov ? this.duration : 0;

            if (ov && this.backgrounds.length) {
                this.backgrounds.shift();
            }

            if (nv) {
                this.backgroundId++;
                this.backgrounds.push({ id: this.backgroundId, value: nv });
            }
        },
    },
    methods: {
        compareItems(a, b) {
            if (a == b) {
                return true;
            }

            if (typeof a == 'object' && typeof b == 'object') {
                return JSON.stringify(a) == JSON.stringify(b);
            }

            return false;
        },
    },
};
</script>

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

@include vue-transition(px-background-fader__fade) {
    $dur: 0.5s;

    @include vt-transition {
        @include transition(opacity, $dur: $dur);
    }
    @include vt-leaving() {
        --fade-leave-delay-def: $dur;
        transition-delay: v-bind(fadeLeaveDelayCalc);
    }
    @include vt-hidden {
        opacity: 0;
    }
}

.px-background-fader {
    width: 100%;
    height: 100%;
    position: relative;

    &__group {
        display: contents;
    }

    &__bg {
        @include abs();
    }
}
</style>
