<template>
  <div class="el-transfer">
    <transfer-panel v-bind="$props" ref="leftPanel" :data="sourceData" :title="titles[0] || t('el.transfer.titles.0')"
      :default-checked="leftDefaultChecked" :placeholder="filterPlaceholder || t('el.transfer.filterPlaceholder')"
      @checked-change="onSourceCheckedChange">
      <slot name="left-footer"></slot>
    </transfer-panel>
    <div class="el-transfer__buttons">
      <div>
        <el-button type="primary" :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
          @click.native="moveUp" :disabled="upDisabled || isDisabled">
          <i class="el-icon-arrow-up"></i>
        </el-button>
      </div>
      <div>
        <el-button type="primary" :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
          @click.native="moveDown" :disabled="downDisabled || isDisabled">
          <i class="el-icon-arrow-down"></i>
        </el-button>
      </div>
      <div>
        <el-button type="primary" :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
          @click.native="addToLeft" :disabled="rightChecked.length === 0 || isDisabled">
          <i class="el-icon-arrow-left"></i>
        </el-button>
      </div>
      <div>
        <el-button type="primary" :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
          @click.native="addToRight" :disabled="leftChecked.length === 0 || isDisabled">
          <i class="el-icon-arrow-right"></i>
        </el-button>
      </div>
    </div>
    <transfer-panel v-bind="$props" ref="rightPanel" :data="targetData" :title="titles[1] || t('el.transfer.titles.1')"
      :default-checked="rightDefaultChecked" :placeholder="filterPlaceholder || t('el.transfer.filterPlaceholder')"
      @checked-change="onTargetCheckedChange">
      <slot name="right-footer"></slot>
    </transfer-panel>
  </div>
</template>

<script>
import ElButton from 'element-ui/packages/button';
import Emitter from 'element-ui/src/mixins/emitter';
import Locale from 'element-ui/src/mixins/locale';
import TransferPanel from './transfer-panel.vue';
import Migrating from 'element-ui/src/mixins/migrating';

export default {
  name: 'ElGrpTransfer',

  mixins: [Emitter, Locale, Migrating],

  components: {
    TransferPanel,
    ElButton
  },

  props: {
    isDisabled: {
      type: Boolean,
      default() {
        return false;
      }
    },
    data: {
      type: Array,
      default() {
        return [];
      }
    },
    titles: {
      type: Array,
      default() {
        return [];
      }
    },
    buttonTexts: {
      type: Array,
      default() {
        return [];
      }
    },
    filterPlaceholder: {
      type: String,
      default: ''
    },
    filterMethod: Function,
    leftDefaultChecked: {
      type: Array,
      default() {
        return [];
      }
    },
    rightDefaultChecked: {
      type: Array,
      default() {
        return [];
      }
    },
    renderContent: Function,
    value: {
      type: Array,
      default() {
        return [];
      }
    },
    format: {
      type: Object,
      default() {
        return {};
      }
    },
    filterable: Boolean,
    props: {
      type: Object,
      default() {
        return {
          label: 'label',
          key: 'key',
          disabled: 'disabled'
        };
      }
    },
    targetOrder: {
      type: String,
      default: 'original'
    }
  },

  data() {
    return {
      leftChecked: [],
      rightChecked: [],
      upDisabled: true,
      downDisabled: true
    };
  },

  computed: {
    dataObj() {
      const key = this.props.key;
      return this.data.reduce((o, cur) => (o[cur[key]] = cur) && o, {});
    },

    sourceData() {
      return this.data.filter(item => this.value.indexOf(item[this.props.key]) === -1);
    },

    targetData() {
      if (this.targetOrder === 'original') {
        // return this.data.filter(item => this.value.indexOf(item[this.props.key]) > -1);
        let arr = [];
        this.value.forEach(o => {
          arr.push(this.data.find(o2 => o2[this.props.key] === o));
        });
        return arr;
      } else {
        return this.value.reduce((arr, cur) => {
          const val = this.dataObj[cur];
          if (val) {
            arr.push(val);
          }
          return arr;
        }, []);
      }
    },

    hasButtonTexts() {
      return this.buttonTexts.length === 2;
    }
  },

  watch: {
    value(val) {
      this.dispatch('ElFormItem', 'el.form.change', val);
    }
  },

  methods: {
    getMigratingConfig() {
      return {
        props: {
          'footer-format': 'footer-format is renamed to format.'
        }
      };
    },

    onSourceCheckedChange(val, movedKeys) {
      this.leftChecked = val;
      this.upDisabled = true;
      this.downDisabled = true;
      if (movedKeys === undefined) return;
      this.$emit('left-check-change', val, movedKeys);
    },

    onTargetCheckedChange(val, movedKeys, currentItem) {
      this.rightChecked = val;
      if (currentItem != null) {
        let index = this.targetData.indexOf(currentItem);
        this.upDisabled = index === 0;
        this.downDisabled = index === this.targetData.length - 1;
      }
      if (movedKeys === undefined) return;
      this.$emit('right-check-change', val, movedKeys);
    },
    moveUp() {
      let currentItem = this.$refs.rightPanel.getCurrentItem();
      let oldIndex = this.value.indexOf(currentItem[this.props.key]);
      let newIndex = oldIndex - 1;
      this.value.splice(newIndex, 0, this.value.splice(oldIndex, 1)[0]);
      this.$emit('move', { oldIndex, newIndex, currentItem, type: 'up' });
    },
    moveDown() {
      let currentItem = this.$refs.rightPanel.getCurrentItem();
      let oldIndex = this.value.indexOf(currentItem[this.props.key]);
      let newIndex = oldIndex + 1;
      this.value.splice(newIndex, 0, this.value.splice(oldIndex, 1)[0]);
      this.$emit('move', { oldIndex, newIndex, currentItem, type: 'down' });
    },
    addToLeft() {
      let currentValue = this.value.slice();
      this.rightChecked.forEach(item => {
        const index = currentValue.indexOf(item);
        if (index > -1) {
          currentValue.splice(index, 1);
        }
      });
      this.$emit('input', currentValue);
      this.$emit('change', currentValue, 'left', this.rightChecked);
    },

    addToRight() {
      let currentValue = this.value.slice();
      const itemsToBeMoved = [];
      const key = this.props.key;
      this.data.forEach(item => {
        const itemKey = item[key];
        if (
          this.leftChecked.indexOf(itemKey) > -1 &&
          this.value.indexOf(itemKey) === -1
        ) {
          itemsToBeMoved.push(itemKey);
        }
      });
      currentValue = this.targetOrder === 'unshift'
        ? itemsToBeMoved.concat(currentValue)
        : currentValue.concat(itemsToBeMoved);
      this.$emit('input', currentValue);
      this.$emit('change', currentValue, 'right', this.leftChecked);
    },

    clearQuery(which) {
      if (which === 'left') {
        this.$refs.leftPanel.query = '';
      } else if (which === 'right') {
        this.$refs.rightPanel.query = '';
      }
    }
  }
};
</script>
