<template>
    <div class="infinite-scroll-container">
        <div class="viewport-stage">
            <div
                v-for="viewport in visibleViewports"
                class="viewport"
                :style="{
                    height: viewport.height + 'px',
                    transform: `translateY(${viewport.offsetY - scrollY}px)`,
                }"
                :key="viewport.index"
            >
                <slot
                    name="viewport"
                    :viewport="viewport"
                    :content="viewport.content"
                >
                    <!-- Default viewport content -->
                    <div class="default-viewport">
                        <h2>Viewport {{ viewport.index }}</h2>
                        <pre>{{
                            JSON.stringify(viewport.content, null, 2)
                        }}</pre>
                    </div>
                </slot>
            </div>
        </div>
    </div>
</template>

<script setup>
import { watch } from 'vue'
import { useInfiniteScroll } from '@/composables/useInfiniteScroll'

const props = defineProps({
    /**
     * Function to generate content for each viewport
     * @param {number} index - Viewport index
     * @returns {Promise|Object} Content for the viewport
     */
    generateContent: {
        type: Function,
        required: true,
    },

    /**
     * Height of each viewport in pixels
     * If not provided, will use window height
     */
    viewportHeight: {
        type: Number,
        default: null,
    },

    /**
     * Number of viewports to keep loaded outside visible area
     */
    bufferSize: {
        type: Number,
        default: 1,
    },

    /**
     * Starting viewport index
     */
    initialIndex: {
        type: Number,
        default: 0,
    },
})

const emit = defineEmits(['viewport-change', 'content-loaded'])

const {
    currentViewportIndex,
    visibleViewports,
    scrollY,
    reset,
    retryViewport,
    start,
    stop,
    hasError,
    errors,
    _state,
} = useInfiniteScroll({
    generateContent: async (index) => {
        const content = await props.generateContent(index)
        emit('content-loaded', { index, content })
        return content
    },
    viewportHeight: props.viewportHeight,
    bufferSize: props.bufferSize,
    initialIndex: props.initialIndex,
})

watch(currentViewportIndex, (newIndex, oldIndex) => {
    emit('viewport-change', { newIndex, oldIndex })
})

// Expose to parent
defineExpose({
    reset,
    retryViewport,
    start,
    stop,
    currentViewportIndex,
    visibleViewports,
    scrollY,
    hasError,
    errors,
    _state,
})
</script>

<style lang="scss">
.infinite-scroll-container {
    position: fixed;
    inset: 0;
    width: 100%;
    height: calc(100 * var(--vh));
    overflow: hidden;

    .viewport-stage {
        position: relative;
        width: 100%;
        height: 100%;
    }

    .viewport {
        box-sizing: border-box;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        will-change: transform;
    }
}
</style>
