      
<template>
  <div class="video-uploader">
    <div class="van-uploader">
        <div class="van-uploader__wrapper">
            <div class="van-uploader__preview" v-for="(item, index) in videos" :key="index" @click="previewing = index">
                <div v-if="item.ref_name || item.is_shifan" class="preview-name van-ellipsis"><van-icon v-if="item.is_shifan" name="star" color="gold" />{{item.ref_name}}</div>
                <div class="van-uploader__preview-image">
                    <video :src="item.resource_url + '#t=0.01'" playsinline webkit-playsinline x5-video-player-type="h5" preload="metadata"></video>
                </div>
                <div v-if="item.ref_desc" class="preview-desc">
                    <div class="van-multi-ellipsis--l3">{{item.ref_desc}}</div>
                </div>
                <div v-if="!readonly" role="button" class="van-uploader__preview-delete van-uploader__preview-delete--shadow" tabindex="0" aria-label="删除">
                    <van-icon name="cross" class="van-uploader__preview-delete-icon" @click="remove(index, $event)"></van-icon>
                </div>
            </div>
            <div class="van-uploader__upload" v-if="(!readonly || addable) && videos?.length < 5">
                <i class="van-badge__wrapper van-icon van-icon-photograph van-uploader__upload-icon"></i>
                <input type="file" class="van-uploader__input" @change="chooseFile" accept="video/*">
            </div>
        </div>
    </div>
    <template v-if="modelValue">
        <video-preview :readonly="readonly && !addable" :can-set-shifan="canSetShifan" :downloadable="downloadable" :resource="modelValue[previewing]" @cancel="previewing = -1" @change="update($event)"></video-preview>
    </template>
  </div>
</template>

<script lang="ts">
import { defineComponent, getCurrentInstance, inject, ref, nextTick } from 'vue';
import { computedAsync } from '@vueuse/core';
import { Icon, Uploader, Button, showFailToast } from 'vant';
import { hwUpYun } from '~/utils/upyun';
import request from "~/utils/request";
import {RefResource, RefTypes, RefResourceTypes, TaskFrom, TaskStatuses, TaskTypes} from '~/types';
import VideoPreview from './video-preview.vue';
import { MediaHelper } from '~/utils';
import useTask, { tsCreateTaskLastError } from "~/store/task";

type VoidFunction = (args?: any) => void;

export default defineComponent({
  name: "multi-video-uploader",
  components: {
    [Icon.name]: Icon,
    [Uploader.name]: Uploader,
    [Button.name]: Button,
    [VideoPreview.name]: VideoPreview
},
  props: {
    readonly: { type: Boolean, default: false },
    addable: { type: Boolean, default: true },
    multiple: { type: Boolean, default: false },
    maxCount: { type: Number, default: 9 },
    simple: { type: Boolean, default: false },
    showButton: { type: Boolean, default: false },
    showUpload: { type: Boolean, default: true },
    downloadable: { type: Boolean, default: false },
    canSetShifan: {type: Boolean, default: false},
    modelValue: Array<RefResource> // 这行如果不在最后一个，在服务器上build会报错，逗号语法问题
  },
  emits: ['update:modelValue', 'update:shifan'],
  setup(props) {

    const instance = getCurrentInstance();
    const files = ref([])
    const previewing = ref(-1);
    const {createTask} = useTask()

    const videos = computedAsync(async () => {
        return Promise.all(props.modelValue?.map(async x => (await MediaHelper.authorize(x))) || []);
    })

    const startProgress = inject<VoidFunction>('startProgress') as VoidFunction;
    const updateProgress = inject<VoidFunction>('updateProgress') as VoidFunction;
    const endProgress = inject<VoidFunction>('endProgress') as VoidFunction;

    const afterRead = async (file: File) => {
      startProgress();
      const { r, d, e } = await hwUpYun.upload(file, 'music-room', percentage => {
        updateProgress(percentage);
      });
      if (r) {
        const res = await request({
          url: '/api/v1/uc/create_hty_resource', method: 'POST',
          data: { filename: file.name, url: d }
        });
        if (res.r) {
          const task_id = await createTask({
            task_type: TaskTypes.VIDEO_COMPRESSION,
            payload: {
              file_url: d,
              resolution_type: 'HD',
              hty_resource_id: res.d,
            },
          });
          if (!task_id) {
            showFailToast(tsCreateTaskLastError.message || '视频压缩任务创建失败');
            endProgress();
            return;
          }
          let resource: RefResource = {
            resource_url: d,
            ref_type: RefTypes.CourseSection,
            resource_type: RefResourceTypes.Video,
            hty_resource_id: res.d,
            tasks: {
              vals: [{
                task_id,
                task_type: TaskTypes.VIDEO_COMPRESSION,
                task_status: TaskStatuses.PENDING,
                task_from: TaskFrom.TaskServer,
                created_at: new Date(),
              }],
            },
          };
          instance?.emit('update:modelValue', [...(props.modelValue || []), resource]);
          await nextTick(() => {
            previewing.value = (props.modelValue?.length || 0) - 1;
          })
        } else {
          showFailToast(res.e);
        }
      } else {
        showFailToast(e);
      }
      endProgress();
    };

    const chooseFile = async (e: Event) => {
        const { files } = e.target as HTMLInputElement;
        if (!files || !files.length) {
            return;
        }
        let file = files[0] as File;
        if (file.size > 100 * 1024 * 1024) {
            showFailToast("文件尺寸不能超过100MB!")
            return;
        }
        if (!file.type.startsWith("video")) {
            showFailToast('请上传视频文件！');
            return;
        }
        await afterRead(files[0])
    }

    const update = async (resource: any) => {
        let data = props.modelValue || [];
        if (resource.is_shifan) {
          data.forEach(x => x.is_shifan = false);
          instance?.emit("update:shifan")
        }
        data[previewing.value] = resource;
        instance?.emit("update:modelValue", data)
        previewing.value = -1;
    }

    const remove = (index: number, e: Event) => {
        e.stopPropagation();
        let data = props.modelValue || [];
        data.splice(index, 1);
        instance?.emit("update:modelValue", data);
    }

    return { chooseFile, remove, videos, files, previewing, update };
  }
});
</script>

<style scoped lang="less">

.video-uploader {

  position: relative;

  .van-uploader__preview {
    margin: 0 var(--van-padding-md) var(--van-padding-md) 0;
    padding: 0 1px;
    width: 144px;
    font-size: 0.24rem;
    box-shadow: 0 0 6px 3px rgba(0,0,0,0.1);
    border-radius: 3px;

    .preview-name {
        text-align: center;
        padding: 0.1rem 0.12rem;
        font-weight: bolder;
        width: 100%;
    }

    .preview-desc {
        padding: 0.1rem 0.12rem;
        width: 100%;
    }
  }

  .van-uploader__preview-image, .van-uploader__upload {
    position: relative;
    width: 142px;
    height: 120px;
    background: var(--van-uploader-upload-background);
  }

  video {
    width: 100%;
    height: 100%;
  }

  .btn-close {
    position: absolute;
    right: 0;
    top: 0;
    width: 0.5rem;
    height: 0.5rem;
    background: rgba(0, 0, 0, 0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1;

    i {
      font-size: 0.28rem;
    }
  }

}

</style>
