<template>
    <swiper
        class="m-tiktok-video-swiper"
        circular
        @change="swiperChange"
        :current="state.current"
        :vertical="true"
        duration="300"
    >
        <swiper-item v-for="(item, index) in state.displaySwiperList" :key="index">
            <view class="swiper-item" @click="(e) => handleClick(index, e)">
                <video
                    :id="`video__${index}`"
                    :controls="controls"
                    :autoplay="false"
                    :loop="loop"
                    @ended="ended"
                    @controlstoggle="controlstoggle"
                    @play="onPlay"
                    @error="emits('error')"
                    class="m-tiktok-video-player"
                    :src="item.src || item.explainUrl"
                    v-if="index === 0 || !state.isFirstLoad"
                ></video>
                <view class="cover-triangle" v-if="pause"></view>
                <image
                    v-if="item.poster && state.displayIndex != index"
                    :src="item.poster"
                    class="m-tiktok-video-poster"
                    mode="aspectFit"
                ></image>
                <slot :item="item"></slot>
            </view>
        </swiper-item>
    </swiper>
</template>

<script setup>
import { ref, reactive, getCurrentInstance, watch, nextTick } from 'vue';
import { onLoad, onUnload } from '@dcloudio/uni-app';
const _this = getCurrentInstance();
const emits = defineEmits(['play', 'error', 'loadMore', 'change', 'controlstoggle', 'click', 'ended']);

const lastTapTime = ref(0);
const pause = ref(false);
const props = defineProps({
    /**
     * 视频列表
     */
    videoList: {
        type: Array,
        default: () => [],
    },
    /**
     * 是否循环播放一个视频
     */
    loop: {
        type: Boolean,
        default: true,
    },
    /**
     * 显示原生控制栏
     */
    controls: {
        type: Boolean,
        default: true,
    },
    /**
     * 是否自动播放
     */
    autoplay: {
        type: Boolean,
        default: true,
    },
    /**
     * 是否自动滚动播放
     */
    autoChange: {
        type: Boolean,
        default: false,
    },
    /**
     * 滚动加载阈值（即播放到剩余多少个之后触发加载更多
     */
    loadMoreOffsetCount: {
        type: Number,
        default: 2,
    },
    /**
     * 暂停 1 单机暂停； 2 双击暂停； 0关闭
     */
    pauseType: {
        type: Number,
        default: 2,
    },
});

const state = reactive({
    originList: [], // 源数据
    displaySwiperList: [], // swiper需要的数据
    displayIndex: 0, // 用于显示swiper的真正的下标数值只有：0，1，2。
    originIndex: 0, // 记录源数据的下标
    current: 0,
    oid: 0,
    showControls: '',
    toggleShow: true, // 显示面板
    videoContexts: [],
    isFirstLoad: true,
});

const initVideoContexts = () => {
    state.videoContexts = [
        uni.createVideoContext('video__0', _this),
        uni.createVideoContext('video__1', _this),
        uni.createVideoContext('video__2', _this),
    ];
};

const onPlay = (e) => {
    emits('play', e);
};

const setVideoRef = (el, index) => {
    if (el) {
        videoRefs.value[index] = el;
    }
};

function handleClick(index, e) {
    const now = Date.now();
    switch (props.pauseType) {
        case 1:
            if (pause.value) {
                state.videoContexts[index].play();
                pause.value = false;
            } else {
                state.videoContexts[index].pause();
                pause.value = true;
            }
            break;
        case 2:
            if (now - lastTapTime.value < 300) {
                if (pause.value) {
                    state.videoContexts[index].play();
                    pause.value = false;
                } else {
                    state.videoContexts[index].pause();
                    pause.value = true;
                }
            }
            break;
    }
    lastTapTime.value = now;
    state.toggleShow = !state.toggleShow;
    emits('click', e);
}
function ended() {
    // 自动切换下一个视频
    if (props.autoChange) {
        if (state.displayIndex < 2) {
            state.current = state.displayIndex + 1;
        } else {
            state.current = 0;
        }
    }
    emits('ended');
}
/**
 * 初始一个显示的swiper数据
 * @originIndex  从源数据的哪个开始显示默认0，如从其他页面跳转进来，要显示第n个，这个参数就是他的下标
 */
function initSwiperData(originIndex = state.originIndex) {
    const originListLength = state.originList.length; // 源数据长度
    const displayList = [];
    displayList[state.displayIndex] = state.originList[originIndex];
    displayList[state.displayIndex - 1 == -1 ? 2 : state.displayIndex - 1] =
        state.originList[originIndex - 1 == -1 ? originListLength - 1 : originIndex - 1];
    displayList[state.displayIndex + 1 == 3 ? 0 : state.displayIndex + 1] =
        state.originList[originIndex + 1 == originListLength ? 0 : originIndex + 1];
    state.displaySwiperList = displayList;

    if (state.oid >= state.originList.length) {
        state.oid = 0;
    }
    if (state.oid < 0) {
        state.oid = state.originList.length - 1;
    }
    // 暂停所有视频
    state.videoContexts.map((item) => item?.stop());
    setTimeout(() => {
        // 当前视频
        if (props.autoplay) {
            uni.createVideoContext(`video__${state.displayIndex}`, _this).play();
        }
    }, 500);
    // 数据改变
    emits('change', {
        index: originIndex,
        detail: state.originList[originIndex],
    });
    // 加载更多
    var pCount = state.originList.length - props.loadMoreOffsetCount;
    if (originIndex == pCount) {
        emits('loadMore');
    }
}
/**
 * swiper滑动时候
 */
function swiperChange(event) {
    const { current } = event.detail;
    state.isFirstLoad = false;
    const originListLength = state.originList.length; // 源数据长度
    // 向后滚动
    if (state.displayIndex - current == 2 || state.displayIndex - current == -1) {
        state.originIndex = state.originIndex + 1 == originListLength ? 0 : state.originIndex + 1;
        state.displayIndex = state.displayIndex + 1 == 3 ? 0 : state.displayIndex + 1;
        state.oid = state.originIndex - 1;
        initSwiperData(state.originIndex);
    }
    // 如果两者的差为-2或者1则是向前滑动
    else if (state.displayIndex - current == -2 || state.displayIndex - current == 1) {
        state.originIndex = state.originIndex - 1 == -1 ? originListLength - 1 : state.originIndex - 1;
        state.displayIndex = state.displayIndex - 1 == -1 ? 2 : state.displayIndex - 1;
        state.oid = state.originIndex + 1;
        initSwiperData(state.originIndex);
    }
    state.toggleShow = true;
}

function controlstoggle(e) {
    state.showControls = e.detail.show;
    emits('controlstoggle', e);
}

watch(
    () => props.videoList,
    () => {
        if (props.videoList?.length) {
            state.originList = props.videoList;
            if (state.isFirstLoad || !state.videoContexts?.length) {
                initSwiperData();
                initVideoContexts();
            }
        }
    },
    {
        immediate: true,
    }
);

let loadTimer = null;
onLoad(() => {
    // 为了首次只加载一条视频（提高首次加载性能），延迟加载后续视频
    loadTimer = setTimeout(() => {
        state.isFirstLoad = false;
        clearTimeout(loadTimer);
    }, 5000);
});

onUnload(() => {
    clearTimeout(loadTimer);
});

defineExpose({
    initSwiperData,
});
</script>

<style lang="stylus" scoped>
.m-tiktok-video-swiper,
.m-tiktok-video-player {
    width: 100%;
    height: 100%;
    background-color: #000;
}
.m-tiktok-video-swiper {
    .swiper-item {
        position: relative;
        height: 100%;
    }
    .m-tiktok-video-poster {
        background-color: #000;
        position: absolute;
        width: 100%;
        height: 100%;
    }
}

.cover-triangle{
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%)
    width: 132rpx
    height: 132rpx
    border-radius: 50%;
    background: rgba(0,0,0,0.3)
}
.cover-triangle::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-40%, -50%) rotate(90deg);
    width: 0;
    height: 0;
    border-left: 40rpx solid transparent;
    border-right: 40rpx solid transparent;
    border-bottom: 60rpx solid #fff;
}
</style>
