<template>
    <div class="file-preview-wrapper flex overlay" v-if="preview">
        <el-scrollbar height="100vh">
            <div class="file-list">
                <section
                    v-for="(item, index) in files"
                    :key="index"
                    class="flex gap v-center pointer"
                    :active="files.indexOf(activeFile) === index"
                    @click="filePreview(item)"
                >
                    <icon :name="getIconName(item.fileName)" :size="24" />
                    <span>{{ item.fileName }}</span>
                </section>
            </div>
        </el-scrollbar>
        <div class="file-content flex center v-center" @click="preview = false">
            <div
                class="img-container flex center"
                v-if="getFileType(activeFile.fileName) === FileType.IMG"
                @wheel="wheel"
            >
                <img
                    :src="`${BASE_PATH}/file/stream/${activeFile.filePath}`"
                    ref="imgRef"
                    @click.stop
                    :style="{
                        transform: `rotate(${rotate}deg) scale(${scale}) translate(${translateX}px, ${translateY}px)`,
                    }"
                    @mousedown="mousedown"
                    @mousemove="mousemove"
                    @mouseup="mouseup"
                    draggable="false"
                />
                <button
                    class="rotate-left-btn pointer"
                    @click.stop.prevent="rotateLeft"
                    size="small"
                    title="左旋转"
                >
                    <icon name="local-icon-rotate-left" :size="28" />
                </button>
                <button
                    class="rotate-right-btn pointer"
                    @click.stop.prevent="rotateRight"
                    size="small"
                    title="右旋转"
                >
                    <icon name="local-icon-rotate-right" :size="28" />
                </button>
            </div>
            <template
                v-else-if="getFileType(activeFile.fileName) === FileType.PDF"
            >
                <iframe
                    :src="`${BASE_PATH}/file/stream/${activeFile.filePath}`"
                    style="height: 100vh; width: 900px"
                ></iframe>
            </template>
            <template
                v-else-if="getFileType(activeFile.fileName) === FileType.MP3"
            >
                <audio controls style="width: 50vw">
                    <source
                        :src="`${BASE_PATH}/file/stream/${activeFile.filePath}`"
                        type="audio/mp3"
                    />
                </audio>
            </template>
            <template
                v-else-if="getFileType(activeFile.fileName) === FileType.MP4"
            >
                <video controls @click.stop style="max-height: 100vh">
                    <source
                        :src="`${BASE_PATH}/file/stream/${activeFile.filePath}`"
                        type="video/mp4"
                    />
                </video>
            </template>
            <template
                v-else-if="getFileType(activeFile.fileName) === FileType.WORD"
            >
                <vue-office-docx
                    :src="`${BASE_PATH}/file/stream/${activeFile.filePath}`"
                    style="height: 100vh; width: 900px"
                    @error="fileRrror = true"
                    v-if="!fileRrror"
                    @click.stop
                />
                <div v-else class="error flex column text-center">
                    <span style="padding: 20px"
                        >文件预览解析错误，如有需要请下载到本地预览</span
                    >
                </div>
            </template>
            <template
                v-else-if="
                    getFileType(activeFile.fileName) === FileType.EXCEL &&
                    activeFile.fileName.toLocaleLowerCase().endsWith('.xlsx')
                "
            >
                <vue-office-excel
                    :src="`${BASE_PATH}/file/stream/${activeFile.filePath}`"
                    style="height: 100vh; width: 60vw"
                    @error="fileRrror = true"
                    v-if="!fileRrror"
                    @click.stop
                />
                <div v-else class="error flex column text-center">
                    <span style="padding: 20px"
                        >文件预览解析错误，如有需要请下载到本地预览</span
                    >
                </div>
            </template>
            <template v-else>
                <div style="background: #fff">
                    <el-result
                        icon="error"
                        title="不支持预览"
                        sub-title="该文件格式暂不支持预览，请下载预览"
                        style="background: #fff; width: 600px; height: 400px"
                        @click.stop
                    >
                        <template #extra>
                            <el-button
                                type="primary"
                                text
                                size="large"
                                @click="download"
                                >下载文件</el-button
                            >
                        </template>
                    </el-result>
                </div>
            </template>
            <div class="file-number" @click.stop>
                <span
                    >{{ files.indexOf(activeFile) + 1 }} /
                    {{ files.length }}</span
                >
            </div>
            <button
                class="left-btn pointer"
                @click.stop.prevent="prev"
                v-if="files.length > 1"
            >
                <icon name="el-icon-ArrowLeftBold" :size="28" />
            </button>
            <button
                class="right-btn pointer"
                @click.stop.prevent="next"
                v-if="files.length > 1"
            >
                <icon name="el-icon-ArrowRightBold" :size="28" />
            </button>
        </div>
        <div class="close-btn"></div>
        <button class="close-btn pointer" @click="preview = false">
            <icon name="el-icon-Close" :size="28" />
        </button>

        <el-button class="download-btn" @click="download" type="primary" plain>
            <template #icon>
                <icon name="el-icon-Download" :size="20" />
            </template>
            下载文件
        </el-button>
    </div>
</template>
<script setup>
import { BASE_PATH } from "@/api/request";
import { FileType } from "@/enums/fileEnums";
import { getFileType, getIconName } from "@/utils/util";
import "@vue-office/docx/lib/index.css";
import "@vue-office/excel/lib/index.css";

import VueOfficeDocx from "@vue-office/docx";
import VueOfficeExcel from "@vue-office/excel";

const props = defineProps({
    files: {
        type: Array,
        default: () => [],
    },
    show: {
        type: Boolean,
        default: false,
    },
});
const emit = defineEmits(["update:show"]);

const preview = ref(false);
const activeFile = ref({});

watch(
    () => props.show,
    (val) => {
        preview.value = val;
        nextTick(() => {
            if (
                val &&
                Object.keys(activeFile.value).length === 0 &&
                props.files.length > 0
            ) {
                activeFile.value = props.files[0];
                rotate.value = 0;
                scale.value = 1;
                translateX.value = 0;
                translateY.value = 0;
                moveFlag = false;
            }
        });
    }
);

watch(preview, (val) => {
    emit("update:show", val);
});

const rotate = ref(0);
const scale = ref(0);
const translateX = ref(0);
const translateY = ref(0);
let moveFlag = false;
let initialX = 0;
let initialY = 0;
const fileRrror = ref(false);

function filePreview(file) {
    preview.value = true;
    activeFile.value = file;
    rotate.value = 0;
    scale.value = 1;
    translateX.value = 0;
    translateY.value = 0;
    moveFlag = false;
}

function download() {
    window.open(`${BASE_PATH}/file/stream/${activeFile.value.filePath}`);
}

function prev() {
    const index = props.files.indexOf(activeFile.value);
    if (index === 0) {
        filePreview(props.files[props.files.length - 1]);
    } else {
        filePreview(props.files[index - 1]);
    }
}
function next() {
    const index = props.files.indexOf(activeFile.value);
    if (index === props.files.length - 1) {
        filePreview(props.files[0]);
    } else {
        filePreview(props.files[index + 1]);
    }
}

function wheel(event) {
    if (event.deltaY > 0 && scale.value > 0.5) {
        scale.value -= 0.1;
    }
    if (event.deltaY < 0) {
        scale.value += 0.1;
    }
}

function mousedown() {
    moveFlag = true;
    initialX = event.clientX;
    initialY = event.clientY;
}
function mousemove(event) {
    if (!moveFlag) {
        return;
    }
    if (rotate.value % 360 === 0) {
        translateX.value += event.clientX - initialX;
        translateY.value += event.clientY - initialY;
    }
    if (rotate.value === 90) {
        translateY.value -= event.clientX - initialX;
        translateX.value += event.clientY - initialY;
    }
    if (rotate.value === 180) {
        translateX.value -= event.clientX - initialX;
        translateY.value -= event.clientY - initialY;
    }
    if (rotate.value === 270) {
        translateY.value += event.clientX - initialX;
        translateX.value -= event.clientY - initialY;
    }
    initialX = event.clientX;
    initialY = event.clientY;
}

function mouseup(event) {
    moveFlag = false;
}

function rotateLeft() {
    if (rotate.value === 360) {
        rotate.value = 0;
    } else {
        rotate.value += 90;
    }
}

function rotateRight() {
    if (rotate.value === 0) {
        rotate.value = 270;
    } else {
        rotate.value -= 90;
    }
}
</script>
<style lang="scss" scoped>
.file-preview-wrapper {
    .file-list {
        width: 15vw;
        height: 100vh;
        padding: 16px 8px;
        background-color: #fff;
        box-sizing: border-box;
        section {
            padding: 8px 16px;
            border: 2px solid transparent;
            background-color: #fff;
            &:hover {
                color: var(--primary-color);
                font-weight: 700;
            }
            &[active="true"] {
                border-color: var(--primary-color);
            }
            span {
                width: calc(100% - 32px);
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
            }
        }
    }
    .file-content {
        width: 86vw;
        position: relative;

        .img-container {
            img {
                max-height: 100vh;
                &:hover {
                    cursor: pointer;
                }
            }
        }
        .error {
            background-color: #fff;
            img {
                width: 500px;
            }
        }
    }
    .close-btn {
        position: absolute;
        top: 12px;
        right: 8px;
        background-color: transparent;
        border: none;
        color: #fff;
        &:hover {
            color: red;
        }
    }
    .rotate-left-btn {
        position: absolute;
        top: 12px;
        right: 118px;
        background-color: transparent;
        border: none;
        color: #fff;
    }
    .rotate-right-btn {
        position: absolute;
        top: 12px;
        right: 68px;
        background-color: transparent;
        border: none;
        color: #fff;
    }
    .left-btn {
        position: absolute;
        top: 50%;
        left: 0;
        transform: translateY(-50%);
        background-color: transparent;
        border: none;
        color: #fff;
    }
    .right-btn {
        position: absolute;
        top: 50%;
        right: 0;
        transform: translateY(-50%);
        background-color: transparent;
        border: none;
        color: #fff;
    }
    .download-btn {
        position: absolute;
        bottom: 20px;
        right: 20px;
    }
    .file-number {
        position: absolute;
        top: 16px;
        left: 18px;
        color: #fff;
    }
}
</style>