<template>
  <view class="up-upload" :style="[boxStyleComp]">
    <view class="up-upload__image" :style="[itemWH]" @click="handleChooseImage">
      <view class="up-upload__image-icon">
        <slot>
          <xd-font-icon :icon="icon" :size="size" :color="color"></xd-font-icon>
        </slot>
      </view>
    </view>
  </view>
</template>

<script>
  import XdFontIcon from "@/components/XdFontIcon/XdFontIcon";
  import {mapActions} from "vuex";

  export default {
    name: "XdUpload",
    components: {
      XdFontIcon
    },
    props: {
      defaultValue: {
        type: String | null,
        default: null
      },
      width: {
        type: String | Number,
        default: '200'
      },
      height: {
        type: String | Number,
        default: '200'
      },
      /**style**/
      borderWidth: {
        type: String | Number,
        default: ''
      },
      borderColor: {
        type: String,
        default: ''
      },
      borderStyle: {
        type: String,
        default: ''
      },
      borderRadius: {
        type: String | Number,
        default: ''
      },
      backgroundColor: {
        type: String,
        default: '#f8f8f8'
      },
      /**style**/

      /**icon**/
      icon: {
        type: String,
        default: 'iconzhankai_xian'
      },
      color: {
        type: String,
        default: '#aaa'
      },
      size: {
        type: String | Number,
        default: '80'
      },
      /**icon**/

      /**选择相关参数**/
      selectType:{
        type: String,
        default: 'file' , //['image', 'video','file']
      },

      selectCount:{
        type: Number,
        default: 1
      },
      selectExt:{
        type: Array||null,
        default(){
          //file=['txt', 'doc', 'docx', 'pdf'],
          //video = ['mp4']
          //image = ['jpg' ,'jpeg', 'png', 'gif']
          return null;
        }
      },
      selectSize: {
        type:Number,
        default: 5, //5M 1M = 1 / 1024 / 1024 字节;
      },
      selectSource:{
        type: Array,
        default() {
          return ['album','camera']; //相册，相机现场照
        }
      },
      selectSizeType:{
        type: Array,
        default() {
          return ['original', 'compressed']; //原尺寸，压缩尺寸
        }
      },
      /**
       * @description 不设置情况使用视频高宽，设置封面图相关信息 宽（像素） * 高（像素） * 时间（秒）
       */
      selectVideoCoverSize:{
        type:String,
        default: '' //格式：800*600*1，
      },
      /**选择相关参数**/

      ossType:{
        type: String,
        default: 'public' //上传桶名称，其值：public，private  (选填）默认值：publi
      },
    },

    data() {
      return {
        curFiles:[],
        doneFiles:[],
        count:1,//选择资源个数
      }
    },

    computed:{
      itemWH(){
        return {
          width: this.width + 'rpx',
          height: this.height + 'rpx'
        }
      },
      boxStyleComp(){
        return {
          backgroundColor: this.backgroundColor,
          borderWidth:  this.borderWidth,
          borderColor:  this.borderColor,
          borderStyle:  this.borderStyle,
          borderRadius:  this.borderRadius,
          ...this.itemWH,
        }
      },
    },

    watch: {
      defaultValue(value) {
        if (value !== null) {
          this.url = value['url'];
          this.id = value['id'];
        }
      },
    },

    created() {
      //选择类型
      if(['video', 'image', 'file'].includes(this.selectType)) {
        if(this.selectType === 'file' || this.selectType === 'video') this.count = 1;
        else  {
          if(this.selectCount > 0) {
            this.count = this.selectCount;
          }
        }
      }
    },

    methods: {
      ...mapActions(['getUploadParams']),

      /**
       * @description 完成事件
       */
      handleDone(){
        console.log('handleDone',this.doneFiles)
        this.$xdHideLoading();
        this.$emit('on-done', this.$xdUniHelper.cloneDeep(this.doneFiles));
        this.curFiles = [];
        this.doneFiles = [];

      },

      getImageInfo(file, res , path, cb){
        //图片返回参数
        if(file.type.indexOf('image/') !== -1) {
          uni.getImageInfo({
            src: path,
            success:(info)=>{
              cb({
                url: res.url,
                id: res.id,
                width:info.width,
                height:info.height,
                name:file.name,
                type:this.selectType,
                size: file.size
              })
            }
          })
        }
        else if(file.type.indexOf('video/') !== -1) {
          let time = 2;
          let width = file.width;
          let height = file.height;

          //设置封面图相关信息
          if(this.selectVideoCoverSize) {
            let arr = this.selectVideoCoverSize.split('*');
            if(arr.length === 3) {
              time = Number(arr[2]);
              width = Number(arr[0]);
              height = Number(arr[1]);
            }
          }
          let cover = `x-oss-process=video/snapshot,t_${time*1000},f_jpg,w_${width},h_${height},m_fast`
          cb({
            duration: file['duration'],
            name:file.name,
            width:file.width,
            height:file.height,
            type:this.selectType,
            size: file.size,
            url_cover: `${res.url}?${cover}`,
            url: res.url,
            id: res.id,
          })
        }
        else {
          cb({
            url: res.url,
            id: res.id,
            name:file.name,
            type:this.selectType,
            size: file.size
          })
        }
      },

      /***
       * @description 检测文件格式
       */
      checkFile(file,ext) {
        let regName = new RegExp(`^.*\\.(${ext.join('|')})$`);
        let regType = new RegExp(`(${ext.join('|')})$`);
        //检测name中是否有指定文件类型
        if (regName.test(file.name) || !file.type) {
          return true
        }

        //检测type中是否有指定文件类型
        return regType.test(file.type);

      },

      handleDelMapSame(ext){
        let temp = [];
        let filters = ['javascript','plain']
        ext.map(item=>{
          if(!filters.includes(item)) temp.push(item)
        });
        return temp;
      },

      handleMapSame(ext){
        let maps = {js: 'javascript', txt: 'plain'};
        let temp = [];
        ext.map(item=>{
          if(maps[item]) {
            temp.push(maps[item]);
          }
          temp.push(item);
        });
        return temp;
      },

      /**
       * @description 获取上次类型
       * @return {*[]}
       */
      getSelectExt(){
        let ext = []

        //判断不为空
        if(this.selectExt !== null && this.selectExt.length !==0) {
          ext = this.$xdUniHelper.cloneDeep(this.selectExt);
        }

        //图片设置默认值
        if(this.selectType === 'image') {
          if(this.selectExt === null || this.selectExt.length ===0) {
            ext = ['jpg' ,'jpeg', 'png', 'gif'];
          }
        }

        //视频设置默认值
        if(this.selectType === 'video') {
          if(this.selectExt === null || this.selectExt.length ===0) {
            ext = ['mp4'];
          }
        }

        //其他文件设置默认值
        if(this.selectType === 'file'){
          if(this.selectExt === null || this.selectExt.length ===0) {
            ext = ['txt', 'doc', 'docx', 'pdf'];
          }
        }
        ext = this.handleMapSame(ext);
        return ext
      },

      /**
       * @description 判断上传文件格式，尺寸，大小
       * @param files
       * @return {Array} true=> 通过 false=>不通过
       */
      checkType(files=[]){
        let ext = this.getSelectExt();

        let error = [];
        let byte = this.selectSize * 1024 * 1024;
        files.map(item=>{
          let file = {
            name : item.name,
            error: [],
          };
          if(item.size>byte) file.error.push(`文件名：${file.name}<br/>限制文件大小: <span style="color:red">${this.selectSize}</span>MB, <br/>当前文件大小: <span style="color:red">${(item.size/1024/1024).toFixed(2)}</span>MB`);
          if(!this.checkFile(item, ext)) {
            let extOrg = this.handleDelMapSame(ext);
            file.error.push(`文件名：${item.name}<br/>上传文件格式: ${extOrg.join('/').toLocaleUpperCase()} `);
          }
          if(file.error.length > 0) error.push(file)
        });
        return error
      },
      /**
       * @description 上传图片地址
       * @param file
       * @param path
       * @param cb
       */
      getActions(file, path, cb){
        this.getUploadParams({name: file.name, type: this.ossType})
          .then(res=>{
            uni.uploadFile({
              url: res.action,
              filePath: path,
              name: 'file',
              formData: this.$xdUniHelper.cloneDeep(res),
              success: (uploadFileRes) => {
                cb(res)
              },
              error:()=>{
                cb(null)
              }
            });
          })
          .catch();
      },

      //#ifdef MP-WEIXIN
      /**
       * @description 微信小程序设置补全图片信息
       * @param files
       * @param selectType
       * @return {*}
       */
      handleWxFile(files,selectType){
        function getExtInfo(path){
          let name = [];
          //开发工具返回值
          if(path.indexOf('//tmp/') !==-1){
            name = path.split('//tmp/')
          }

          //正式环境返回值
          if(path.indexOf('wxfile://') !== -1) {
            name = path.split('wxfile://');
          }

          let type = name[1].split('.')[1]
          return {
            name : name[1],
            type: `${selectType}/${type}`,
          }
        }

        files.tempFiles = files.tempFiles.map(item=>{
          let info = getExtInfo(item.path);
          item['name'] = item['name'] || info.name;
          item['type'] = item['type'] || info.type;
          return item
        });
        return files;
      },
      //#endif

      /**
       * @description 选择文件动作开始
       * @example https://uniapp.dcloud.net.cn/api/media/image.html#chooseimage
       */
      handleChooseImage() {
        this.curFiles = null;
        let fnName = 'chooseImage';
        if(this.selectType === 'video') fnName = 'chooseVideo';

        //#ifdef H5
        if(this.selectType === 'file') fnName = 'chooseFile';
        //#endif

        //#ifdef MP-WEIXIN
        if(this.selectType === 'file'){
          console.log(this.selectType,this.getSelectExt() )
          wx.chooseMessageFile({
            count:1,
            type: this.selectType,
            extension: this.getSelectExt(),
            success:(files)=>{
              let tempFilePaths = [files['tempFiles'][0].path];
              let tempFiles = files['tempFiles'];
              files = {
                tempFilePaths,
                tempFiles
              };
              this.handleChooseSuccess(files);
            },fail: (error) => {
              throw new Error('选中文件失败')
            },
          });
          return;
        }
        //#endif

        uni[fnName]({
          //张数：H5端选择相册图片时候不起作用，只对选择结果起作用，只能限制单选/多选，并不能限制数量
          count: this.count,
          sizeType: this.selectSizeType,
          sourceType:this.selectSource,
          success: (files) => {
            this.handleChooseSuccess(files);
          },
          fail: (error) => {
            let msg = '选中图片失败';
            if(this.selectType === 'video') msg = '选中视频失败'
            if(this.selectType === 'file') msg = '选中文件失败'
            throw new Error('选中图片失败')
          },
        })
      },

      handleChooseSuccess(files){
        console.log('files',files);
        //视频
        if(this.selectType === 'video') {
          let tempFilePaths = [files['tempFilePath']];
          let tempFiles = [];
          //#ifdef H5
          files['tempFile']['width'] = files['width'];
          files['tempFile']['height'] = files['height'];
          files['tempFile']['duration'] = files['duration'];
          tempFiles.push(files['tempFile']);
          //#endif
          //#ifdef MP-WEIXIN
          tempFiles.push({
            width: files['width'],
            height: files['height'],
            duration: files['duration'],
            size: files['size'],
            path: files['tempFilePath']
          })
          //#endif
          files = {
            tempFilePaths,
            tempFiles
          };
        }

        //#ifdef MP-WEIXIN
        //微信小程序设置补文件信息
        console.log(files);
        files = this.handleWxFile(files, this.selectType)
        //#endif

        let errors = this.checkType(files.tempFiles)
        if(errors.length > 0 ) {
          let error = errors.pop().error
          this.$xdConfirm({
            title: '温馨提示',
            content: error.pop(),
            cancel: false,
            isHtml: true,
            confirmText:'我知道了'
          });
          return
        }
        this.curFiles = files;

        //循环上传
        this.$xdShowLoading({});
        files.tempFiles.map((item,index)=>{
          this.getActions(item, files.tempFilePaths[index],(res)=>{
            this.getImageInfo(item, res, files.tempFilePaths[index],(imageInfo)=>{
              this.doneFiles.push(imageInfo);
              if(this.doneFiles.length === files.tempFiles.length) {
                this.handleDone()
              }
            });
          });
        });
      }

    }

  }
</script>

<style scoped lang="less">
  .up-upload {
    &__image {
      &-icon {
        position: relative;
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
      }

      &-url {
        width: 100%;

        & > image {
          width: 100%;
          height: 100%;
        }
      }
    }
  }
</style>
