<template>
  <div class="v-page" @contextmenu.prevent.stop>
    <SearchTreeMenu
      ref="treeMenuRef"
      title="资源分类列表"
      current-node-key=""
      :tree-data="tree_list"
      @current-change="onChange"
      @onCreate="onCreateClassify"
      @onEdit="onEditClassify"
      @onDelete="onDeleteClassify"
    />
    <div class="v-ctx">
      <h2 class="v-title res_path">
        资源目录：
        <span @click="toBackRoot">根目录</span>
        <template v-if="find_params.path!='/'"><span v-for="(v,i) in find_params.path.substring(1).split('/')" :key="i" @click="toChangePath(i)">/{{v}}</span></template>
      </h2>
      <div class="flex-h mt-12 mb-12">
        <QueryInput v-model="find_params.like_name" @query="findAllResource" />
        <i
          title="切换视图"
          class="type_icon ml-12"
          :class="['i-zy-slt','i-zy-lb'][show_type]"
          @click="changeShowType"
        />
        <i
          title="按创建时间排序"
          class="type_icon ml-12"
          :class="{'':'i-zy-sj',ASC:'i-zy-sj-d',DESC:'i-zy-sj-u'}[find_params.sort_create_time]"
          @click="findBySort('sort_create_time')"
        />
        <i
          title="按文件大小排序"
          class="type_icon ml-12"
          :class="{'':'i-zy-dx',ASC:'i-zy-dx-d',DESC:'i-zy-dx-u'}[find_params.sort_size]"
          @click="findBySort('sort_size')"
        />
        <div class="flex-1"></div>
        <el-button @click.stop="toMoveFolder" type="warning" round>移动到文件夹</el-button>
        <el-button @click.stop="toMoveClassify" type="primary" round>移动到分类</el-button>
        <el-button @click.stop="toDelete" type="danger" round>删除选中</el-button>
        <el-button @click="toUpload" type="success" round>上传资源</el-button>
      </div>

      <div
        v-if="show_type"
        style="height: calc(100vh - 280px);overflow: auto;"
        @contextmenu.prevent.stop="showContextmenu"
      >
        <div class="res_card_layout">
          <div
            class="res_card"
            v-for="v in res_list"
            :key="v.id"
            :title="v.name"
            :class="{active:active_resources.includes(v.id),'normal_icon':!accept_map[v.type].icon}"
            @contextmenu.prevent.stop="showResContextmenu($event, v)"
            @dblclick="toPreview(v)"
            @click.stop="onSelectResources(v)"
          >
            <div
              :class="['res_icon',accept_map[v.type].icon]"
              :style="{[accept_map[v.type].icon?'color':'backgroundColor']:accept_map[v.type]?.color}"
              :data-label="v.type"
            />
            <div class="res_name ellipsis-1">{{ v.name }}</div>
            <i v-if="v.type!='folder'" class="el-icon-success" />
          </div>
          <el-empty class="v-empty" v-if="!res_list.length" />
        </div>

        <ul
          v-show="contextmenu_position"
          v-clickoutside="closeContextmenu"
          :style="contextmenu_position"
          class="contextmenu_layout"
        >
          <li v-for="(v, i) in contextmenu" :key="i" @click="onContextmenuClick(v)">{{ v.label }}</li>
        </ul>
      </div>

      <TableLayout
        v-else
        selection
        ref="tableRef"
        calcMaxHeight="317px"
        :column="column"
        :data="res_list"
        @selection-change="onTableSelectionChange"
      >
        <template v-slot:classify="{ row }">{{classifyMap[row.classifyId]?.name}}</template>
        <template v-slot:size="{ row }">{{row.size?.formatFileSize()}}</template>
        <template v-slot:createTime="{row}">{{new Date(row.createTime).format('yyyy-MM-dd hh:mm')}}</template>
        <template v-slot:action="{ row }">
          <el-button @click="toRename(row)" type="text" icon="el-icon-edit">重命名</el-button>
          <el-button v-if="row.type=='folder'" @click="toPreview(row)" type="text" icon="el-icon-folder-opened">打开</el-button>
          <el-button v-else @click="toPreview(row)" type="text" icon="el-icon-view">预览</el-button>
          <el-button @click="toDelete(row)" type="text" icon="el-icon-delete" class="color-danger">删除</el-button>
        </template>
      </TableLayout>

      <div class="bottom_info_bar">
        <p>共有<span v-text="pageInfo.total"/>文件 已选中<span v-text="active_resources.length"/>文件</p>
        <Pagination :pageInfo="pageInfo" @page-info-change="onPageInfoChange" />
      </div>
    </div>
  </div>
</template>

<script>
import { SearchTreeMenu, TableLayout } from '@/components/layout'
import { Pagination, QueryInput } from '@/components/widget'

import contextmenuMixin from './mixins/contextmenu'

import clickoutside from 'element-ui/src/utils/clickoutside'

import {
  createResourceClassifyApi,
  deleteResourceClassifyApi,
  findAllResourceApi,
  findAllResourceClassifyApi,
  updateResourceClassifyApi
} from '@/api/system/resource'
import { lst, ACCEPT_MAP } from '@/utils'

export default {
  components: { SearchTreeMenu, TableLayout, Pagination, QueryInput },

  mixins: [contextmenuMixin],

  directives: { clickoutside },

  data: () => ({
    find_params: { like_name: '', path: '/', classifyId: '', sort_create_time: '', sort_size: '' },
    show_type: 0,
    tree_list: [],
    res_list: [],
    active_resources: [],
    pageInfo: { current: 1, size: 50, total: 0 }
  }),

  watch: {
    show_type (v) {
      lst.save('RESOURCE_SHOW_TYPE', v)
      if (v === 0) {
        this.$nextTick(() => {
          const actives = []
          for (const item of this.res_list) {
            if (this.active_resources.includes(item.id)) actives.push(item)
          }
          this.$refs.tableRef.toggleRowSelections(actives, true)
        })
      }
    },

    'find_params.path': {
      immediate: true,
      handler (v) {
        this.pageInfo.current = 1
        this.findAllResource()
      }
    }
  },

  created () {
    this.accept_map = ACCEPT_MAP
    this.classifyMap = {}
    this.show_type = +lst.get('RESOURCE_SHOW_TYPE') || 0
    this.column = [
      { prop: 'name', label: '文件名' },
      { prop: 'classify', label: '分类' },
      { prop: 'type', label: '文件类型' },
      { prop: 'size', label: '文件大小' },
      { prop: 'createTime', label: '创建时间', width: '120' },
      { prop: 'createor', label: '上传人' },
      { prop: 'action', label: '操作', width: '200' }
    ]

    this.$store.$on('onUploadEnd', this.findAllResource)
    this.findAllResourceClassify()
  },

  mounted () {
    document.body.addEventListener('click', this.toCancelActiveResources)
  },

  beforeDestroy () {
    document.body.removeEventListener('click', this.toCancelActiveResources)
  },

  methods: {
    async findAllResourceClassify () {
      const { data } = await findAllResourceClassifyApi()
      const { map, tree } = data.toTree()
      this.classifyMap = map
      this.tree_list = [{ id: '', name: '全部' }, ...tree]
    },

    onChange (current) {
      if (this.find_params.classifyId === current.id) return
      this.find_params.classifyId = current.id
      this.pageInfo.current = 1
      this.findAllResource()
    },

    async findAllResource () {
      const { data: { list, total } } = await findAllResourceApi({
        path: this.find_params.path,
        likeName: this.find_params.like_name,
        classifyId: this.find_params.classifyId,
        sortBySize: this.find_params.sort_size,
        sortByCreateTime: this.find_params.sort_create_time,
        ...this.pageInfo
      })
      this.pageInfo.total = total
      this.res_list = list
    },

    onCreateClassify (currentClassify) {
      this.saveClassify({ pid: currentClassify?.id || 0 })
    },

    onEditClassify (currentClassify) {
      if (!currentClassify.id) return this.$message.error('该资源类型不可修改')
      this.saveClassify({ ...currentClassify })
    },

    async onDeleteClassify ({ id }) {
      if (!id) return this.$message.error('该资源类型不可删除')
      await this.$confirm('将删除一个资源类型，是否继续？', '操作提示', {
        type: 'warning'
      })
      await deleteResourceClassifyApi(id)
      this.findAllResourceClassify()
    },

    async saveClassify ({ id, name, pid }) {
      const value = await this.showInputPrompt('请输入资源类型', {
        inputValue: name,
        inputErrorMessage: '请输入资源类型'
      })

      await (!id ? createResourceClassifyApi : updateResourceClassifyApi)({
        id,
        name: value,
        pid
      })
      this.findAllResourceClassify()
    },

    async showInputPrompt (title, options) {
      const { value } = await this.$prompt('', title, {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputPattern: /\S+/,
        ...options
      })
      return value
    },

    changeShowType () {
      this.show_type = (this.show_type + 1) % 2
    },

    onPageInfoChange () {
      this.findAllResource()
      this.active_resources = []
    },

    onTableSelectionChange (selection) {
      this.active_resources = selection.map(v => v.id)
    },

    onSelectResources (row) {
      if (row.type === 'folder') return

      const index = this.active_resources.indexOf(row.id)
      if (index === -1) {
        this.active_resources.push(row.id)
      } else {
        this.active_resources.splice(index, 1)
      }
    },

    toUpload () {
      this.$store.showUploadDialog({ path: this.find_params.path })
    },

    findBySort (sortKey) {
      const keys = ['', 'ASC', 'DESC']
      this.find_params[sortKey] = keys[
        (keys.indexOf(this.find_params[sortKey]) + 1) %
        keys.length
      ]
      this.findAllResource()
    }
  }
}
</script>

<style lang="scss" scoped>
.res_path span {
  padding: 2px;
  font-weight: 400;
  font-size: 13px;
  color: $--color-text-regular;
  cursor: pointer;

  &:hover {
    text-decoration: underline;
    color: $--color-text-primary;
  }
}

.v-ctx {
  position: relative;
}

.type_icon {
  width: 32px;
  line-height: 32px;
  text-align: center;
  font-size: 28px;
  color: $--color-primary;
  cursor: pointer;
}

.res_card_layout {
  display: flex;
  flex-wrap: wrap;
  position: relative;
  overflow: auto;

  .res_card {
    margin: 12px;
    padding: 16px;
    width: 104px;
    height: 108px;
    text-align: center;
    position: relative;

    .res_icon {
      margin: auto auto 8px;
      border-radius: 15px;
      font-size: 15px;
      color: #fff;
      user-select: none;

      &::before {
        font-size: 64px;
      }
    }

    &.normal_icon .res_icon {
      font-weight: bold;
      background-color: #ff9800;

      &::after {
        content: attr(data-label);
      }
    }

    .res_name {
      line-height: 1.3;
      color: $--color-text-regular;
    }

    .el-icon-success {
      display: none;
      position: absolute;
      left: 3px;
      top: 3px;
      font-size: 18px;
      color: rgba($color: $--color-primary, $alpha: 0.3);
    }

    &:hover,
    &.active {
      background-color: rgba($color: $--color-primary, $alpha: 0.1);
      outline: 1px solid rgba($color: $--color-primary, $alpha: 0.5);
      cursor: pointer;
    }

    &:hover .el-icon-success,
    &.active .el-icon-success {
      display: block;
    }

    &.active .el-icon-success {
      color: $--color-primary;
    }
  }
}

.bottom_info_bar {
  position: absolute;
  left: 0;
  bottom: 0;
  right: 0;

  > p {
    position: inherit;
    bottom: 10px;
    left: inherit;
    font-size: 13px;
    color: #666;
    word-spacing: 12px;

    > span {
      font-weight: bold;
      color: $--color-danger;
    }
  }

  ::v-deep > .el-pagination {
    position: inherit;
    bottom: inherit;
    right: inherit;
  }
}

.contextmenu_layout {
  padding: 6px 0;
  position: fixed;
  z-index: 1;
  background-color: #fff;
  box-shadow: 0 0 8px 0 #ccc;
  border-radius: 3px;

  > li {
    padding: 0 12px;
    display: block;
    line-height: 28px;
    cursor: pointer;

    &:hover {
      background-color: rgba($color: $--color-primary, $alpha: 0.2);
    }
  }
}
</style>
