<template>
    <div :class="bem()" ref="loadmore" >
        <div @click="reload" v-if="isError" :class="[bem('btn'), bem('error')]">
            <slot name="error" >加载失败，请重试</slot>
        </div>
        <div v-else-if="innerNoMore">
            <div :class="bem('nomore')">
                <!-- 这里提供了默认文本，提供了默认的组件gd-nomore模板 -->
                <slot name="nomore">
                    没有更多了
                </slot>
            </div>
        </div>
        <template v-else>
            <slot name="more" :reload="reload" :isLoading="pending" v-if="!autoLoad">
                <div :class="bem('btn')" @click="reload">
                    <Icon v-if="pending" name="loading" />
                    加载更多
                </div>
            </slot>
            <div v-else :class="bem('loading')">
                <slot name="loading" >
                    <span>玩命加载中...</span>
                </slot>
            </div>
        </template>
        <slot name="footer"/>
    </div>
</template>

<script>
import { createComponentName, componentMixin } from '../_utils/component';
import Icon from '../Icon';
import NomoreTemplets from './NomoreTemplets';
import { isSSR } from '../_utils/constant';

if (!isSSR()) {
    require('intersection-observer');
}

export default {
    name: createComponentName('loadmore'),
    components: {
        Icon,
    },
    NomoreTemplets,
    mixins: [componentMixin],
    props: {
        // 业务方请求
        loadmore: {
            type: Function,
            required: true,
        },
        // 是否自动加载更多
        autoLoad: {
            type: Boolean,
            default: true,
        },
        // 无数据状态
        isNoMore: {
            type: Boolean,
            default: false,
        },
        // 加载失败状态
        isError: {
            type: Boolean,
            default: false,
        },
        // 视图窗口展示的百分比 执行数据加载
        threshold: {
            type: Number,
            default: 0.5
        },
        // 距离底部加载的距离
        offset: {
            type: Number,
            default: 0
        },
    },
    data() {
        return {
            pending: false,
            innerNoMore: this.isNoMore,
        };
    },
    watch: {
        isNoMore(v) {
            setTimeout(() => {
                this.innerNoMore = v;
            }, 1000);
            if (!v) this.tryLoad();
        },
        isError(v) {
            if (!v) this.tryLoad();
        }
    },
    mounted() {
        // 传入fn进来 dom 渲染交给业务  返回promise 来操作页面loading状态
        const onIntersection = (observation) => {
            observation.forEach(async(change) => {
                this.intersectionRatio = change.intersectionRatio;
                this.tryLoad();
            });
        };

        this.observer = new IntersectionObserver(onIntersection, { threshold: [0, 0.25, 0.5, 0.75, 1], rootMargin: `0px 0px ${this.offset}px 0px` });
        const bottom = this.$refs.loadmore;
        this.observer.observe(bottom);
    },
    beforeDestroy() {
        if (this.$refs.loadmore && this.observer) {
            this.observer.unobserve(this.$refs.loadmore);
        }
    },
    methods: {
        async tryLoad() {
            if (!this.pending && this.intersectionRatio > this.threshold) {
                // 无数据状态 数据加载失败状态 不触发分页加载
                if (!this.autoLoad || this.isError || this.isNoMore) {
                    return;
                }
                await this.load();
            }
        },
        async reload() {
            await this.load();
        },
        async load() {
            this.pending = true;
            try {
                await this.loadmore();
                this.pending = false;

                // 处理加载更多后，组件仍处于视口，需要再重新重新加载下一页
                setTimeout(() => {
                    this.tryLoad();
                }, 0);
            }
            catch (error) {
                this.pending = false;
                throw error;
            }
        }
    }
};
</script>
<style lang="less">
@import '../_styles/base.less';

.@{loadmore} {
    min-height: 1px;

    &__nomore {
        text-align: center;
        width: 100%;
        margin-bottom: 70px;
    }
    &__min-height {
        min-height: 48px;
        margin-bottom: 70px;
    }
    &__loading{
        height: 48px;
        display: block;
        line-height: 48px;
        padding: 0;
        margin-bottom: 70px;

        color: #888;
        font-size: 14px;
        text-align: center;

        > span{
            &:before{
                display: inline-block;
                content: "";
                background-image: url('../../assets/img/loading.gif');
                // background: svg-load('../assets/icons/loader.svg', stroke=#888);
                background-size: contain;
                margin: -1px 5px 0 0;
                height: 1em;
                width: 1em;
                vertical-align: middle;

                // animation: rotation 1.6s linear infinite;
            }
        }
    }
    &__btn {
        position: relative;
        left: 50%;
        margin-left: -122px;
        width: 244px;
        height: 48px;
        line-height: 48px;
        background: #000;
        color: #fff;
        box-shadow: 0px 2px 8px 0px rgba(0,0,0,0.06);
        border-radius: 2px;
        color: #fff;
        font-size: 14px;
        display: flex;
        justify-content: center;
        align-items: center;
        cursor: pointer;
        margin-bottom: 70px;

        & .@{icon}--loading {
            margin-right: 6px;
            margin-left: -20px;
        }
    }
}
</style>
