<style lang="scss">
.z-schema-transfer {
  display: flex;
  justify-content: space-between;
  box-sizing: border-box;
  &__left,
  &__right {
    width: 50%;
    flex: 1;
    border: 1px solid #ebeef5;
  }
  &__left {
    border-right: 0;
  }
  &__header {
    display: flex;
    background: #f5f7fa;
    padding: 8px 10px;
    font-size: 14px;
  }
  &__content {
    padding: 10px;
  }
}
</style>

<template>
  <div class="z-schema-transfer">
    <div class="z-schema-transfer__left">
      <div class="z-schema-transfer__header">
        <div class="z-schema-transfer__title">
          <slot name="title-left">{{ titles[0] }}</slot>
        </div>
      </div>
      <div class="z-schema-transfer__content">
        <slot :onChoose="onChoose" :valueFormatter="valueFormatter">
          <z-schema-page
            :size="transferSize"
            :value-filter="valueFilter"
            :value-table="valueTable"
            :schema="schemaLeft"
            :api-search="searchMethod"
            @update:value-filter="e => $emit('update:value-filter', e)"
            :auto="auto"
          >
            <template #operation>
              <el-table-column label="操作" width="80" align="center" fixed="right">
                <template #default="{ row, $index }">
                  <div class="z-schema-page__table-operation">
                    <el-button type="text" :disabled="_rowDisabled(row, $index)" @click="onChoose(row)">选择</el-button>
                  </div>
                </template>
              </el-table-column>
            </template>
          </z-schema-page>
        </slot>
      </div>
    </div>
    <div class="z-schema-transfer__right">
      <div class="z-schema-transfer__header">
        <div class="z-schema-transfer__title">
          <slot name="title-right">{{ titles[1] }}</slot>
        </div>
      </div>
      <div class="z-schema-transfer__content">
        <slot name="selected" :onRemove="onRemove">
          <z-schema-table :size="transferSize" :value="value" :schema="schemaRight" @input="onInput">
            <el-table-column label="操作" width="80" align="center" fixed="right">
              <template #default="{ row, $index }">
                <div class="z-schema-page__table-operation">
                  <el-button type="text" :disabled="_rowDisabled(row, $index)" @click="onRemove(row, $index)">移除</el-button>
                </div>
              </template>
            </el-table-column>
          </z-schema-table>
        </slot>
      </div>
    </div>
  </div>
</template>

<script>
import { cloneDeep, get } from '../utils';

export default {
  name: 'SchemaTransfer',
  props: {
    value: {
      type: Array,
      default() {
        return [];
      },
    },
    schema: {
      required: true,
      type: Object,
      default() {
        return {};
      },
    },
    titles: {
      type: Array,
      default() {
        return ['未选中', '已选中'];
      },
    },
    source: Array,
    valueKey: {
      type: String,
      default: 'id',
    },
    size: String,
    disabled: Boolean,
    auto: Boolean,
    rowDisabled: Function,
    apiSearch: Function,
    valueFilter: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  inject: {
    elForm: {
      default: undefined,
    },
    elFormItem: {
      default: undefined,
    },
  },
  data() {
    return {
      dataSource: this.source || [],
    };
  },
  watch: {
    source(val) {
      this.dataSource = val || [];
    },
  },
  computed: {
    _elFormItemSize() {
      return (this.elFormItem || {}).elFormItemSize;
    },
    transferSize() {
      return this.size || this._elFormItemSize || (this.elForm || {}).size || (this.$ELEMENT || {}).size;
    },
    transferDisabled() {
      return this.disabled || (this.elForm || {}).disabled;
    },
    schemaFilter() {
      return this.schema.filter || {};
    },
    schemaLeft() {
      return {
        ...this.schema,
        selection: false,
        action: false,
        filter: this.schema.filter
          ? {
              props: {
                span: 12,
                ...(this.schemaFilter.props || {}),
              },
              ...this.schemaFilter,
            }
          : false,
        pagination: !this.apiSearch ? false : get(this.schema, 'pagination'),
      };
    },
    schemaRight() {
      if (this.schema.selected) {
        return this.schema.selected;
      }
      return {
        props: {
          border: true,
          'highlight-current-row': true,
          ...(get(this.schema, 'table.props') || {}),
        },
        ...this.schema.table,
      };
    },
    valueKeys() {
      return this.value.map(item => item[this.valueKey]);
    },
    valueTable() {
      return this.valueFormatter(this.dataSource || []);
    },
  },
  methods: {
    _rowDisabled(row, index) {
      if (this.transferDisabled) {
        return true;
      }
      if (this.rowDisabled) {
        return this.rowDisabled({ row, index });
      }
      return false;
    },
    valueFormatter(value) {
      return value.filter(item => !this.valueKeys.includes(item[this.valueKey]));
    },
    onChoose(row) {
      this.$emit('input', [...this.value, row]);
    },
    onRemove(row, index) {
      const newValue = cloneDeep(this.value || []);
      newValue.splice(index, 1);
      this.$emit('input', newValue);
    },
    onInput(value) {
      this.$emit('input', value);
    },
    searchMethod(e) {
      if (this.apiSearch) {
        return this.apiSearch(e).then(result => {
          this.dataSource = result[0] || [];
          return [this.valueTable, result[1]];
        });
      }
      return new Promise(resolve => {
        resolve([]);
      });
    },
  },
};
</script>
