<script>
const { ref, watch, computed, onMounted, nextTick } = require('vue');

function throttle(fn, delay) {
    let timer = null;
    return function () {
        if (!timer) {
            timer = setTimeout(() => {
                fn.apply(this, arguments);
                timer = null;
            }, delay);
        }
    }
}

function isMobile() {
    return window.innerWidth <= 576;
}

module.exports = {
    compatConfig: {
        MODE: 3
    },
    compilerOptions: {
        whitespace: 'condense'
    },
    props: {
        pageListLoader: {
            type: Object,
            default: null,
        },
        autoFocus: {
            type: Boolean,
            default: false,
        },
        lazyLoad: {
            type: Boolean,
            default: false
        }
    },
    setup(props) {
        const containerRef = ref();

        let initLoaded = false;

        const pageListLoading = ref(true);
        const contentLoading = ref(false);
        const pageList = ref([]);
        const selectedPageIdx = ref(null);
        const previewPageContent = ref('');
        const selectedPageUrl = ref('#');

        const bookletClassList = ref([]);

        const onSelectPage = (idx) => {
            selectedPageIdx.value = idx;
        }

        const selectedPageInfo = computed(() => {
            if (selectedPageIdx.value !== null && selectedPageIdx.value < pageList.value.length) {
                return pageList.value[selectedPageIdx.value];
            } else {
                return '';
            }
        });

        const loadPageList = () => {
            props.pageListLoader.loadPageList().then((loadedPageList) => {
                pageListLoading.value = false;
                pageList.value = loadedPageList;
                initLoaded = true;

                // 自动选中第一项
                if (!isMobile() && selectedPageIdx.value === null && props.autoFocus && pageList.value.length > 0) {
                    selectedPageIdx.value = 0;
                }
            }).catch((err) => {
                console.error(err);
            });
        }

        const loadPageContent = () => {
            contentLoading.value = true;
            selectedPageUrl.value = '#';
            props.pageListLoader.loadPageContent(selectedPageInfo.value).then((pageContent) => {
                contentLoading.value = false;
                previewPageContent.value = pageContent;

                props.pageListLoader.getPageUrl(selectedPageInfo.value).then((pageUrl) => {
                    selectedPageUrl.value = pageUrl;
                }).catch((err) => {
                    console.error(err);
                });
            }).catch((err) => {
                contentLoading.value = false;
                console.error(err);
            });
        }

        // 处理Lazy Load
        const onWindowScroll = throttle(() => {
            if (initLoaded) {
                window.removeEventListener('scroll', onWindowScroll, { passive: true });
                return;
            }

            let container = containerRef.value;
            let containerRect = container.getBoundingClientRect();
            let containerTop = containerRect.top;
            let containerBottom = containerRect.bottom;

            let windowHeight = window.innerHeight;

            if (containerTop < windowHeight && containerBottom > 0) {
                loadPageList();
                window.removeEventListener('scroll', onWindowScroll, { passive: true });
            }
        }, 100);

        const onClickBack = () => {
            focusMenuTransition().then(() => {
                selectedPageIdx.value = null;
            });
        }

        const focusContentTransition = () => {
            return new Promise((resolve, reject) => {
                // 进入动画
                bookletClassList.value = ['animating', 'focus-menu-transition'];
                nextTick(() => {
                    setTimeout(() => {
                        bookletClassList.value = ['animating', 'focus-content-transition'];
                    }, 10);

                    setTimeout(() => {
                        bookletClassList.value = ['focus-content'];
                        resolve();
                    }, 200);
                });
            });
        }

        const focusMenuTransition = () => {
            return new Promise((resolve, reject) => {
                // 退出动画
                bookletClassList.value = ['animating', 'focus-content-transition'];
                nextTick(() => {
                    setTimeout(() => {
                        bookletClassList.value = ['animating', 'focus-menu-transition'];
                    }, 10);

                    setTimeout(() => {
                        bookletClassList.value = ['focus-menu'];
                        resolve();
                    }, 200);
                });
            });
        }

        watch(() => selectedPageIdx.value, (newValue, oldValue) => {
            // 选中页面变化时，加载页面内容
            if (newValue !== null) {
                loadPageContent();
            }

            // 手机端页面动画
            if (oldValue === null && newValue !== null) {
                focusContentTransition();
            }
        });

        onMounted(() => {
            if (!props.pageListLoader) {
                console.error('pageListLoader is not set');
                return;
            }

            if (!props.lazyLoad) {
                loadPageList();
            } else {
                window.addEventListener('scroll', onWindowScroll, { passive: true });
                nextTick(() => {
                    onWindowScroll(); // init
                });
            }
        });

        return {
            // global mw object
            mw,
            // states
            containerRef,
            pageListLoading,
            contentLoading,
            pageList,
            selectedPageIdx,
            previewPageContent,
            selectedPageInfo,
            selectedPageUrl,
            bookletAnimateClassList: bookletClassList,
            // methods
            onSelectPage,
            onClickBack
        };
    }
};
</script>

<template>
    <div class="isekai-preview-page-list-container" ref="containerRef">
        <div v-if="pageListLoading" class="loading">
            <div class="spinner">
                <div class="oo-ui-widget oo-ui-widget-enabled oo-ui-progressBarWidget-indeterminate oo-ui-progressBarWidget"
                    aria-disabled="false" role="progressbar" aria-valuemin="0" aria-valuemax="100">
                    <div class="oo-ui-progressBarWidget-bar"></div>
                </div>
            </div>
        </div>
        <div v-else class="isekai-booklet-layout" :class="bookletAnimateClassList">
            <div class="isekai-booklet-menu">
                <ul class="isekai-list isekai-preview-page-list isekai-thin-scrollbar">
                    <a class="isekai-list-item" v-for="(pageInfo, idx) in pageList" :key="idx" href="javascript:;"
                        :class="{ active: idx === selectedPageIdx }" @click.prevent="onSelectPage(idx)">
                        <div class="isekai-list-item-content">
                            <div class="isekai-list-item-subtitle" v-if="pageInfo.subTitle">{{ pageInfo.subTitle }}</div>
                            <div class="isekai-list-item-title">
                                <div>{{ pageInfo.title }}</div>
                            </div>
                        </div>
                        <div class="isekai-list-item-icon">
                            <span
                                class="oo-ui-widget oo-ui-widget-enabled oo-ui-iconElement oo-ui-iconElement-icon oo-ui-icon-next oo-ui-labelElement-invisible oo-ui-iconWidget"
                                :class="{ 'oo-ui-image-invert': idx === selectedPageIdx, 'oo-ui-image-progressive': idx !== selectedPageIdx }"
                                aria-disabled="false"></span>
                        </div>
                    </a>
                </ul>
            </div>
            <div class="isekai-booklet-content" v-if="selectedPageIdx === null">
                <div class="isekai-preview-page-list-placeholder">
                    {{ mw.msg('isekai-preview-page-list-preview-placeholder') }}
                </div>
            </div>
            <div class="isekai-booklet-content" v-else>
                <div class="card-header">
                    <div class="card-header-buttons back-button-container">
                        <span class="oo-ui-widget oo-ui-widget-enabled oo-ui-buttonElement oo-ui-buttonElement-frameless oo-ui-iconElement oo-ui-buttonWidget">
                            <a class="oo-ui-buttonElement-button" role="button" tabindex="0" href="javascript:;" @click.prevent="onClickBack">
                                <span class="oo-ui-iconElement-icon oo-ui-icon-previous"></span>
                                <span class="oo-ui-labelElement-label oo-ui-labelElement-invisible">{{ mw.msg('isekai-preview-page-list-back-btn') }}</span>
                                <span class="oo-ui-indicatorElement-indicator oo-ui-indicatorElement-noIndicator"></span>
                            </a>
                        </span>
                    </div>
                    <div class="card-header-text">{{ selectedPageInfo && selectedPageInfo.title }}</div>
                    <div class="card-header-buttons">
                        <span class="oo-ui-widget oo-ui-widget-enabled oo-ui-buttonElement oo-ui-buttonElement-framed oo-ui-iconElement oo-ui-labelElement oo-ui-flaggedElement-primary oo-ui-flaggedElement-progressive oo-ui-buttonWidget">
                            <a class="oo-ui-buttonElement-button" role="button" tabindex="0" :href="selectedPageUrl" target="_blank">
                                <span class="oo-ui-iconElement-icon oo-ui-icon-ellipsis oo-ui-image-invert"></span>
                                <span class="oo-ui-labelElement-label">{{ mw.msg('isekai-preview-page-list-readmore-btn') }}</span>
                                <span class="oo-ui-indicatorElement-indicator oo-ui-indicatorElement-noIndicator oo-ui-image-invert"></span>
                            </a>
                        </span>
                    </div>
                </div>
                <div class="isekai-preview-container">
                    <div v-if="contentLoading" class="loading">
                        <div class="spinner">
                            <div class="oo-ui-widget oo-ui-widget-enabled oo-ui-progressBarWidget-indeterminate oo-ui-progressBarWidget"
                                aria-disabled="false" role="progressbar" aria-valuemin="0" aria-valuemax="100">
                                <div class="oo-ui-progressBarWidget-bar"></div>
                            </div>
                        </div>
                    </div>
                    <div v-else class="isekai-preview-content" v-html="previewPageContent"></div>
                </div>
            </div>
        </div>
    </div>
</template>