<template>
  <div class="el-transfer-view">
    <p class="el-transfer-view__header">
      <span>
        {{ title }}
        <span v-if="pagination" class="el-transfer-view__header-text">{{ total }}个</span>
        <span v-else class="el-transfer-view__header-text">{{ filteredData.length }}个</span>
      </span>
      <span class="el-transfer__icon">
        <i class="el-icon-clear" @click="clearItem"></i>
      </span>
    </p>

    <div :class="['el-transfer-view__body', (pagination || hasFooter) ? 'is-with-footer' : '']">
      <div class="el-transfer-view__filter_box">
        <el-input class="el-transfer-view__filter" v-model="query" size="large" :placeholder="placeholder" @mouseenter.native="inputHover = true" @mouseleave.native="inputHover = false" clearable
          v-if="filterable">
          <i class="el-input__icon el-icon-search icon" slot="suffix" @click="clearQuery" />
        </el-input>
      </div>

      <el-scrollbar class="scrollbar" :class="{ 'is-filterable': filterable }">
        <template>
          <ol class="el-transfer-view__list" role="transfer-view-list" v-show="!hasNoMatch && targetData.length > 0" :class="{ 'is-filterable': filterable }"
            :style="filterable ? 'margin-top: 0;':'margin-top: 8px;'">
            <li class="el-transfer-view__item" ref="viewItem" :disabled="item[disabledProp]" role="transfer-view-item" :key="item[keyProp]" @dragend.stop="handleDragEnd"
              @drop.stop="handleDragEnter($event, item)" v-for="(item, index) in filteredData">
              <div v-if="fixedList.includes(item[keyProp])">{{item[labelProp]}}</div>
              <template v-else>
                <div class="el-transfer-view__item--text" :draggable="dragable" @dragover.stop="handleDragOver($event, item)" @dragstart.stop="handleDragStart($event, item)">
                  <i class="el-icon-dragable el-transfer__icon" v-if="dragable"></i>{{item[labelProp]}}
                </div>
                <div class="el-transfer-view__item--icons">
                  <slot name="right-btn" v-bind="{item, index}"></slot>
                  <i @click="delItem(item)" class="el-icon-transfer-close el-transfer__icon"></i>
                </div>
              </template>
            </li>

          </ol>
          <p class="el-transfer-view__empty" v-show="hasNoMatch">
          <span>{{ t('el.transfer.noMatch') }}</span></p>
          <p class="el-transfer-view__empty" v-show="targetData.length === 0 && !hasNoMatch">
          <span>{{ t('el.transfer.noData') }}</span></p>
        </template>

      </el-scrollbar>

    </div>
    <div class="el-transfer-view__footer" v-if="pagination">
      <div style="position: relative;">
        <el-pagination ref="pagination" layout="prev, pager, smallPager, next" :total="total" :page-size="pageSize" @prev-click="prevClick" @next-click="nextClick"></el-pagination>
        <div v-show="targetData.length === 0 || hasNoMatch" class="pafination-reset"> 0/0 </div>
      </div>
    </div>
    <p class="el-transfer-view__footer" v-if="hasFooter">
      <slot></slot>
    </p>
  </div>
</template>

<script>
import ElInput from 'modesign-ui/packages/input';
import Locale from 'modesign-ui/src/mixins/locale';
import ElScrollbar from 'modesign-ui/packages/scrollbar';
import ElPagination from 'modesign-ui/packages/pagination';

export default {
  mixins: [Locale],

  name: 'ElTransferView',

  componentName: 'ElTransferView',

  components: {
    ElInput,
    ElScrollbar,
    ElPagination
  },

  props: {
    targetData: {
      type: Array,
      default() {
        return [];
      }
    },
    renderContent: Function,
    placeholder: String,
    title: String,
    filterable: Boolean,
    filterMethod: Function,
    userList: Array,
    dragable: Boolean,
    props: Object,
    fixedList: {
      type: Array,
      default: () => []
    },
    pagination: Boolean,
    pageSize: Number
  },

  data() {
    return {
      query: '',
      inputHover: false,
      dragging: null, // 拖拽的对象
      filteredData: [], // 展示列表的数据
      total: 0,
      filterPaginationData: [], // 分页状态下搜索时维护的数组
      page: 1
    };
  },

  watch: {
    targetData: {
      immediate: true,
      handler(newVal, oldVal) {
        this.setFilteredData();
      }
    },
    query: {
      immediate: true,
      handler() {
        this.setFilteredData();
      }
    }
  },

  computed: {
    hasNoMatch() {
      return this.query.length > 0 && this.filteredData.length === 0;
    },

    labelProp() {
      return this.props.label || 'label';
    },

    keyProp() {
      return this.props.key || 'key';
    },

    // 用户操作元素时可能要加的属性名
    userProp() {
      return this.props.user || '';
    },

    disabledProp() {
      return this.props.disabled || 'disabled';
    },

    hasFooter() {
      return !!this.$slots.default;
    }
  },

  methods: {
    getFilterData(arr = []) {
      return arr.filter(item => {
        const i = this.userList.findIndex(x => x[this.keyProp] === item[this.keyProp]);
        if (this.userProp) {
          this.$set(item, this.userProp, i > -1 ? true : false);
        }
        if (typeof this.filterMethod === 'function') {
          return this.filterMethod(this.query, item);
        } else {
          const label = item[this.labelProp] || item[this.keyProp].toString();
          return label.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
        }
      });
    },

    setFilteredData() {
      let arr = this.getFilterData(this.targetData);
      if (this.fixedList.length > 0) {
        const fixed = [];
        const list = [];
        arr.forEach(item => {
          if (this.fixedList.includes(item[this.keyProp])) {
            fixed.push(item);
          } else {
            list.push(item);
          }
        })
        arr = [...fixed, ...list];
      }
      this.filteredData = arr.slice(this.pageSize * (this.page - 1), this.pageSize * this.page);
      if (this.pagination) {
        this.filterPaginationData = arr;
        this.filteredData = arr.slice(this.pageSize * (this.page - 1), this.pageSize * this.page);
        this.total = this.filterPaginationData.length;
      } else {
        this.filteredData = arr;
      }
      if (this.userProp) {
        // 如果用户需要对数据操作
        this.$emit('handleDealData', this.filteredData);
      }
      // window.getSelection().empty() // 对右侧搜索栏有影响，只能一次输入一个字符
    },
    clearQuery() {
      this.query = '';
    },

    // 删除字段
    delItem(item) {
      if (this.filteredData.length <= 1) {
        this.$parent.pageR = this.$parent.pageR === 1 ? 1 : this.$parent.pageR - 1
        this.setFilteredData()
      }
      this.$emit('delItem', item);
    },

    // 清空所有选择字段
    clearItem() {
      this.$emit('clearItem', this.filteredData);
    },

    handleDragStart(event, item) {
      // 暂时定为所有给元素赋属性的情况都是不允许拖动的
      // 如果是fixedList里的元素，也不允许拖动
      if (item[this.userProp] || this.fixedList.includes(item[this.keyProp])) {
        return;
      }
      this.dragging = item;
    },

    handleDragOver(event) {
      event.dataTransfer.dropEffect = 'move';
      event.preventDefault();
    },

    handleDragEnter(event, item) {
      event.dataTransfer.effectAllowed = 'move';
      if (!this.dragging || item === this.dragging || this.fixedList.includes(item[this.keyProp])) {
        return;
      }
      const newItems = [...this.filteredData];
      const src = newItems.indexOf(this.dragging);
      const dst = item[this.userProp] ? this.userList.length : newItems.indexOf(item);
      if (dst === src) {
        return;
      }
      newItems.splice(dst, 0, ...newItems.splice(src, 1));
      this.filteredData = newItems;
      this.$emit('dragEnter', newItems)
      event.preventDefault();
    },

    handleDragEnd() {
      this.dragging = null;
    },

    // 上一页
    prevClick() {
      this.page = this.$refs.pagination.internalCurrentPage
      this.filteredData = this.filterPaginationData.slice(this.pageSize * (this.page - 1), this.pageSize * this.page);
    },

    // 下一页
    nextClick() {
      this.page = this.$refs.pagination.internalCurrentPage
      this.filteredData = this.filterPaginationData.slice(this.pageSize * (this.page - 1), this.pageSize * this.page);
    }
  }
};
</script>
