<template>
    <div class="watcher_file">
        <div v-if="filePreviewList.includes(previewType)" class="preview_item">
            <PdfViewer 
                :initCourseLearnPage="props.initCourseLearnPage"
                @pageChange="(params)=>HandlePageChange('pdf',params)"
                :showPage="props?.allowDragOrShowPage === 0 ? false : true"
                :pdf-url="props?.fileMessage?.url" 
                v-if="previewType == 'pdf'" 
            />
            <vue-office-excel
                class="preview_main"
                v-else-if="previewType == 'xlsx'"
                :src="props?.fileMessage?.url"
                :options="excelOptions"
                @rendered="renderedHandler"
                @error="errorHandler"
            />

            <vue-office-docx
                class="preview_main"
                v-else-if="previewType == 'docx'"
                :src="props?.fileMessage?.url"
                @rendered="renderedHandler"
                @error="errorHandler"
            />

            <div 
                v-else-if="['mp4','avi','mpg','mpeg','wmv','mkv','mov','flv','mpg'].includes(previewType)" 
                class="preview_main"  
            >
             <!--  视频时间的执行先后顺序 
                @loadeddata  (1) 视频初始加载一次
                @seeking    (2)
                @timeupdate (3)
                videoPlayer.value.currentTime 的变更 会触发 (2)(3) 依次执行
            -->
                
            <video 
                @loadeddata="HandleVideoLoaded"
                @seeking="props?.allowDragOrShowPage ? '' : HandleVideoDragStart()"
                style="background-color: black;"
                ref="videoPlayer" 
                @timeupdate="handleTimeUpdate"
                @ratechange="handleRateChange"
                controls 
                controlslist="nodownload nofullscreen"
                :src="props?.fileMessage?.url" 
            />
            <img  class="full_screen" :src="isFullScreen ? exitFullScreenIcon : fullScreenIcon" alt=""  @click="HandleFullScreen">
        </div>
                
           

            <PptViewer
                :initCourseLearnPage="props.initCourseLearnPage"
                @pageChange="(params)=>HandlePageChange('ppt',params)"
                @fileLoaded="emit('pptLoaded')"
                v-else-if="['pptx'].includes(previewType)"    
                :fileMessage="props?.fileMessage">
            </PptViewer>

            <img  @click="HandleImgPreview" style="text-align: center;" v-else-if="['jpg','png','jpeg','gif','svg','webp'].includes(previewType)" :src="props?.fileMessage?.url"/>
            
        
        </div>
        <div style="text-align: center;" v-else-if="previewType == '加载中'">加载中...</div>
        <div style="text-align: center;" v-else>不支持预览 .{{ previewType }}文件</div>

         <el-image-viewer
            v-if="imgVisible"
            :url-list="[props?.fileMessage?.url]"
            show-progress
            @close="imgVisible = false"
        />

        <!-- 页面指示器 -->
        <div class="nav_group" v-if="totalPage > 0"> 
            <span :class="['pre_nav',{'first':currentPage === 1} ]" @click="currentPage == 1 ? '' : HandlePageJump('reduce')">
                <el-icon><ArrowLeftBold /></el-icon>
            </span>
            <span :class="['next_nav',{'end':currentPage === totalPage}]" @click="currentPage === totalPage ?  '' : HandlePageJump('add')">
                <el-icon><ArrowRightBold /></el-icon>
            </span>
        </div>

        <!-- <div v-if="previewType == 'docx'" class="pageProcess">
           进度：{{ progressPercent }} %
        </div> -->


    </div>
</template>   


<script setup lang="ts">
import PdfViewer from './PdfViewer/PdfViewer.vue'
import PptViewer from './PptViewer/PptViewer.vue'
import { ref, computed, onMounted, watch } from 'vue'

import fullScreenIcon from '@/assets/icon/fullScreen.png'
import exitFullScreenIcon from '@/assets/icon/exitFullScreen.png'


//引入VueOfficeExcel组件
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
//引入VueOfficeDocx组件
import VueOfficeDocx from '@vue-office/docx'
//引入相关样式
import '@vue-office/docx/lib/index.css'

interface FileMsg {
    name:String,
    url:String
}


const props = defineProps({
    fileMessage:{
        required:true,
        type:Object
    },
    allowDragOrShowPage:{
        type:null,
        required:false,
        default:true,
    },
    initRecord:{
        type:null,
        required:false,
    },
    updateVideoCurrentTime:{
        type:Number
    },
    initCourseLearnPage:{
        type:Number,
        required:false,
        default:0
    }
})


const emit = defineEmits(['processChange','pptLoaded','manulFullScreen'])

const videoProcessUpdateFlag = ref()  //进度更新状态标识
const currentVideoTime = ref(0)  //只记录用户的前进，不记录回退

// const videoPlayer = ref()
const videoPlayer = defineModel('videoPlayer')
const defaultVideoRate = ref(1)

const handleRateChange = (event)=>{
    let currentRate = event.target.playbackRate
    console.log('当前速率',currentRate)
    defaultVideoRate.value = currentRate
}

const handleTimeUpdate = ()=>{
    const video = videoPlayer.value;
    const currentTime = Math.floor(video?.currentTime); // 当前播放时间（秒）
    const duration = Math.floor(video?.duration); // 视频总时长（秒）

    // 播放的结尾的时候再触发一次 更新
    if(videoProcessUpdateFlag.value && currentTime !== duration){
        return
    }

    // 只记录用户的前进，不记录回放
    if(currentVideoTime.value < currentTime){
        currentVideoTime.value = currentTime
    }

    emit('processChange',{type:'video',
                        videoDuration:duration,
                        currentVideoTime:currentTime,
                        latestWatchTime:currentVideoTime.value})  //记录 用户的实际播放位置 和 最新的前进进度
    // 获取视频播放倍数
    // 要保证 同步频率 和视频的播放速度一致 或者更快（整数倍）
    videoProcessUpdateFlag.value = setTimeout(()=>{
        console.log('进度更新了')
        console.log('视频当前时间-总时长',currentTime,'-',duration)
        clearTimeout(videoProcessUpdateFlag.value)
        videoProcessUpdateFlag.value = null
        /** 遇到小数的情况下
         * floor：
            同步相对快
            速率相对慢
            ceil：
            同步相对慢
            速率相对快
         */
        // 这个后续过程中是否会有问题，待确认 —— 待完善
        // 确保视频前进1s同步一次
    },Math.floor(1000 / defaultVideoRate.value))
}


const currentPage = ref(1)
const totalPage = ref(0)


const pageTotalHeight = ref(0)
const currentReadHeight = ref(0)
const progressPercent = computed(()=>{
    if(currentReadHeight.value == 0 || pageTotalHeight.value == 0){
        return 0
    }
    return Math.round((currentReadHeight.value / pageTotalHeight.value) * 100)
})


const filePreviewList = ref(['pptx','pdf','gif','jpeg','jpg','png','svg','webp','xlsx','docx','mp4','avi','mpg','mpeg','wmv','mkv','mov','flv','mpg'])
const imgVisible = ref(false)

/**
 * 
 */
const previewType = ref('加载中')

const excelOptions = {
    xls: false,       //预览xlsx文件设为false；预览xls文件设为true
    minColLength: 0,  // excel最少渲染多少列，如果想实现xlsx文件内容有几列，就渲染几列，可以将此值设置为0.
    minRowLength: 0,  // excel最少渲染多少行，如果想实现根据xlsx实际函数渲染，可以将此值设置为0.
    widthOffset: 10,  //如果渲染出来的结果感觉单元格宽度不够，可以在默认渲染的列表宽度上再加 Npx宽
    heightOffset: 10, //在默认渲染的列表高度上再加 Npx高
    beforeTransformData: (workbookData) => {return workbookData}, //底层通过exceljs获取excel文件内容，通过该钩子函数，可以对获取的excel文件内容进行修改，比如某个单元格的数据显示不正确，可以在此自行修改每个单元格的value值。
    transformData: (workbookData) => {return workbookData}, //将获取到的excel数据进行处理之后且渲染到页面之前，可通过transformData对即将渲染的数据及样式进行修改，此时每个单元格的text值就是即将渲染到页面上的内容
}


const timeoutFlag = ref()

const HandleScroll = (e)=>{
    if(timeoutFlag.value){
        clearTimeout(timeoutFlag.value)
    }
    timeoutFlag.value =  setTimeout(() => {

        let totalHeight = e.target.scrollHeight  //总高度
        let scrollTop = e.target.scrollTop   //滚动高度
        let pageHeight = e.target.clientHeight // 客户端高度

        // 用户阅读进度  = ( pageHeight + scrollTop ) / totalHeight
        console.log('滚动事件',e)
        console.log('滚动高度',scrollTop)
        console.log('总高度',totalHeight)
        console.log('客户端高度',pageHeight)

        pageTotalHeight.value = Math.floor(Number(totalHeight)) || 0
        currentReadHeight.value = Math.floor( Number(pageHeight) + Number(scrollTop) ) || 0
        
        emit('processChange',{type:'docx',currentProcess:progressPercent.value})

        clearTimeout(timeoutFlag.value)
        timeoutFlag.value = null
    }, 200);
}

const excelScrollTimeOutFlag = ref()
const HandleExcelScroll = (e,type)=>{
    if(excelScrollTimeOutFlag.value){
        clearTimeout(excelScrollTimeOutFlag.value)
    }
    excelScrollTimeOutFlag.value =  setTimeout(() => {
        emit('processChange',{type:'excel'})
        clearTimeout(excelScrollTimeOutFlag.value)
        excelScrollTimeOutFlag.value = null
    }, 200);
}

const HandlePageChange = (type,params)=>{
    emit('processChange',{type,...params})
}

const isFullScreen = ref(false)

const HandleVideoLoaded = ()=>{
    if(['mp4','avi','mpg','mpeg','wmv','mkv','mov','flv','mpg'].includes(previewType.value)){
        videoPlayer.value.currentTime = currentVideoTime.value
    }
    // 禁用右击事件
    videoPlayer.value.addEventListener('contextmenu', (event) => {
        event.preventDefault();
    });

    if (document.fullscreenElement) {
        isFullScreen.value = true
    }else{
        isFullScreen.value = false
    }




}
const HandleVideoDragStart = ()=>{
    console.log('拖拽开始',videoPlayer.value.currentTime)
    console.log('历史播放记录',currentVideoTime.value)
    // 只能拖拽已观看部分，不能拖拽未观看部分
    if(videoPlayer.value.currentTime > currentVideoTime.value){
        videoPlayer.value.currentTime = currentVideoTime.value
    }
}

const HandlePageRedirect = (dom)=>{
     // docx 的进度重定位放到这里
    // props.initCourseLearnPage
    // 根据百分比 换算滚动高度
    let totalHeight = dom.scrollHeight  //总高度
    let pageHeight = dom.clientHeight // 客户端高度
    let realScroll = props.initCourseLearnPage * 0.01 * totalHeight - pageHeight
    let scrollTop = realScroll > 0 ? realScroll : 0

    dom.scrollTo({
        top: scrollTop,
        left: 0,
        behavior: 'smooth'
    });

    pageTotalHeight.value = Math.floor(Number(totalHeight)) || 0
    // 用户阅读进度  = ( pageHeight + scrollTop ) / totalHeight
    currentReadHeight.value = Math.floor( Number(pageHeight) + Number(scrollTop) ) || 0
    emit('processChange',{type:'docx',currentProcess:progressPercent.value})
}


const  renderedHandler = (params)=> {
    console.log("渲染完成",params)
    const scrollDom = document.querySelectorAll('.preview_main')
    if(previewType.value == 'docx'){
        scrollDom[0].addEventListener('scroll',HandleScroll,false)
        HandlePageRedirect(scrollDom[0])

    }else if(previewType.value == 'xlsx'){
        console.log('excel表格渲染中')

        // 监听横向滚动
        const excelDomHorizontal = document.querySelector('.vue-office-excel-main  .x-spreadsheet-sheet   .x-spreadsheet-scrollbar.horizontal ')
        excelDomHorizontal?.addEventListener('scroll',(event)=>HandleExcelScroll(event,'horizontal'))

        // 监听纵向滚动
        const excelDomVertical = document.querySelector('.vue-office-excel-main  .x-spreadsheet-sheet   .x-spreadsheet-scrollbar.vertical ')
        excelDomVertical?.addEventListener('scroll',(event)=>HandleExcelScroll(event,'vertical'))


    }

}

const errorHandler = (err) => {
    console.log("渲染失败",err)
}


const HandleImgPreview = ()=>{
    imgVisible.value = true
}

const HandlePageJump = (type)=>{
    switch(type){
        case 'add':
            currentPage.value += 1
            break;
        case 'reduce':
            currentPage.value -= 1
            break
    }
}

const HandleFullScreen = ()=>{
    emit('manulFullScreen')
    isFullScreen.value = !isFullScreen.value
}

watch(()=>props?.fileMessage,(newVal)=>{
    let suffixName = newVal?.name?.split('.').pop()
    if(suffixName){
        previewType.value = suffixName
    }
})

watch(()=>props.initRecord,(newVal)=>{
    // 重置视频的进度
    currentVideoTime.value  = newVal
})


watch(()=>props.updateVideoCurrentTime,(newVal)=>{
    // 这个不加也可以
    // videoPlayer.value.currentTime = newVal
})

</script>



<style lang="scss" scoped>

.pageProcess{
    position: fixed;
    top:40%;
    right: 60px;
}
.nav_group{
    position: absolute;
    width: calc(100% - 40px  - 50px);
    
    display: flex;
    justify-content: space-between;
    bottom:50%;
    left: calc(40px);

    
    .pre_nav,
    .next_nav{
        line-height: 1;
        border-radius: 20px;
        padding:10px;
        background-color: #415058;
        color:white;
    }
    .first,
    .end{
        background-color: #c3c8d0;
    }
}

.page_index{
    position: absolute;
    bottom: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap:5px;
    width: 100%;
}

.watcher_file{
    // border:solid blue 1px;
    width: 100%;
    min-height: 100%;
    // overflow: auto;
}

.preview_item{
    min-height: 100%;
    height: 100%;

    // overflow: auto;
    display: flex;
    flex-direction: column;

    .preview_main{
        position: relative;
        min-height: 100%;
        // overflow: auto;
        border-radius: 8px;

        .full_screen{
            width: 15px;
            position: absolute;
            right:65px;
            bottom:40px;
            background-color: rgba(0,0,0,0.5);
            text-align: right;
        }
        video{
            width: 100%;
            min-height: 100%;
        }
    }
}

</style>


<style lang="scss">
    .preview_main{
        .vue-office-excel-main{
            width: 100%;
            height: 100%;
            .x-spreadsheet{
                height: 100%;
                .x-spreadsheet-sheet{
                    height: calc(100% - 40px);
                }
            }
        }

        .docx-wrapper{
            // width: 100%;
            padding-top:20px;
            padding-bottom: 20px;
            background-color: #e8eaee !important;
            overflow: auto;
            box-sizing: border-box;
            .docx{
                overflow: auto;
                margin-bottom: 0;
                // width: 80% !important;
                // width: auto !important;
            }
        }
    }

</style>