<template>
  <div ref="containerRef" :class="`${prefixCls}-container`">
    <a-upload
      :headers="headers"
      :multiple="multiple"
      :action="uploadUrl"
      :fileList="fileList"
      :disabled="disabled"
      :progress="progress"
      v-bind="bindProps"
      @remove="onRemove"
      @change="onFileChange"
      @preview="onFilePreview"
    >
      <template v-if="isImageMode">
        <div v-if="!isMaxCount">
          <Icon icon="ant-design:plus-outlined" />
          <div class="ant-upload-text">{{ text }}</div>
        </div>
      </template>
      <a-button v-else-if="buttonVisible" :disabled="disabled">
        <Icon icon="ant-design:upload-outlined" />
        <span>{{ text }}</span>
      </a-button>
    </a-upload>
    <a-button v-if="fileList.length && isUploading === false && showDownloadBtn" class="ml-2" @click="toBatchDownload" type="primary">下载</a-button>
    <a-upload :fileList="fileList" v-show="uploadProgress"></a-upload>
    <div class="tip-wrap">
      <div v-for="(tip, index) in tipArr" :key="index">{{ tip }}</div>
    </div>
    <template v-if="tipHtml">
      <span class="ml-2" v-if="tipHtml.preContentHtml" v-html="tipHtml.preContentHtml"></span>
      <span style="display:flex;align-items:center;">{{ tipHtml.preContent }}</span>
      <span @click="downloadFile(tipHtml.fileUrl, tipHtml.fileName)" v-html="tipHtml.downloadLinkText" style="display:flex;align-items:center;"></span>
      <span style="display:flex;align-items:center;">{{ tipHtml.nextContent }}</span>
      <a-button
        type="primary"
        @click="mapShow = true"
        v-if="tipHtml.fieldName == '矢量边界' && fileList.length && isUploading === false && showDownloadBtn"
        >预览</a-button
      >
    </template>
    <a-button type="primary" @click="toPreview" v-if="showPreviewBtn && fileList.length > 0" class="ml-2">预览</a-button>
  </div>
  <a-modal v-model:visible="mapShow" title="预览" width="80%">
    <template #footer></template>
    <Mapbj :data="tipHtml.params"  v-if="mapShow"/>
  </a-modal>

  <!-- 边界地图 -->
  <a-modal v-model:visible="previewShow" title="预览" width="50%" :footer="null" class="preview-modal">
    <a-carousel arrows :autoplay="true">
      <template #prevArrow>
        <div class="custom-slick-arrow" style="left: 10px; z-index: 1">
          <left-circle-outlined />
        </div>
      </template>
      <template #nextArrow>
        <div class="custom-slick-arrow" style="right: 10px">
          <right-circle-outlined />
        </div>
      </template>
      <div v-for="item in previewData" :key="item">
        <img :src="item" style="width:100%"/>
      </div>
    </a-carousel>
  </a-modal>
  <!-- 图片预览 -->
</template>

<script lang="ts" setup>
  import { ref, reactive, computed, watch, nextTick, createApp, unref } from 'vue';
  import { Icon } from '/@/components/Icon';
  import { getToken } from '/@/utils/auth';
  import { uploadUrl, downloadFile, getFileblob } from '/@/api/common/api';
  import { propTypes } from '/@/utils/propTypes';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { createImgPreview } from '/@/components/Preview/index';
  import { useAttrs } from '/@/hooks/core/useAttrs';
  import { useDesign } from '/@/hooks/web/useDesign';
  import { UploadTypeEnum } from './upload.data';
  import UploadItemActions from './components/UploadItemActions.vue';
  import Mapbj from '@/components/customComponent/mapqybj.vue';
  import type { UploadProps } from 'ant-design-vue';
  import { getAppEnvConfig } from '/@/utils/env';

  const { createMessage, createConfirm } = useMessage();
  const { prefixCls } = useDesign('j-upload');
  const attrs = useAttrs();
  const emit = defineEmits(['change', 'update:value']);
  const mapShow = ref(false);
  const previewShow = ref(false);
  const previewUrl = ref('');
  const progress: UploadProps['progress'] = {
    strokeColor: {
      '0%': '#108ee9',
      '100%': '#87d068',
    },
    strokeWidth: 3,
    format: percent => `${parseFloat(percent.toFixed(2))}%`,
    class: 'test',
  };
  const uploadProgress = ref(false);
  let {VITE_GLOB_ONLINE_VIEW_URL} = getAppEnvConfig();

  const props = defineProps({
    value: propTypes.oneOfType([propTypes.string, propTypes.array]),
    // 提示语
    tipArr: propTypes.object.def([]),
    tipHtml: propTypes.object.def({}),
    text: propTypes.string.def('上传'),
    fileType: propTypes.string.def(UploadTypeEnum.all),
    /*这个属性用于控制文件上传的业务路径*/
    bizPath: propTypes.string.def('temp'),
    /**
     * 是否返回url，
     * true：仅返回url
     * false：返回fileName filePath fileSize
     */
    returnUrl: propTypes.bool.def(true),
    // 最大上传数量
    maxCount: propTypes.number.def(0),
    fileName: propTypes.string.def('1'),
    buttonVisible: propTypes.bool.def(true),
    multiple: propTypes.bool.def(true),
    // 是否显示左右移动按钮
    mover: propTypes.bool.def(true),
    // 是否显示下载按钮
    download: propTypes.bool.def(true),
    // 是否显示下载按钮
    showDownloadBtn: propTypes.bool.def(true),
    // 删除时是否显示确认框
    removeConfirm: propTypes.bool.def(false),
    beforeUpload: propTypes.func,
    disabled: propTypes.bool.def(false),
    // 替换前一个文件，用于超出最大数量依然允许上传
    replaceLastOne: propTypes.bool.def(false),
    // 是否显示上传的文件列表
    showPreviewBtn: propTypes.bool.def(false),
  });

  const previewData = ref<any>([]);
  const toPreview = () => {
    previewShow.value = true;
    if (!fileList.value || fileList.value.length == 0) {
      return;
    }
    let arr = props.value?.split(',');
    previewData.value = [];
    arr.forEach(async (item) => {
      if (item && ['jpg','png','PNG','JPG'].includes(item.split(".")[1])) {
        getFileblob('/sys/common/static'+item,{}).then(data =>{
          if (!data || data.size === 0) {
            createMessage.warning('文件下载失败');
            return;
          }
          if (typeof window.navigator?.msSaveBlob !== 'undefined') {
            window.navigator?.msSaveBlob(new Blob([data]), fileName);
          } else {
            let url = window.URL.createObjectURL(new Blob([data]));
            previewData.value.push(url)
          }
        })
      } else {
        previewData.value.push(fileList.value[0].url);
      }
    });

  };

   const geturl = async (item) => {
    let filePath = '';
    if (item && ['jpg','png','PNG','JPG'].includes(item.split(".")[1])) {
      await getFileblob('/sys/common/static/'+item,{}).then(data =>{
        if (!data || data.size === 0) {
          createMessage.warning('文件下载失败');
          return;
        }
        if (typeof window.navigator?.msSaveBlob !== 'undefined') {
          window.navigator?.msSaveBlob(new Blob([data]), fileName);
        } else {
          let url = window.URL.createObjectURL(new Blob([data]));
          filePath = url
        }
      })
    } else {
      filePath = item;
    }
    return filePath;
  }



  const isUploading = ref<boolean>(false);
  const headers = reactive({
    'X-Access-Token': getToken(),
  });
  const fileList = ref<any[]>([]);
  const uploadGoOn = ref<boolean>(true);
  // refs
  const containerRef = ref();
  // 是否达到了最大上传数量
  const isMaxCount = computed(() => props.maxCount > 0 && (fileList.value.length >= props.maxCount));
  // 当前是否是上传图片模式
  const isImageMode = computed(() => props.fileType === UploadTypeEnum.image);
  // 上传按钮是否禁用
  // const buttonDisabled = computed(() => {
  //   if (props.disabled === true) {
  //     return true;
  //   }
  //   if (isMaxCount.value === true) {
  //     console.log(1111, props.replaceLastOne);
  //     if (props.replaceLastOne === true) {
  //       return false;
  //     } else {
  //       return true;
  //     }
  //   }
  //   return false;
  // });
  // 合并 props 和 attrs
  const bindProps = computed(() => {
    //update-begin-author:liusq date:20220411 for: [issue/455]上传组件传入accept限制上传文件类型无效
    const bind: any = Object.assign({}, props, unref(attrs), {disabled: (props.disabled || !props.buttonVisible)});
    //update-end-author:liusq date:20220411 for: [issue/455]上传组件传入accept限制上传文件类型无效

    bind.name = 'file';
    bind.listType = isImageMode.value ? 'picture-card' : 'text';
    bind.class = [bind.class, { 'upload-disabled': ( props.disabled || !props.buttonVisible) }];
    bind.data = { biz: props.bizPath, ...bind.data };
    //update-begin-author:taoyan date:20220407 for: 自定义beforeUpload return false，并不能中断上传过程
    if (!bind.beforeUpload) {
      bind.beforeUpload = onBeforeUpload;
    }
    //update-end-author:taoyan date:20220407 for: 自定义beforeUpload return false，并不能中断上传过程
    // 如果当前是图片上传模式，就只能上传图片
    if (isImageMode.value && !bind.accept) {
      bind.accept = 'image/*';
    }
    return bind;
  });

  watch(
    () => props.value,
    (val) => {
      if (Array.isArray(val)) {
        if (props.returnUrl) {
          parsePathsValue(val.join(','));
        } else {
          parseArrayValue(val);
        }
      } else {
        //update-begin---author:liusq ---date:20230914  for：[issues/5327]Upload组件returnUrl为false时上传的字段值返回了一个'[object Object]' ------------
        if (props.returnUrl) {
          parsePathsValue(val);
        } else {
          val && parseArrayValue(JSON.parse(val));
        }
        //update-end---author:liusq ---date:20230914  for：[issues/5327]Upload组件returnUrl为false时上传的字段值返回了一个'[object Object]' ------------
      }
    },
    { immediate: true }
  );

  watch(fileList, () => nextTick(() => addActionsListener()), { immediate: true });

  const antUploadItemCls = 'ant-upload-list-item';

  // Listener
  function addActionsListener() {
   
    if (!isImageMode.value) {
      return;
    }
    const uploadItems = containerRef.value ? containerRef.value.getElementsByClassName(antUploadItemCls) : null;
    if (!uploadItems || uploadItems.length === 0) {
      return;
    }
    for (const uploadItem of uploadItems) {
      let hasActions = uploadItem.getAttribute('data-has-actions') === 'true';
      if (!hasActions) {
        uploadItem.addEventListener('mouseover', onAddActionsButton);
      }
    }
  }

  // 添加可左右移动的按钮
  function onAddActionsButton(event) {
    const getUploadItem = () => {
      for (const path of event.path) {
        if (path.classList.contains(antUploadItemCls)) {
          return path;
        } else if (path.classList.contains(`${prefixCls}-container`)) {
          return null;
        }
      }
      return null;
    };
    const uploadItem = getUploadItem();
    if (!uploadItem) {
      return;
    }
    const actions = uploadItem.getElementsByClassName('ant-upload-list-item-actions');
    if (!actions || actions.length === 0) {
      return;
    }
    // 添加操作按钮
    const div = document.createElement('div');
    div.className = 'upload-actions-container';
    createApp(UploadItemActions, {
      element: uploadItem,
      fileList: fileList,
      mover: props.mover,
      download: props.download,
      emitValue: emitValue,
    }).mount(div);
    actions[0].appendChild(div);
    uploadItem.setAttribute('data-has-actions', 'true');
    uploadItem.removeEventListener('mouseover', onAddActionsButton);
  }

  // 解析数据库存储的逗号分割
  function parsePathsValue(paths) {
    if (!paths || paths.length == 0) {
      fileList.value = [];
      return;
    }
    let list: any[] = [];
    for (const item of paths.split(',')) {
      // 是上传一个 保存一个
      list = [];
      list.push({
        uid: uidGenerator(),
        name: getFileName(item),
        status: 'done',
        url: item,
        response: { status: 'history', message: item },
      });
    }
    fileList.value = list;
  }

  // 解析数组值
  function parseArrayValue(array) {
    if (!array || array.length == 0) {
      fileList.value = [];
      return;
    }
    let list: any[] = [];
    for (const item of array) {
      // 是上传一个 保存一个
      list = [];
      list.push({
        uid: uidGenerator(),
        name: item.fileName,
        url: item.filePath,
        status: 'done',
        response: { status: 'history', message: item.filePath },
      });
    }
    fileList.value = list;
  }

  // 文件上传之前的操作
  function onBeforeUpload(file) {
    isUploading.value = true;
    uploadGoOn.value = true;
    if (isImageMode.value) {
      if (file.type.indexOf('image') < 0) {
        createMessage.warning('请上传图片');
        uploadGoOn.value = false;
        return false;
      }
    }
    // 扩展 beforeUpload 验证
    if (typeof props.beforeUpload === 'function') {
      return props.beforeUpload(file);
    }
    return true;
  }

  // 删除处理事件
  function onRemove() {
    if (props.removeConfirm) {
      return new Promise((resolve) => {
        createConfirm({
          title: '删除',
          content: `确定要删除这${isImageMode.value ? '张图片' : '个文件'}吗？`,
          iconType: 'warning',
          onOk: () => resolve(true),
          onCancel: () => resolve(false),
        });
      });
    }
    return true;
  }

  // upload组件change事件
  function onFileChange(info) {
    if (!info.file.status) {
      return
    }
    // 检查文件的状态，如果上传已完成或者出现错误，设置 isUploading 为 false
    if (info.file.status === 'done' || info.file.status === 'error') {
      isUploading.value = false;
      uploadProgress.value = false;
    } else {
      if (!uploadProgress.value) {
        uploadProgress.value = true;
      }
    }
    if (!info.file.status && uploadGoOn.value === false) {
      info.fileList.pop();
    }
    let fileListTemp = info.fileList;
    // 限制最大上传数
    if (props.maxCount > 0) {
      let count = fileListTemp.length;
      if (count >= props.maxCount) {
        let diffNum = props.maxCount - fileListTemp.length;
        if (diffNum >= 0) {
          fileListTemp = fileListTemp.slice(-props.maxCount);
        } else {
          return;
        }
      }
    }
    if (info.file.status === 'done') {
      let successFileList = [];
      if (info.file.response.success) {
        successFileList = fileListTemp.map((file) => {
          if (file.response) {
            file.url = file.response.message;
          }
          return file;
        });
      } else {
        successFileList = successFileList.slice(0,successFileList.length-1)
        successFileList = fileListTemp.filter((item) => {
          return item.uid != info.file.uid;
        });
        createMessage.error(`${info.file.response.message}`);
      }
      fileListTemp = successFileList;
    } else if (info.file.status === 'error') {
      createMessage.error(`${info.file.response.message}`);
    }
    fileList.value = fileListTemp;
    if (info.file.status === 'done' || info.file.status === 'removed') {
      //returnUrl为true时仅返回文件路径
      if (props.returnUrl) {
        handlePathChange(info.file.response);
      } else {
        //returnUrl为false时返回文件名称、文件路径及文件大小
        let newFileList: any[] = [];
        for (const item of fileListTemp) {
          if (item.status === 'done') {
            let fileJson = {
              fileName: item.name,
              filePath: item.response.message,
              fileSize: item.size,
            };
            newFileList.push(fileJson);
          } else {
            return;
          }
        }
        emitValue(newFileList);
      }
    }
  }

  function handlePathChange(response) {
    if (!response.result) {
      createMessage.error(`${response.message}`);
      return;
    }
    let uploadFiles = fileList.value;
    let path = '';
    if (!uploadFiles || uploadFiles.length == 0) {
      path = '';
    }
    let pathList: string[] = [];
    for (const item of uploadFiles) {
      // 是上传一个 保存一个
      pathList = [];
      if (item.status === 'done') {
        pathList.push(item.response.message);
      } else {
        return;
      }
    }
    if (pathList.length > 0) {
      path = pathList.join(',');
    }
    emitValue(path);
  }

  // 预览文件、图片
  function onFilePreview(file) {
    if (isImageMode.value) {
      createImgPreview({ imageList: [file.url], maskClosable: true });
    } else {
      window.open(file.url);
    }
  }

  function emitValue(value) {
    emit('change', value);
    emit('update:value', value);
  }

  function uidGenerator() {
    return '-' + parseInt(Math.random() * 10000 + 1, 10);
  }

  function getFileName(path) {
    if (path.lastIndexOf('\\') >= 0) {
      let reg = new RegExp('\\\\', 'g');
      path = path.replace(reg, '/');
    }
    return path.substring(path.lastIndexOf('/') + 1);
  }

  function toBatchDownload() {
    console.log(fileList.value, 'fileList.value');
    fileList.value.forEach((item) => {
      let fileExtension = item.url.split('.').pop();
      console.log('下载', item.url, props.fileName + '.' + fileExtension);
      downloadFile('/sys/common/static' + item.url, `${props.fileName}.${fileExtension}`);
    });
  }

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

<style lang="less">
.ant-upload-list-item-card-actions {
  display: none!important;
}
  .jeecg-j-upload-container {
    display: flex;
  }
  //noinspection LessUnresolvedVariable
  @prefix-cls: ~'@{namespace}-j-upload';

  .@{prefix-cls} {
    &-container {
      position: relative;

      .upload-disabled {
        .ant-upload-list-item {
          .anticon-close {
            display: none;
          }

          .anticon-delete {
            display: none;
          }
        }

        /* update-begin-author:taoyan date:2022-5-24 for:VUEN-1093详情界面 图片下载按钮显示不全*/
        .upload-download-handler {
          right: 6px !important;
        }

        /* update-end-author:taoyan date:2022-5-24 for:VUEN-1093详情界面 图片下载按钮显示不全*/
      }

      .ant-upload-list-item {
        .upload-actions-container {
          position: absolute;
          top: -31px;
          left: -18px;
          z-index: 11;
          width: 84px;
          height: 84px;
          line-height: 28px;
          text-align: center;
          pointer-events: none;

          a {
            opacity: 0.9;
            margin: 0 5px;
            cursor: pointer;
            transition: opacity 0.3s;

            .anticon {
              color: #fff;
              font-size: 16px;
            }

            &:hover {
              opacity: 1;
            }
          }

          .upload-mover-handler,
          .upload-download-handler {
            position: absolute;
            pointer-events: auto;
          }

          .upload-mover-handler {
            width: 100%;
            bottom: 0;
          }

          .upload-download-handler {
            top: -4px;
            right: -4px;
          }
        }
      }
    }
  }

  .tip-wrap {
    display: inline-flex;
    color: #bfbfbf;
    div {
      margin-left: 10px;
      &:first-child {
        margin-left: 0;
      }
    }
  }
  .preview-modal .ant-modal-body {
    text-align: center;
    padding: 15px;
  }
</style>
