<template>
  <div class="mm-transfer">
    <ui-transfer-panel
      v-model="leftChecked"
      :title="titles[0]"
      :filterable="filterable"
      :filter-placeholder="filterPlaceholder"
      :filter-method="filterMethod"
      :format="format"
      :list="leftList">
      <slot name="left-footer"></slot>
    </ui-transfer-panel>
    <div class="mm-transfer-buttons">
      <ui-button
        :disabled="!rightChecked.length"
        icon="chevronleft"
        @click.native="transfer('right')">
        <span v-if="buttonTexts[0]">
          {{ buttonTexts[0] }}
        </span>
      </ui-button>
      <ui-button
        :disabled="!leftChecked.length"
        icon="chevronright"
        @click.native="transfer('left')">
        <span v-if="buttonTexts[1]">
          {{ buttonTexts[1] }}
        </span>
      </ui-button>
    </div>
    <ui-transfer-panel
      v-model="rightChecked"
      :title="titles[1]"
      :filterable="filterable"
      :filter-placeholder="filterPlaceholder"
      :filter-method="filterMethod"
      :format="format"
      :list="rightList">
      <slot name="right-footer"></slot>
    </ui-transfer-panel>
  </div>
</template>

<script>
import { t } from "../../locale"
import TransferPanel from "./transfer-panel"
import Button from "../button"

import config from "../../managers/config"

config.defaults({
  "Transfer.filterable": false,
  "Transfer.targetOrder": "original",
  "Transfer.keymap": () => ({
    key: "key",
    label: "label",
    disabled: "disabled",
  }),
})

export default {
  name: "mm-transfer",
  components: {
    "ui-button": Button,
    "ui-transfer-panel": TransferPanel,
  },
  props: {
    value: {
      type: Array,
      default: () => [],
    },
    data: Array,
    filterable: {
      type: Boolean,
      default: () => config.get("Transfer.filterable"),
    },
    filterPlaceholder: {
      type: String,
      default: t("ui.transfer.filterPlaceholder"),
    },
    filterMethod: Function,
    targetOrder: {
      type: String,
      default: () => config.get("Transfer.targetOrder"),
      validator(val) {
        return ["original", "push", "unshift"].includes(val)
      },
    },
    titles: {
      type: Array,
      default: () => t("ui.transfer.titles"),
    },
    buttonTexts: {
      type: Array,
      default: () => [],
    },
    renderContent: Function,
    format: {
      type: Object,
      default: () => ({
        noChecked: "{checked}/{total}",
        hasChecked: "{checked}/{total}",
      }),
    },
    keymap: {
      type: Object,
      default() {
        return config.get("Transfer.keymap").call(this)
      },
    },
    leftDefaultChecked: {
      type: Array,
      default: () => [],
    },
    rightDefaultChecked: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      localData: [],
      localValue: [],
      leftChecked: this.leftDefaultChecked,
      rightChecked: this.rightDefaultChecked,
    }
  },
  computed: {
    key() {
      return this.keymap.key || "key"
    },
    label() {
      return this.keymap.label || "label"
    },
    disabled() {
      return this.keymap.disabled || "disabled"
    },
    leftList() {
      return this.localData.filter(item => !this.localValue.includes(item.key))
    },
    rightList() {
      const list = this.localData.filter(item => this.localValue.includes(item.key))
      const tempObject = {}
      list.forEach(item => {
        tempObject[item.key] = item
      })

      return this.localValue.map(item => tempObject[item])
    },
  },
  watch: {
    value: {
      immediate: true,
      handler(val) {
        this.localValue = val
      },
    },
    localValue(val) {
      this.$emit("input", val)
    },
    data: {
      immediate: true,
      handler() {
        const key = this.key
        const label = this.label
        const disabled = this.disabled

        this.localData = this.data.map(item => ({
          ...item,
          key: item[key],
          label: item[label],
          disabled: item[disabled],
        }))
      },
    },
  },
  methods: {
    transfer(type) {
      const checked = this[`${type}Checked`]
      if (!checked.length) {
        return
      }
      const order = this.targetOrder
      // 保留数据源的顺序
      const checkedList = this.localData
        .filter(item => checked.includes(item.key))
        .map(item => item.key)
      let temp

      if (type === "left") {
        switch (order) {
          case "unshift":
            this.localValue = [...checkedList, ...this.localValue]
            break
          case "push":
            this.localValue = [...this.localValue, ...checkedList]
            break
          default:
            temp = [...checkedList, ...this.localValue]
            this.localValue = this.localData
              .filter(item => temp.includes(item.key))
              .map(item => item.key)
        }
      }

      if (type === "right") {
        this.localValue = this.localValue.filter(value => !checkedList.includes(value))
      }

      this[`${type}Checked`] = []
    },
  },
}
</script>
