<script setup lang="ts">

import {CSSProperties, reactive, ref, shallowRef, watch} from "vue";
import {FileMetas, Pagination, Position, RectangleSize} from "./model.ts";
import {ImageItem, ImagePreloader} from "./image-preloader.ts";

const props = withDefaults(defineProps<{
    metas: FileMetas,
    viewportSize: RectangleSize,
    defaultPage?: number,
    headless?: boolean,
    dev?: boolean
}>(), {
    defaultPage: 1,
    headless: false,
    dev: false
});

const emit = defineEmits<{
    paginationChange: [pagination: Pagination];
    loading: [boolean];
}>();

const totalPages = ref(0);
const current = ref<ImageItem|null>(null);
const renderTs = ref(0);
const preloader = shallowRef<ImagePreloader>(null as any);

const contentStyle = reactive<CSSProperties>({});

/**
 * 计算内容区的样式
 */
const calContentStyle = (): void => {
    if (!current.value || !current.value.width || !current.value.height) {
        contentStyle.top = "0";
        contentStyle.left = "0";
        contentStyle.width = "100%";
        contentStyle.height = "100%";
    } else {
        const scaleX = props.viewportSize.width / current.value.width;
        const scaleY = props.viewportSize.height / current.value.height;
        const contentScale = Math.min(scaleX, scaleY);
        const contentWidth = Math.floor(current.value.width * contentScale);
        const contentHeight = Math.floor(current.value.height * contentScale);
        const contentLeft = Math.floor((props.viewportSize.width - contentWidth) / 2);
        const contentTop = Math.floor((props.viewportSize.height - contentHeight) / 2);

        contentStyle.width = `${contentWidth}px`;
        contentStyle.height = `${contentHeight}px`;
        contentStyle.top = `${contentTop}px`;
        contentStyle.left = `${contentLeft}px`;
    }
}

const goto = async (pos: Position): Promise<void> => {
    console.log("[cf-player] (image-h) goto ", pos);
    let page = pos.page;
    if (pos.page > totalPages.value) {
        page = totalPages.value;
    }
    if (pos.page < 1) {
        page = 1;
    }

    calContentStyle();
    current.value = preloader.value.pre(page);

    emit("paginationChange", {total: totalPages.value, current: page});
    if (page < totalPages.value) {
        preloader.value.pre(pos.page + 1);
    }
    if (page > 1) {
        preloader.value.pre(pos.page - 1);
    }
}

const prev = async (): Promise<void> => {
    if (!current.value) {
        return ;
    }
    await goto({page: current.value.page - 1});
};

const next = async (): Promise<void> => {
    if (!current.value) {
        return ;
    }
    await goto({page: current.value.page + 1});
}

// 监听 metas 变化，重新初始化
watch(() => props.metas, (newMetas) => {
    console.log("[cf-player] (image-h) metas changed, reinitializing...");
    totalPages.value = newMetas.page ? newMetas.page : 0;
    current.value = null;
    renderTs.value = 0;
    
    // 重新创建 preloader
    preloader.value = new ImagePreloader(newMetas);
    preloader.value.on("loaded", () => {
        if (!renderTs.value) {
            emit("loading", false);
        }
        calContentStyle();
        renderTs.value = Date.now();
    });
    
    // 加载指定页
    emit("loading", true);
    goto({page: props.defaultPage});
}, { deep: true, immediate: true });

defineExpose({
    prev,
    next,
    goto,
});

</script>

<template>
    <div class="cf-player__engine cf-player__engine--image-horizontal">
        <div ref="contentEl" class="cf-player__content" v-if="current && renderTs > 0" :style="contentStyle">
            <img v-if="current.state === 'loaded'" :src="current.el?.currentSrc" :alt="`第${current.page}页`" />
            <div v-else-if="['unloaded', 'queueing', 'loading'].includes(current.state)">
                第{{ current.page }}页，正在加载中...
            </div>
            <div v-else>
                第{{ current.page }}页，加载失败...
            </div>
        </div>
    </div>
</template>
