<template>
    <div
        class="mosaic-viewport"
        v-intersect:once="{
            callback: onIntersect,
            rootMargin: '-25% 0px -25% 0px',
        }"
    >
        <div class="mosaic-container">
            <router-link
                v-for="(cell, i) in content.cells"
                :class="[
                    'mosaic-cell',
                    `layout-${cell.width * wWidth >= cell.height * wHeight ? 'landscape' : 'portrait'}`,
                ]"
                :style="{
                    left: cell.x * 100 + 'vw',
                    top: cell.y * 100 + 'vh',
                    width: cell.width * 100 + 'vw',
                    height: cell.height * 100 + 'vh',
                }"
                :to="{
                    name: 'mosaic-item',
                    params: { id: cell.content.slug },
                }"
                :key="`${viewport.index}-${cell.id}`"
                @mouseenter="onMouseEnter(i)"
                ref="cells"
            >
                <div class="hover-bg" :style="{ background: hoverColors[i] }" />
                <strapi-media
                    :image="cell.content.image"
                    :aspect="100"
                    fit="contain"
                />
            </router-link>
        </div>
    </div>
</template>

<script setup>
import { ref } from 'vue'
import gsap from 'gsap'
import { useWindowSize } from '@vueuse/core'

const THEME_S = 90
const THEME_L = 50

const props = defineProps({
    viewport: {
        type: Object,
        required: true,
    },
    content: {
        type: Object,
        required: true,
    },
})

const cells = ref([])
const hoverColors = ref(
    cells.value.map(
        () => `hsl(${Math.random() * 360}deg ${THEME_S}% ${THEME_L}%)`,
    ),
)

const { width: wWidth, height: wHeight } = useWindowSize()

const onMouseEnter = (i) => {
    hoverColors.value[i] =
        `hsl(${Math.random() * 360}deg ${THEME_S}% ${THEME_L}%)`
}

const onIntersect = (isIntersecting) => {
    if (isIntersecting) {
        if (!cells.value) return

        const cellGifs = cells.value
            .map((cell) => cell.$el?.children?.[1])
            .filter(Boolean)

        gsap.to(cellGifs, { opacity: 1, duration: 0, stagger: 0.1 })
    }
}
</script>

<style lang="scss">
.mosaic-viewport {
    height: calc(100 * var(--vh));
    display: flex;
    position: relative;
    overflow: hidden;

    .mosaic-container {
        flex: 1;
        position: relative;

        .mosaic-cell {
            position: absolute;
            overflow: hidden;
            border: 0.5px solid var(--theme-fg);
            cursor: pointer;
            display: flex;
            justify-content: center;
            align-items: center;
            background: var(--theme-bg);

            &.layout-portrait {
                .strapi-media {
                    width: 40%;
                    aspect-ratio: 1;
                }
            }
            &.layout-landscape {
                .strapi-media {
                    height: 40%;
                    aspect-ratio: 1;
                }
            }
            .hover-bg {
                position: absolute;
                inset: 0;
                clip-path: circle(0% at 50% 50%);
                transition: clip-path 0.3s ease-in-out;
            }
            .strapi-media {
                opacity: 0;
                position: relative;
                z-index: 5;
            }

            &:hover {
                .strapi-media {
                    @include bonk-animation(0s, 1s, 10deg);
                }
                .hover-bg {
                    clip-path: circle(100% at 50% 50%);
                }
            }
        }
    }
}
</style>
