<template>
  <div class="transfer-wrap">
    <div class="transfer-allData">
      <div class="transfer-allData-filter">
        <span>{{ titles && titles[0] ? titles[0] : '未选' }}（{{allDataOptions.length}}）</span>
        <div class="transfer-filter-input">
          <el-input
            v-model="filters.all"
            :maxlength="200"
            placeholder="请输入"
            clearable
          ></el-input>
        </div>
        <div>
          <el-button
            size="mini"
            @click="filterAllData"
          >检索</el-button>
        </div>
        <div>
          <el-button
            size="mini"
            @click="showImportDialog"
          >导入</el-button>
        </div>
      </div>
      <div class="transfer-allData-box">
        <ul
          class="transfer-allData-select"
          tabindex="1"
          @focus="() => resetSelect('value')"
        >
          <template v-for="(item, index) in allDataOptions">
            <li
              :class="{'selected': selected.all.indexOf(getValue('key', item))>-1}"
              :key="index"
              :id="index"
              :value="getValue('key', item)"
              @click="() => selectedValueHandle('all', getValue('key', item))"
              @dblclick="() => addClickValue(getValue('key', item))"
              @mousedown="() => dragstartHandle('all', index)"
              @mouseover="() => dragingHandle('all', index)"
            >
              <slot
                name="option"
                :data="item"
                :$index="index"
              >
                {{ getValue('label', item) }}
              </slot>
            </li>
          </template>
        </ul>
      </div>
    </div>
    <div class="transfer-btnBox">
      <div class="cancel-btn-box">
        <div
          class="transfer-btnBox-btn"
          @click="removeSelectedValue(true)"
        >
          <i class="el-icon-d-arrow-left"></i>
        </div>
        <div
          class="transfer-btnBox-btn"
          @click="removeSelectedValue()"
        >
          <i class="el-icon-arrow-left"></i>
        </div>
      </div>
      <div class="selected-btn-box">
        <div
          class="transfer-btnBox-btn"
          @click="addSelectedValue()"
        >
          <i class="el-icon-arrow-right"></i>
        </div>
        <div
          class="transfer-btnBox-btn"
          @click="addSelectedValue(true)"
        >
          <i class="el-icon-d-arrow-right"></i>
        </div>
      </div>
      <el-button
        size="mini"
        type="primary"
        @click="submitHandle"
      >确定</el-button>
      <br />
      <br />
      <el-button
        size="mini"
        @click="cancelHandle"
      >取消</el-button>
    </div>
    <div class="transfer-selectData">
      <div class="transfer-selectData-filter">
        <span>{{ titles && titles[1] ? titles[1] : '已选' }}（{{selectDataOptions.length}}）</span>
        <div class="transfer-filter-input">
          <el-input
            v-model.trim="filters.selected"
            :maxlength="200"
            placeholder="请输入"
            clearable
          ></el-input>
        </div>
        <div>
          <el-button
            size="mini"
            @click="filterSelectedData"
          >检索</el-button>
        </div>
      </div>
      <div class="transfer-selectData-box">
        <ul
          class="transfer-selectData-select"
          tabindex="2"
          @focus="() => resetSelect('all')"
        >
          <template v-for="(item, index) in selectDataOptions">
            <li
              :class="{'selected': selected.value.indexOf(getValue('key', item))>-1}"
              :key="index"
              :value="getValue('key', item)"
              @click="() => selectedValueHandle('value', getValue('key', item))"
              @dblclick="() => removeClickValue(getValue('key', item))"
              @mousedown="() => dragstartHandle('value', index)"
              @mouseover="() => dragingHandle('value', index)"
            >
              <slot
                name="option"
                :data="item"
                :$index="index"
              >
                {{ getValue('label', item) }}
              </slot>
            </li>

          </template>
        </ul>
      </div>
    </div>
    <el-input
      id="copyArea"
      class="copyArea"
      type="textarea"
      resize="none"
    ></el-input>
    <normal-dialog
      title="导入"
      :visible.sync="importDialogVisible"
      :before-close="closeHandle"
      append-to-body
    >
      <el-input
        type="textarea"
        v-model="importData"
        :autosize="{ minRows: 5, maxRows: 10}"
        resize="none"
        placeholder="请粘贴数据"
        clearable
      ></el-input>
      <div slot="footer">
        <el-button
          type="primary"
          @click="checkImportData"
        >确定</el-button>
        <el-button @click="closeHandle">取消</el-button>
      </div>
    </normal-dialog>
  </div>
</template>

<script>
export default {
  name: 'ks-transfer',
  props: {
    titles: Array,
    list: { type: Array, default: () => [] },
    value: Array,
    onChange: Function,
    mapProps: {
      type: Object,
      default: () => ({
        key: 'id',
        label: 'name',
      }),
    },
  },

  data() {
    return {
      filters: this.initFilter(),
      trueValue: this.value,
      selected: {
        all: [],
        value: [],
      },
      dragging: false,
      startIndex: undefined,
      lastIndex: undefined,
      importDialogVisible: false,
      importData: '',
    };
  },
  watch: {
    value(nVal) {
      if (nVal && nVal.length) {
        this.trueValue = nVal;
      } else {
        this.trueValue = [];
      }
    },
  },
  computed: {
    allDataOptions() {
      return this.list
        .filter(i => !this.trueValue.includes(i[this.mapProps.key]))
        .filter(i =>
          this.filters.allValue
            ? i[this.mapProps.label]
              ? i[this.mapProps.label].includes(this.filters.allValue)
              : false
            : true
        );
      return list;
    },
    selectDataOptions() {
      return this.list
        .filter(i => this.trueValue.includes(i[this.mapProps.key]))
        .filter(i =>
          this.filters.selectedValue
            ? i[this.mapProps.label]
              ? i[this.mapProps.label].includes(this.filters.selectedValue)
              : false
            : true
        );
    },
  },
  methods: {
    initFilter() {
      return {
        all: '',
        allValue: '',
        selected: '',
        selectedValue: '',
      };
    },
    filterAllData() {
      this.filters.allValue = this.filters.all;
    },
    filterSelectedData() {
      this.filters.selectedValue = this.filters.selected;
    },
    addClickValue(val) {
      this.trueValue.push(val);
    },
    removeClickValue(val) {
      this.trueValue = this.trueValue.filter(item => item !== val);
      this.selected.value = this.selected.value.filter(item => item !== val);
    },
    addSelectedValue(flag) {
      this.trueValue = flag
        ? this.list.map(i => i[this.mapProps.key])
        : [...this.trueValue, ...this.selected.all];
      this.selected.all = [];
    },
    removeSelectedValue(flag) {
      this.trueValue = flag
        ? []
        : this.trueValue.filter(i => !this.selected.value.includes(i));
    },
    submitHandle() {
      this.filters = this.initFilter();
      if (this.onChange) {
        this.onChange(this.trueValue);
      } else {
        this.$emit('input', this.trueValue);
        this.$emit('close');
      }
    },
    cancelHandle() {
      this.filters = this.initFilter();
      this.$emit('close');
    },
    getValue(key, item) {
      return item[this.mapProps[key]];
    },
    selectedValueHandle(key, val) {
      this.selected[key] = [val];
    },
    dragstartHandle(key, index) {
      let value =
        key === 'value'
          ? this.selectDataOptions[index]
          : this.allDataOptions[index];
      this.selectedValueHandle(value);
      this.startIndex = index;
      this.dragging = true;
      document.addEventListener('mouseup', this.dragendHandle);
    },
    dragingHandle(key, index) {
      if (this.dragging) {
        let value =
          key === 'value'
            ? this.selectDataOptions[index]
            : this.allDataOptions[index];
        this.lastIndex = index;
        let options =
          key === 'value' ? this.selectDataOptions : this.allDataOptions;
        if (this.lastIndex > this.startIndex) {
          this.selected[key] = options
            .slice(this.startIndex, this.lastIndex + 1)
            .map(item => this.getValue('key', item));
        } else {
          this.selected[key] = options
            .slice(this.lastIndex, this.startIndex + 1)
            .map(item => this.getValue('key', item));
        }
      }
    },

    dragendHandle(e) {
      this.dragging = false;
      this.startIndex = undefined;
      this.lastIndex = undefined;
      document.removeEventListener('mouseup', this.dragendHandle);
    },
    resetSelect(key) {
      this.selected[key] = [];
    },
    showImportDialog() {
      this.importDialogVisible = true;
    },
    closeHandle(done) {
      this.importData = '';
      done && typeof done == 'function'
        ? done()
        : (this.importDialogVisible = false);
    },
    checkImportData() {
      let dataList = this.importData.split(/\n/);
      console.log(dataList);
      let errorList = [];
      let selectedList = [];
      for (let index = 0; index < dataList.length; index++) {
        const element = dataList[index];
        let dataIndex = this.allDataOptions.findIndex(
          i => i[this.mapProps.label] === element
        );
        if (dataIndex > -1) {
          selectedList.push(this.allDataOptions[dataIndex][this.mapProps.key]);
        } else {
          errorList.push(element);
        }
      }
      this.selected.all = selectedList;
      if (errorList.length > 0) {
        this.showFailMessage(errorList);
      }
      this.closeHandle();
    },
    showFailMessage(list) {
      console.log(list);
      this.$mdAlert
        .confirm(list.join(',') + ' 等数据并未匹配到选项,点击确认复制失败选项')
        .then(action => {
          let input = document.getElementById('copyArea');
          input.value = list.join('\n');
          input.select();
          document.execCommand('copy');
        })
        .catch(e => {
          console.log(e);
        });
    },
  },
};
</script>

<style lang="scss">
@import '@/assets/styles/variables.scss';

.transfer-wrap {
  height: 600px;
  display: flex;
  .transfer-allData,
  .transfer-selectData {
    flex: 1;
    .transfer-selectData-box,
    .transfer-allData-box {
      width: 100%;
      height: 548px;
      margin-top: 12px;
      .transfer-selectData-select,
      .transfer-allData-select {
        box-sizing: border-box;
        background-color: #fff;
        margin: 0;
        padding: 0;
        overflow-y: auto;
        width: 100%;
        height: 100%;
        border: 1px solid #ebebeb;
        li {
          user-select: none;
          &.selected {
            color: #fff;
            background-color: $subMenuBg;
          }
        }
      }
    }
  }
  .transfer-btnBox {
    width: 100px;
    text-align: center;
    .transfer-btnBox-btn {
      width: 50px;
      height: 50px;
      line-height: 50px;
      margin: 0 auto;
      font-size: 30px;
    }
    .cancel-btn-box {
      margin-top: 100px;
      margin-bottom: 100px;
    }
    .selected-btn-box {
      margin-bottom: 50px;
    }
  }
  .transfer-selectData-filter,
  .transfer-allData-filter {
    display: flex;
    height: 40px;
    line-height: 40px;
    .transfer-filter-input {
      flex: 1;
      margin: 0 10px 0 5px;
    }
  }
  .copyArea {
    position: absolute;
    top: 0;
    left: 0;
    opacity: 0;
    z-index: -10;
  }
}
</style>
