<template>
  <div class="mm-transfer-panel">
    <div class="mm-transfer-panel-title">
      <ui-checkbox
        v-model="checkAll"
        :indeterminate="indeterminate"
        :label="title"
        @change="checkAllHandler"></ui-checkbox>
      <span class="mm-transfer-panel-status">
        {{ status }}
      </span>
    </div>
    <div
      v-if="filterable"
      class="mm-transfer-panel-search">
      <ui-input
        v-model="keyword"
        :placeholder="filterPlaceholder"
        prefix-icon="search"></ui-input>
    </div>
    <ul class="mm-transfer-panel-list">
      <li
        v-for="item of localData"
        :key="item.key"
        class="mm-transfer-panel-item">
        <ui-checkbox
          v-model="checkedList"
          :value="item.key"
          :disabled="item.disabled">
          <ui-label :option="item"></ui-label>
        </ui-checkbox>
      </li>
      <li
        v-if="!localData.length"
        class="mm-empty-no-data">
        <ui-empty
          type="small"
          :desc="keyword.length ? t('ui.transfer.noMatch') : t('ui.transfer.noData')">
        </ui-empty>
      </li>
    </ul>
    <div
      v-if="$slots.default"
      class="mm-transfer-panel-footer">
      <slot></slot>
    </div>
  </div>
</template>

<script>
import { encode } from "../../utils/reg"
import locale from "../../mixins/locale"
import Checkbox from "../checkbox"
import Input from "../input"
import Empty from "../empty"

export default {
  name: "mm-transfer-panel",
  components: {
    "ui-empty": Empty,
    "ui-checkbox": Checkbox,
    "ui-input": Input,
    "ui-label": {
      props: {
        option: Object,
      },
      render(h) {
        const getTransfer = vm => {
          if (vm.$options.name === "mm-transfer") {
            return vm
          } else if (vm.$parent) {
            return getTransfer(vm.$parent)
          } else {
            return vm
          }
        }

        const transfer = getTransfer(this)
        return transfer.renderContent ? (
          transfer.renderContent(h, this.option)
        ) : transfer.$scopedSlots.default ? (
          transfer.$scopedSlots.default({ option: this.option })
        ) : (
          <span>{this.option.label}</span>
        )
      },
    },
  },
  mixins: [locale],
  props: {
    title: String,
    value: Array,
    list: Array,
    filterable: Boolean,
    filterPlaceholder: String,
    filterMethod: Function,
    format: Object,
  },
  data() {
    return {
      keyword: "",
      checkedList: [],
      localData: [],
    }
  },
  computed: {
    validData() {
      return this.list.filter(item => !item.disabled)
    },
    checkAll: {
      set(val) {
        if (val) {
          this.checkedList = this.validData.map(item => item.key)
        }
      },
      get() {
        return this.value.length && this.value.length === this.validData.length
      },
    },
    indeterminate() {
      return this.value.length < this.validData.length && this.value.length > 0
    },
    status() {
      const template = this.value.length
        ? this.format.hasChecked
        : this.format.noChecked
      return template
        .replace(/{checked}/, this.value.length)
        .replace(/{total}/, this.list.length)
    },
  },
  watch: {
    value: {
      immediate: true,
      handler(val) {
        this.checkedList = val
      },
    },
    list: {
      immediate: true,
      handler(val) {
        this.localData = val
      },
    },
    keyword(val) {
      const keyword = val.trim()

      if (!keyword) {
        this.localData = this.list
        return
      }

      if (this.filterMethod) {
        this.localData = this.list.filter(item =>
          this.filterMethod(keyword, item)
        )
        return
      }

      const reg = new RegExp(encode(this.keyword), "i")
      this.localData = this.list.filter(
        item => reg.test(item.label) || reg.test(item.key)
      )
    },
    checkedList(val) {
      this.$emit("input", val)
    },
  },
  methods: {
    checkAllHandler(event, val) {
      if (!val) {
        this.checkedList = []
      }
    },
  },
}
</script>
