<template>
  <div class="el-draggable-transfer-panel" :class="[hasClassify? 'is-with-classify' : '']">
    <p class="el-draggable-transfer-panel__header">
      {{ title }}
      <span>{{ checkedSummary }}</span>
    </p>
    <div class="el-draggable-transfer-panel__main">
      <div class="el-draggable-transfer-panel__classify" v-if="hasClassify">
        <slot name="classify"></slot>
      </div>
      <div :class="['el-draggable-transfer-panel__body', hasFooter ? 'is-with-footer' : '']">
        <el-input
            class="el-draggable-transfer-panel__filter"
            v-model="query"
            :placeholder="placeholder"
            @mouseenter.native="inputHover = true"
            @mouseleave.native="inputHover = false"
            v-if="filterable">
          <i slot="suffix"
             :class="['el-input__icon', 'el-icon-' + inputIcon]"
             @click="clearQuery"
          />
        </el-input>
        <el-checkbox-group
            v-model="checked"
            v-show="!hasNoMatch && data.length > 0"
            :class="{ 'is-filterable': filterable }"
            ref="elDraggableTransferPanelRef"
            class="el-draggable-transfer-panel__list">
          <el-checkbox
              class="el-draggable-transfer-panel__item"
              :label="item[keyProp]"
              :disabled="item[disabledProp]"
              :key="item[keyProp]"
              v-for="item in filteredData">
            <option-content :option="item"></option-content>
          </el-checkbox>
        </el-checkbox-group>
        <p class="el-draggable-transfer-panel__empty"
           v-show="hasNoMatch">无匹配数据</p>
        <p class="el-draggable-transfer-panel__empty"
           v-show="data.length === 0 && !hasNoMatch">无数据</p>
        <p class="el-draggable-transfer-panel__footer" v-if="hasFooter">
          <slot></slot>
        </p>
      </div>
    </div>
  </div>
</template>

<script>
import ElCheckboxGroup from '@ued_fpi/element-ui/packages/checkbox-group';
import ElCheckbox from '@ued_fpi/element-ui/packages/checkbox';
import ElInput from '@ued_fpi/element-ui/packages/input';
import Locale from '@ued_fpi/element-ui/src/mixins/locale';

export default {
  name: 'ElDraggableTransferPanel',
  componentName: 'ElDraggableTransferPanel',
  mixins: [Locale],
  components: {
    ElCheckboxGroup,
    ElCheckbox,
    ElInput,
    OptionContent: {
      props: {
        option: Object
      },
      render(h) {
        const getParent = vm => {
          if (vm.$options.componentName === 'ElDraggableTransferPanel') {
            return vm;
          } else if (vm.$parent) {
            return getParent(vm.$parent);
          } else {
            return vm;
          }
        };
        const panel = getParent(this);
        const transfer = panel.$parent || panel;
        return panel.renderContent
          ? panel.renderContent(h, this.option)
          : transfer.$scopedSlots.default
            ? transfer.$scopedSlots.default({option: this.option})
            : <span>{this.option[panel.labelProp] || this.option[panel.keyProp]}</span>;
      }
    }
  },
  props: {
    data: {
      type: Array,
      default() {
        return [];
      }
    },
    panelType: String,
    renderContent: Function,
    placeholder: String,
    title: String,
    filterable: Boolean,
    isSortable: Boolean,
    isObjectValue: Boolean,
    format: Object,
    sortableProps: Object,
    filterMethod: Function,
    defaultChecked: Array,
    props: Object
  },
  data() {
    return {
      checked: [],
      allChecked: false,
      query: '',
      inputHover: false,
      checkChangeByUser: true
    };
  },
  watch: {
    checked(val, oldVal) {
      this.updateAllChecked();
      if (this.checkChangeByUser) {
        const movedKeys = val.concat(oldVal)
          .filter(v => val.indexOf(v) === -1 || oldVal.indexOf(v) === -1);
        this.$emit('checked-change', val, movedKeys);
      } else {
        this.$emit('checked-change', val);
        this.checkChangeByUser = true;
      }
    },

    data() {
      const checked = [];
      const filteredDataKeys = this.filteredData.map(item => item[this.keyProp]);
      this.checked.forEach(item => {
        if (filteredDataKeys.indexOf(item) > -1) {
          checked.push(item);
        }
      });
      this.checkChangeByUser = false;
      this.checked = checked;
    },

    checkableData() {
      this.updateAllChecked();
    },

    defaultChecked: {
      immediate: true,
      handler(val, oldVal) {
        if (oldVal && val.length === oldVal.length &&
            val.every(item => oldVal.indexOf(item) > -1)) return;
        const checked = [];
        const checkableDataKeys = this.checkableData.map(item => item[this.keyProp]);
        val.forEach(item => {
          if (checkableDataKeys.indexOf(item) > -1) {
            checked.push(item);
          }
        });
        this.checkChangeByUser = false;
        this.checked = checked;
      }
    }
  },
  computed: {

    filteredData() {
      return this.data.filter(item => {
        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;
        }
      });
    },

    checkableData() {
      return this.filteredData.filter(item => !item[this.disabledProp]);
    },

    checkedSummary() {
      const checkedLength = this.checked.length;
      const dataLength = this.data.length;
      const {noChecked, hasChecked} = this.format;
      if (noChecked && hasChecked) {
        return checkedLength > 0
          ? hasChecked.replace(/\${checked}/g, checkedLength).replace(/\${total}/g, dataLength)
          : noChecked.replace(/\${total}/g, dataLength);
      } else {
        return `${checkedLength}/${dataLength}`;
      }
    },

    isIndeterminate() {
      const checkedLength = this.checked.length;
      return checkedLength > 0 && checkedLength < this.checkableData.length;
    },

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

    inputIcon() {
      return this.query.length > 0 && this.inputHover
        ? 'circle-close'
        : 'search';
    },

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

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

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

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

    hasClassify() {
      return !!this.$slots.classify;
    }
  },
  methods: {
    updateAllChecked() {
      const checkableDataKeys = this.checkableData.map(item => item[this.keyProp]);
      this.allChecked = checkableDataKeys.length > 0 &&
          checkableDataKeys.every(item => this.checked.indexOf(item) > -1);
    },

    handleAllCheckedChange(value) {
      this.checked = value
        ? this.checkableData.map(item => item[this.keyProp])
        : [];
    },

    clearQuery() {
      if (this.inputIcon === 'circle-close') {
        this.query = '';
      }
    },

    // 行拖拽
    toDrag() {
      const el = this.$refs.elDraggableTransferPanelRef.$el;
      const _this = this;
      const obj = {
        ...this.sortableProps,
        // onEnd({newIndex, oldIndex}) {
        //     console.log(newIndex, oldIndex)
        //     // const currRow = _this.tableData.splice(oldIndex, 1)[0]
        //     // _this.tableData.splice(newIndex, 0, currRow)
        //     // console.log(_this.tableData)
        // },
        onUpdate({newIndex, oldIndex}) {
          let d = _this.data;

          // let newDataIndex = null
          // if(newIndex === 0){
          //     newDataIndex = d.indexOf(_this.filteredData[newIndex])
          // }else {
          //     newDataIndex = d.indexOf(_this.filteredData[newIndex-1])+1
          // }
          // const oldDataIndex = d.indexOf(_this.filteredData[oldIndex])

          let newDataIndex = null;
          let oldDataIndex = null;
          d.forEach((item, index) => {
            if (_this.filteredData[oldIndex][_this.keyProp] === item[_this.keyProp]) {
              oldDataIndex = index;
            }
            if (_this.filteredData[newIndex][_this.keyProp] === item[_this.keyProp]) {
              newDataIndex = index;
            }
          });

          const currItem = d.splice(oldDataIndex, 1)[0];
          d.splice(newDataIndex, 0, currItem);
          if (_this.isObjectValue) {
            _this.$emit('change', d);
          } else {
            _this.$emit('change', d.map(item => item[_this.keyProp]));
          }
        }
      };
      Sortable.create(el, obj);
    }
  },
  mounted() {
    this.$nextTick(()=>{
      if (this.isSortable && this.panelType === 'right') {
        this.toDrag();
      }
    });
    // console.log(this.$slots)
  }
};
</script>
