<template>
  <div
    class="material-list"
    :class="{
      dark: isDarkTheme,
    }"
  >
    <crumbs
      class="crumbs"
      v-if="!searchKey"
      :isDarkTheme="isDarkTheme"
      :list="folderPath"
      :rootName="$i18n.t(`gather.${materialTypeAlias}`)"
      @click-path="onClickPath"
    />
    <div v-if="searchKey" class="crumbs">{{$i18n.t(`gather.${materialTypeAlias}`)}}</div>

    <div class="table">
      <!-- <div class="table-head-row">
        <span
          class="table-head"
          :style="{
            width: '50px',
          }"
        >
          1
        </span>
        <span
          class="table-head"
          v-for="(item, idx) in tableHeaders"
          :key="idx"
          :style="{
            width: columnWidthList[idx],
          }"
        >
          {{ item.name && $i18n.t(`zh_key.${item.name}`) }}
        </span>
      </div> -->
      <div
        v-show="listLocalLength !== 0 || hasMoreData"
        class="table-body"
        v-infinite-scroll="requestMoreData"
        :infinite-scroll-disabled="!hasMoreData || isRequestingMoreData"
      >
        <!-- vuex中的上传中数据 -->
        <div v-for="(item, i) in uploadStatusList" :key="item.uid">
          <div
            class="table-body-row"
            v-if="item.parentFolderId === currentFolderId && !searchKey"
            @click="onClickRow"
          >
            <!-- 如果已经上传成功 -->
            <template v-if="item.status === 'SUCCESS'">
              <span
                class="table-data"
              >
                <RadioOrCheckbox
                  class="checkbox"
                  :isLightTheme="!isDarkTheme"
                  :isMultiSelection="isMultiSelection"
                  :isCheckedInitial="select.some(i => i.id === item.successInfo.id)"
                  @change="v => selectItem(item.successInfo, v)"
                />
              </span>
              <span
                class="table-data"
                :style="{
                  width: columnWidthList[idx] || '',
                }"
                v-for="(tableItemStructure, idx) in tableHeaders"
                :key="idx"
              >
                <div v-if="tableItemStructure.type" class="list-img">
                  <slot name="materialUploadSuccessIcon" :uploadInfo="item" :tableItemStructure="tableItemStructure">
                  </slot>
                </div>
                <span
                  v-else-if="tableItemStructure.key === 'name'"
                  class="name"
                >
                  <div
                    class="name-inner ellipsis"
                    v-title="item.successInfo[tableItemStructure.key]"
                  >
                    {{ item.successInfo[tableItemStructure.key] }}
                  </div>
                </span>
                <span
                  v-else
                  class="ellipsis"
                >
                  {{item.successInfo[tableItemStructure.key]}}
                </span>
              </span>
            </template>
            <!-- 如果还在上传或切图处理中 -->
            <template v-else-if="item.status === 'LOADING'">
              <span
                class="table-data"
              >
                <RadioOrCheckbox
                  class="checkbox"
                  :isLightTheme="!isDarkTheme"
                  :isMultiSelection="isMultiSelection"
                  :isDisabled="true"
                />
              </span>
              <span
                class="table-data"
                :style="{
                  width: columnWidthList[idx],
                }"
                v-for="(tableItemStructure, idx) in tableHeaders"
                :key="idx"
              >
                <div v-if="tableItemStructure.type" class="list-img">
                  <slot name="materialUploadingIcon">
                  </slot>
                </div>
                <span
                  v-if="tableItemStructure.key === 'name'"
                  class="name upload-status-wrap"
                >
                  <div
                    class="name-inner ellipsis"
                    v-title="item.title"
                  >
                    {{ item.title }}
                  </div>
                  <div v-if="item.ifKnowProgress" class="upload-status">
                    {{$i18n.t(`gather.upload_material`)}} {{ Math.round(item.progress * 100)}}%
                  </div>
                  <div v-else class="upload-status">
                    {{ item.statusText }}
                  </div>
                </span>
                <span v-else></span>
              </span>
            </template>
            <!-- 如果上传失败了 -->
            <template v-else-if="item.status === 'FAIL'">
              <span
                class="table-data"
              >
                <RadioOrCheckbox
                  class="checkbox"
                  :isLightTheme="!isDarkTheme"
                  :isMultiSelection="isMultiSelection"
                  :isDisabled="true"
                />
              </span>
              <span
                class="table-data"
                :style="{
                  width: columnWidthList[idx],
                }"
                v-for="(tableItemStructure, idx) in tableHeaders"
                :key="idx"
              >
                <div v-if="tableItemStructure.type" class="list-img">
                  <slot name="materialUploadFailIcon">
                  </slot>
                </div>
                <span
                  v-if="tableItemStructure.key === 'name'"
                  class="name upload-status-wrap"
                >
                  <div
                    class="name-inner ellipsis"
                    v-title="item.title"
                  >
                    {{ item.title }}
                  </div>
                  <div class="upload-status">
                    {{ item.statusText }}
                  </div>
                </span>
                <span v-if="tableItemStructure.key === 'fileSize'">{{ $i18n.t(`tips_code.FAILURE_3025`) }}</span>
                <span v-if="tableItemStructure.key !== 'name' && tableItemStructure.key !== 'fileSize'"></span>
              </span>
            </template>
          </div>
        </div>
        <!-- 本组件内的列表数据 -->
        <div
          class="table-body-row"
          v-for="(item, i) in list"
          :key="i"
          @click="(e) => {
            if (item.type === 'dir') {
              onClickFolder(item)
            } else {
              onClickRow(e)
            }
          }"
        >
          <span
            class="table-data"
          >
            <RadioOrCheckbox
              class="checkbox"
              :isLightTheme="!isDarkTheme"
              :isDisabled="item.type === 'dir'"
              :isMultiSelection="isMultiSelection"
              :isCheckedInitial="select.some(i => i.id === item.id)"
              @change="v => selectItem(item, v)"
            />
          </span>
          <span
            class="table-data"
            v-for="(tableItemStructure, idx) in tableHeaders"
            :style="{
              width: columnWidthList[idx],
            }"
            :key="idx"
          >
            <div
              v-if="tableItemStructure.type"
              class="list-img"
            >
              <img
                v-if="item.type === 'dir'"
                class="folderIcon"
                src="@/assets/images/icons/folder-blue.png"
                alt=""
              />
              <slot v-else name="materialIcon" :materialInfo="item" :tableItemStructure="tableItemStructure">
              </slot>
            </div>
            <span
              v-else-if="tableItemStructure.key === 'name'"
              class="name"
              :class="{
                searchRes: latestUsedSearchKey,
              }"
            >
              <div
                class="name-inner ellipsis"
                v-title="item[tableItemStructure.key]"
              >
                {{ item[tableItemStructure.key] }}
              </div>
              <div
                v-if="latestUsedSearchKey"
                class="parent-info"
              >
                {{$i18n.t('gather.dir')}} <span class="parent-name" @click.stop="onClickParentFolder(item)">{{item.dirId === 1 ? $i18n.t('gather.root_dir') : item.dirName}}</span>
              </div>
            </span>
            <span
              v-else
              class="ellipsis"
            >
              {{ item[tableItemStructure.key] }}
            </span>
          </span>
        </div>
        <LoadingPoints
          v-show="isRequestingMoreData"
          :isDarkTheme="isDarkTheme"
        />
        <div class="no-more-data" v-show="!hasMoreData">
          - {{$i18n.t('gather.no_more_data')}} -
        </div>
      </div>
      <!-- 无数据时的提示 -->
      <div v-show="!(listLocalLength !== 0 || hasMoreData)" class="no-data">
        <div v-if="latestUsedSearchKey">
          <img :src="require(`@/assets/images/default/empty_search_${isDarkTheme ? 'dark' : 'bright'}.png`)" alt="">
          <span>{{ $i18n.t("gather.no_serch_result") }}</span>
        </div>
        <div v-if="!latestUsedSearchKey">
          <img :src="require(`@/assets/images/default/empty_${isDarkTheme ? 'dark' : 'bright'}.png`)" alt="">
          <span>{{ $i18n.t("gather.no_material_result") }}</span>
          <a v-if="!canUpload" href="/#/">
            <button class="ui-button">{{ $i18n.t("gather.how_to_shoot") }}</button>
          </a>
        </div>
      </div>
    </div>

    <div class="btns">
      <button v-if="canUpload && !searchKey" class="ui-button upload-btn" @click="onClickUpload">
        <span>{{ $i18n.t("gather.upload_material") }}</span>
        <i
          class="iconfont icon-material_prompt tool-tip-for-editor"
          v-tooltip="fileInputBtnTip"
        />
        <FileInput
          ref="file-input"
          :failString="fileInputFailString"
          :limitFailStr="fileInputLimitFailStr"
          :acceptType="fileInputAcceptType"
          :mediaType="fileInputMediaType"
          :limit="fileInputLimit"
          @file-change="onFileInputChange"
        />
      </button>
    </div>
  </div>
</template>

<script>
import {
  getMaterialList,
  getSceneList,
  searchInAllScenes,
  uploadMaterial,
  checkUserSize,
} from "@/api";

import { changeByteUnit } from "@/utils/file";
import { debounce, capitalize } from "@/utils/other.js"

import config from "@/config";

import FileInput from "@/components/shared/uploads/UploadMultiple.vue";
import RadioOrCheckbox from "@/components/shared/RadioOrCheckbox.vue";
import LoadingPoints from "@/components/shared/LoadingPoints.vue";

import folderMixin from "./materialSelectorFolderMixin.js";

export default {
  components: {
    FileInput,
    RadioOrCheckbox,
    LoadingPoints,
  },
  mixins: [
    folderMixin,
  ],
  props: {
    isDarkTheme: {
      type: Boolean,
      default: true,
    },
    currentMaterialType: {
      type: String,
      required: true,
    },
    materialType: {
      type: String,
      required: true,
    },
    materialItemCustomProcess: {
      type: Function,
      default: (item) => {
        return
      }
    },
    tableHeaderKeyList: {
      type: Array,
      default: () => {
        return []
      }
    },
    columnWidthList: {
      type: Array,
      default: () => {
        return []
      },
    },
    isMultiSelection: {
      type: Boolean,
      default: false,
    },
    select: {
      type: Array,
      required: true,
    },
    
    searchKey: {
      type: String,
      default: '',
    },
    canUpload: {
      type: Boolean,
      defaut: false,
    },
    fileInputBtnTip: {
      type: String,
    },
    fileInputCustomCheck: {
      type: Function,
      default: async () => {
        return true
      }
    },
    fileUploadLongPollingCb: {
      type: Function || null,
      default: null
    },
    fileUploadLongPollingStatusText: {
      type: String,
      defaut: ''
    },
    fileInputFailString: {
      type: String,
    },
    fileInputLimitFailStr: {
      type: String,
    },
    fileInputAcceptType: {
      type: String,
    },
    fileInputMediaType: {
      type: String,
    },
    fileInputLimit: {
      type: Number,
    },
  },
  data() {
    return {
      list: [],

      latestUsedSearchKey: '',

      isRequestingMoreData: false,
      hasMoreData: true,

      longPollingIntervalId: null,
    }
  },
  computed: {
    materialTypeAlias() {
      if (this.materialType === '3D') {
        return 'scene'
      } else {
        return this.materialType
      }
    },
    tableHeaders() {
      /*
      [
        {
          en: "素材", // 暂时没用到
          key: "icon",
          name: "素材",
          type: "image",
          width: 150, // 暂时没用到
        },
        {
          en: "名称",
          key: "name",
          name: "名称",
          width: 240,
        },
        {
          en: "大小",
          key: "fileSize",
          name: "大小",
          width: 80,
        }
      ]
       */
      return this.$MAPTABLEHEADER[this.materialTypeAlias].filter(item => {
        return this.tableHeaderKeyList.includes(item.key)
      })
    },
    uploadStatusList() {
      if (this.canUpload) {
        return this.$store.state[`uploadStatusList${capitalize(this.materialType)}`]
      } else {
        return []
      }
    },
    listRealLength() {
      return this.list.length + this.uploadStatusList.filter((item) => {
        return item.status === 'SUCCESS'
      }).length
    },
    listLocalLength() {
      return this.list.length + this.uploadStatusList.length
    },
    needLongPolling() {
      return this.uploadStatusList.some((item) => {
        return item.status === 'LOADING' && item.ifKnowProgress === false
      })
    },
  },
  watch: {
    searchKey: {
      handler: function () {
        if (this.currentMaterialType === this.materialType) {
          this.refreshMaterialList()
        }
      },
      immediate: false,
    },
    currentMaterialType: {
      handler: function (newVal) {
        if (newVal === this.materialType && this.list.length === 0) {
          this.refreshMaterialList()
        }
      },
      immediate: false,
    },
    needLongPolling: {
      handler: function (newVal) {
        if (!newVal) {
          clearInterval(this.longPollingIntervalId)
          this.longPollingIntervalId = null
        } else {
          clearInterval(this.longPollingIntervalId)
          this.longPollingIntervalId = null
          this.longPollingIntervalId = setInterval(() => {
            this.fileUploadLongPollingCb(this.uploadStatusList);
          }, 3000);
        }
      },
      immediate: true,
    },
  },
  methods: {
    selectItem(item, v) {
      item.materialType = this.materialType // 三维场景数据没有type字段来表明自己是三维场景。所以统一加一个字段。
      if (this.isMultiSelection) {
        if (v) {
          this.select.push(item)
        } else {
          const toDeleteIdx = this.select.findIndex((eachSelect) => {
            return eachSelect.id === item.id
          })
          if (toDeleteIdx >= 0) {
            this.select.splice(toDeleteIdx, 1)
          }
        }
      } else {
        this.select.splice(0, this.select.length)
        if (v) {
          this.select.push(item)
        }
      }
    },
    requestMoreData() {
      this.isRequestingMoreData = true
      const latestUsedSearchKey = this.searchKey

      let getListFn = null
      let params = null
      if (this.materialType === '3D') {
        if (!this.searchKey) {
          getListFn = getSceneList
          params = {
            pathLevel2Id: this.folderPath[1]?.id,
            folderId: this.currentFolderId,
            pageNum: Math.floor(this.list.length / config.PAGE_SIZE) + 1,
            pageSize: config.PAGE_SIZE,
            searchKey: this.searchKey,
          }
        } else {
          getListFn = searchInAllScenes
          params = {
            searchKey: this.searchKey
          }
        }
      } else {
        getListFn = getMaterialList
        params = {
          dirId: this.currentFolderId,
          pageNum: Math.floor(this.listRealLength / config.PAGE_SIZE) + 1,
          pageSize: config.PAGE_SIZE,
          searchKey: this.searchKey,
          type: this.materialType,
        }
      }
      getListFn(params, (data) => {
        const newData = data.data.list.map((i) => {
          if (i.fileSize) {
            i.fileSize = changeByteUnit(Number(i.fileSize));
          } else {
            i.fileSize = ''
          }
          this.materialItemCustomProcess(i)
          return i;
        });
        this.list = this.list.concat(newData)
        if (this.listRealLength === data.data.total) {
          this.hasMoreData = false
        }
        this.isRequestingMoreData = false
        this.latestUsedSearchKey = latestUsedSearchKey
      }, () => {
        this.isRequestingMoreData = false
        this.latestUsedSearchKey = latestUsedSearchKey
      });
    },
    refreshMaterialList: debounce(function (type) {
      this.isRequestingMoreData = false
      this.hasMoreData = true
      this.list = []
      if (this.canUpload) {
        let filterResult = this.uploadStatusList.filter((item) => {
          return item.status === 'LOADING'
        })
        const capitalizedMaterialType = capitalize(this.materialType)
        this.$store.commit(`setUploadStatusList${capitalizedMaterialType}`, filterResult)
      }
      this.requestMoreData()
    }, 500, false),
    onFileInputChange(e) {
      e.files.forEach(async (eachFile, i) => {
        if (
          this.fileInputAcceptType.indexOf(eachFile.type) <= -1
        ) {
          console.log('格式不对！');
          setTimeout(() => {
            this.$msg({
              message: `“${eachFile.name}”${this.fileInputFailString}`,
              type: "warning",
            });
          }, i * 100);
          return;
        }

        if (eachFile.name.substring(0, eachFile.name.lastIndexOf(".")).length > 50) {
          setTimeout(() => {
            this.$msg({
              message: `“${eachFile.name}”${this.$i18n.t(`gather.too_long_word`)}`,
              type: "warning",
            });
          }, i * 100);
          return;
        }

        const customCheckRes = await this.fileInputCustomCheck(eachFile, i)
        if (!customCheckRes) {
          return
        }

        let itemInUploadList = {
          title: eachFile.name,
          ifKnowProgress: true,
          progress: 0,
          status: 'LOADING',
          statusText: this.$i18n.t(`gather.uploading_material`),
          uid: `u_${this.$randomWord(true, 8, 8)}`,
          abortHandler: null,
          backendId: '', // 只用于全景图上传
          parentFolderId: this.currentFolderId,
        };

        itemInUploadList.abortHandler = uploadMaterial(
          {
            dirId: this.currentFolderId,
            file: eachFile,
            tempId: itemInUploadList.uid,
            type: this.materialType,
          },
          (response) => { // 上传成功
            if (response.code !== 0) {
              console.error('上传接口响应异常：', response);
              return
            }
            console.log('上传成功');
            if (this.fileUploadLongPollingCb) {
              itemInUploadList.statusText = this.fileUploadLongPollingStatusText
              itemInUploadList.ifKnowProgress = false
              itemInUploadList.backendId = response.data.id
            } else {
              itemInUploadList.status = 'SUCCESS'
              if (response.data.fileSize) {
                response.data.fileSize = changeByteUnit(Number(response.fileSize));
              } else {
                response.data.fileSize = ''
              }
              itemInUploadList.successInfo = response.data
            }
          },
          (err) => {
            if (err.statusText === 'abort') { // 用户取消了上传任务。
              console.log('用户取消了任务！');
              const index = this.uploadStatusList.findIndex((eachItem) => {
                return eachItem.uid === itemInUploadList.uid
              })
              this.uploadStatusList.splice(index, 1)
            } else {
              console.log('上传失败！');
              itemInUploadList.status = 'FAIL'
              itemInUploadList.statusText = this.$i18n.t(`gather.material_upload_fail`)
            }
          },
          (progress) => {
            console.log('进度：', progress);
            itemInUploadList.progress = progress
          }
        )

        this.uploadStatusList.unshift(itemInUploadList);
      })
    },
    onClickRow(e) {
      const checkboxNodeList = e.currentTarget.getElementsByClassName('selection-click-target')
      if (checkboxNodeList && checkboxNodeList[0]) {
        checkboxNodeList[0].click()
      }
    },
    onClickUpload() {
      checkUserSize({}, (data) => {
        //判断已用是否大于3G
        if ((data.data / 1024 / 1024) > 3) {
          this.$alert({ content: this.$i18n.t('tips_code.FAILURE_3024')});
        } else {
          this.$refs['file-input'].click()
        }
      })
    },
  },
  mounted() {
  },
  beforeDestroy() {
    if (this.canUpload) {
      const capitalizedMaterialType = capitalize(this.materialType)
      this.$store.commit(`setUploadStatusList${capitalizedMaterialType}`, this.uploadStatusList.filter((item) => {
        return item.status === 'LOADING'
      }))
    }
  }
}
</script>

<style lang="less" scoped>
.material-list {
  position: relative;
  .ellipsis {
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    width: 100%;
    display: inline-block;
  }

  .crumbs {
    margin-top: 10px;
  }

  // @table-height: 420px;
  // @table-head-row-height: 40px;
  // @table-border-size: 1px;
  @table-height: 420px;
  @table-head-row-height: 0px;
  @table-border-size: 0px;


  .table {
    margin-top: 10px;
    // border: @table-border-size solid #EBEDF0;
    width: 100%;
    height: @table-height;

    // >.table-head-row {
    //   width: 100%;
    //   height: @table-head-row-height;
    //   background: #F5F7FA;
    //   color: #646566;

    //   .table-head {
    //     font-size: 16px;
    //     line-height: @table-head-row-height;
    //     height: 100%;
    //     display: inline-block;
    //     &:nth-of-type(1) {
    //       color: transparent;
    //     }
    //   }
    // }

    >.table-body {
      height: calc(@table-height - @table-head-row-height - @table-border-size - @table-border-size);
      overflow: auto;
      display: inline-block;
      width: 100%;

      .table-body-row {
        height: 50px;
        // border-bottom: 1px solid #EBEDF0;
        display: flex;
        align-items: center;
        border-radius: 4px;
        cursor: pointer;
        &:hover {
          background: #F7F8FA;
        }
        >.table-data {
          font-size: 14px;
          line-height: 50px;
          height: 100%;
          color: #323233;
          &:nth-of-type(1) {
            width: 50px;
          }
          &:nth-of-type(2) {
            width: 96px;
          }
          &:nth-of-type(3) {
            width: calc(100% - 50px - 96px);
          }
          &:last-of-type {
            padding-right: 10px;
          }
          >.list-img {
            position: relative;
            height: 100%;
            display: inline-block;
            width: 100%;

            >img,
            .audio-player {
              position: absolute;
              top: 50%;
              transform: translateY(-50%);
              width: 40px;
              height: 40px;
              object-fit: cover;
              &.folderIcon {
                object-fit: contain;
              }
            }
          }
          > .name:not(.searchRes) {
            display: inline-block;
            height: 100%;
            width: 100%;
            display: flex;
            align-items: center;
            > .name-inner {
              flex: 0 0 auto;
              display: inline-block;
              height: 100%;
              width: 50%;
            }
            > .upload-status {
              flex: 0 0 auto;
              display: inline-block;
              height: 100%;
              margin-left: 20px;
            }
          }
          > .name.searchRes {
            height: 100%;
            width: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: flex-start;
            line-height: initial;
            > .name-inner {
              flex: 0 0 auto;
              display: inline-block;
              width: 100%;
            }
            > .parent-info {
              > .parent-name {
                color: @color;
              }
            }
          }
          > .name:not(.upload-status-wrap):hover {
            > .name-inner {
              width: 100%;
            }
          }
        }
      }
      .no-more-data {
        margin-top: 16px;
        margin-bottom: 16px;
        text-align: center;
        font-size: 12px;
        color: #969799;
      }
    }

    >.no-data {
      height: calc(@table-height - @table-head-row-height - @table-border-size - @table-border-size);
      width: 100%;
      position: relative;

      >div {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        text-align: center;

        >img {
          width: 116px;
        }

        >span {
          margin-top: 20px;
          display: block;
          font-size: 14px;
          color: #646566;
        }

        >a {
          >button {
            margin-top: 20px;
          }
        }
      }
    }
  }

  .checkbox {
    width: 100%;
    height: 100%;
  }

  .btns {
    left: 0;
    margin-top: 29px;
    .upload-btn {
      display: flex;
      align-items: center;

      >span {
        display: inline-block;
        margin-right: 4px;
      }

      i.tool-tip-for-editor {
        font-size: 12px;
        transform: scale(0.923) translateY(1px);
        cursor: default;
      }
    }
  }
}

.material-list.dark {
  .ellipsis {
  }
  .crumbs {
  }
  
  .table {
    // border: @table-border-size solid #EBEDF0;
    // >.table-head-row {
    //   background: #F5F7FA;
    //   color: #646566;
    //   .table-head {
    //     &:nth-of-type(1) {
    //       color: transparent;
    //     }
    //   }
    // }

    >.table-body {
      .table-body-row {
        // border-bottom: 1px solid #EBEDF0;
        &:hover {
          background: #252526;
        }
        >.table-data {
          color: #fff;
          >.list-img {
            >img,
            .audio-player {
              &.folderIcon {
              }
            }
          }
        }
      }
    }

    >.no-data {
      >div {
        >img {
        }
        >span {
          color: rgba(255, 255, 255, 0.6);
        }
        >a {
          >button {
          }
        }
      }
    }
  }

  .checkbox {
  }

  .btns {
    .upload-btn {
      >span {
      }
      i.tool-tip-for-editor {
      }
    }
  }
}
</style>