<template>
    <div class="para-transfer para-item" :class="{disabled:disabled1}" ref="transfer">
        <div class="transfer-box">
            <div class="transfer-left">

                <input-element :value="searchLeft" class="transfer-search" :placeholder="lang.placeholder"
                       size="small"/>

                <div class="transfer-list">
                    <template v-for="(item,i) in data1">
                        <div class="transfer-item noselect ellipsis"
                             v-if="item.hide"
                             :key="i"
                             @dblclick="leftClick($event, i, true)"
                             @click="leftClick($event, i)"
                             :class="getClass(item)"
                             :title="getDisplayName(item.data)">
                            {{getDisplayName(item.data)}}
                            <template v-if="setInfo && typeof setInfo === 'function'">
                                <Popover trigger="click">
                                    <div v-html="getInfo(item)"></div>
                                    <i class="el-icon-info transfer-info-btn" slot="reference"></i>
                                </Popover>
                            </template>
                        </div>
                    </template>
                </div>
                <div class="transfer-bottom-msg">未选择: {{data1.length}} / {{data1.length + value1.length}}</div>
            </div>
            <div class="transfer-button noselect">
                <div>
                    <div>
                        <!--<i class="el-icon-d-arrow-right" @click="change($event, 'allRight')"></i>
                        <i class="el-icon-arrow-right" @click="change($event, 'right')"></i>
                        <i class="el-icon-arrow-up" @click="change($event, 'up')" v-if="sort"></i>
                        <i class="el-icon-arrow-down" @click="change($event, 'down')" v-if="sort"></i>
                        <i class="el-icon-arrow-left" @click="change($event, 'left')"></i>
                        <i class="el-icon-d-arrow-left" @click="change($event, 'allLeft')"></i>-->
                        <Icon type="double-right" @click="change($event, 'allRight')"/>
                        <Icon type="right" @click="change($event, 'right')"/>
                        <Icon type="up" @click="change($event, 'up')" v-if="sort"/>
                        <Icon type="down" @click="change($event, 'down')" v-if="sort"/>
                        <Icon type="left" @click="change($event, 'left')"/>
                        <Icon type="double-left" @click="change($event, 'allLeft')"/>
                    </div>
                </div>
            </div>
            <div class="transfer-right">
                <Input class="transfer-search" v-model="searchRight" :placeholder="lang.placeholder"
                       size="small"/>
                <div class="transfer-list">
                    <template v-for="(item,i) in value1">
                        <div class="transfer-item noselect ellipsis"
                             v-if="item.hide"
                             :key="i"
                             @dblclick="rightClick($event, i, true)"
                             @click="rightClick($event, i)"
                             :class="getClass(item)">
                            {{getDisplayName(item.data)}}
                            <template v-if="setInfo && typeof setInfo === 'function'">
                                <Popover trigger="click">
                                    <div v-html="getInfo(item)"></div>
                                    <i class="el-icon-info transfer-info-btn" slot="reference"></i>
                                </Popover>
                            </template>
                        </div>
                    </template>
                </div>
                <div class="transfer-bottom-msg">已选择: {{value1.length}} / {{data1.length + value1.length}}</div>
            </div>
        </div>
    </div>
</template>

<script>
  import {Icon, Popover, Input} from 'ant-design-vue';
  import $ from 'jquery-slim';
  // import {$deepClone as $cloneJson,$pinyinFirst} from '../../../library/event';
  import {$pinyinFirst,$deepClone as $cloneJson} from '@chenxihub/sweet';
  const lang = {
    'placeholder': '请输入字母或拼音检索内容'
  };
  export default {
    name: 'para-transfer',
    components: {Icon, Popover, 'inputElement':Input},
    props: [
      'value', // 右侧已选择 []
      'data', // 左侧原选项 [{key,value}]
      'disabled', // 禁用
      'sortButton', // 是否启用排序按钮
      'labelKey', // 对象的显示字段名
      'valueKey', // 对象的值字段名
      'split', // value切割符
      'join',
      'setClass',
      'setInfo',
      'leftSearch',
      'filter',
      'rightSearch',
      'contentLang'
    ],
    data() {
      return {
        lang,
        value1: [],
        data1: [],
        disabled1: this.disabled || false,
        labelKey1: this.labelKey || 'key',
        valueKey1: this.valueKey || 'value',
        sort: this.sortButton || false,
        searchLeft: '',
        searchRight: ''
      };
    },
    mounted() {
      this.update();
      $(window).click(this.windowClick);
    },
    methods: {
      update() {
        let left = this.data || [];
        let right = this.value || [];
        if (typeof right === 'string' && typeof this.split === 'string') right = right.split(this.split);
        if ((!left || left.length === 0) && right instanceof Array) left = $cloneJson(right);
        if (typeof this.filter === 'function' && left instanceof Array) {
          left = left.filter(this.filter);
        }
        const data = [];
        const value = [];
        this.concat(left, right).forEach(
          (a, i) => {
            i = right instanceof Array ? right.indexOf(this.getValue(a)) : -1;
            if (i === -1) {
              // 左侧
              data.push(
                {
                  hide: true,
                  active: false,
                  pinyin: $pinyinFirst(this.getDisplayName(a)),
                  data: a
                }
              );
            } else {
              // 右侧
              value.push(
                {
                  hide: true,
                  active: false,
                  pinyin: $pinyinFirst(this.getDisplayName(a)),
                  data: a
                }
              );
            }
          }
        );
        this.data1 = data;
        this.value1 = value;
        this.setValue(this.value1);
      },
      concat(arr1, arr2) {
        arr2 = arr2.filter((a, i) => arr2.slice(0, i).indexOf(a) === -1);
        return arr1.filter((a) => {
          const i = arr2.indexOf(typeof a === 'object' ? a[this.valueKey1] : a);
          if (i > -1) arr2[i] = a;
          return i === -1;
        }).concat(arr2);
      },
      getClass(item) {
        const c = {active: item.active};
        if (typeof this.setClass === 'function') {
          const sc = this.setClass(item.data);
          if (sc && sc instanceof Array && sc.length > 0) {
            for (let i = 0, l = sc.length; i < l; i++) {
              c[sc[i]] = true;
            }
          }
        }
        return c;
      },
      getInfo(item) {
        return this.setInfo(item.data);
      },
      getDisplayName(item) {
        let name = '';
        if (typeof item === 'string') name = item;
        else if (typeof this.labelKey1 === 'function') name = this.labelKey1(item);
        else name = item[this.labelKey1] || item.label;
        if (!name) name = item[this.valueKey1];
        if (this.contentLang && this.contentLang[name]) return this.contentLang[name];
        return name;
      },
      getValue(item) {
        if (typeof item === 'string') return item;
        return item[this.valueKey1];
      },
      change(e, type) {
        if (this.disabled1) return;
        switch (type) {
          case 'allRight':
            this.AtoB('data1', 'value1', true);
            this.fromBottom('.transfer-right .transfer-list');
            break;
          case 'right':
            this.AtoB('data1', 'value1');
            this.fromBottom('.transfer-right .transfer-list');
            break;
          case 'up':
            this.itemUpAndDown('data1', type);
            this.itemUpAndDown('value1', type);
            break;
          case 'down':
            this.itemUpAndDown('data1', type);
            this.itemUpAndDown('value1', type);
            break;
          case 'left':
            this.AtoB('value1', 'data1');
            this.fromBottom('.transfer-left .transfer-list');
            break;
          case 'allLeft':
            this.AtoB('value1', 'data1', true);
            this.fromBottom('.transfer-left .transfer-list');
            break;
          default:
            break;
        }
      },
      setValue(data) {
        let value = [];
        data.forEach(
          (a) => {
            value.push(this.getValue(a.data));
          }
        );
        this.lock = true;
        if (typeof this.join === 'string') value = value.join(this.join);
        this.$emit('input', value);
      },
      leftClick(e, i, dblclick) {
        if (this.disabled1) return;
        this.data1 = this.setActive(this.data1, i, e, dblclick);
        if (dblclick === true) this.change(e, 'right');
      },
      rightClick(e, i, dblclick) {
        if (this.disabled1) return;
        this.value1 = this.setActive(this.value1, i, e, dblclick);
        if (dblclick === true) this.change(e, 'left');
      },
      setActive(data, i, e, dblclick) {
        if (this.disabled1 && e) return;
        data = $cloneJson(data);
        for (const c in data) {
          if (Number(c) === Number(i)) data[c].active = dblclick === true ? true : !data[c].active;
          else if (i === -1 || (e && !e.ctrlKey)) data[c].active = false;
        }
        return data;
      },
      windowClick(e) {
        if (this.disabled1) return;
        if ($(e.target).closest('.transfer-Button').length > 0) return;
        if ($(e.target).closest(this.$refs.transfer).length === 0) return this.clearChecked('all');
        const left = $(e.target).closest('.transfer-left').length;
        const right = $(e.target).closest('.transfer-right').length;
        if (left === 0) this.clearChecked('left');
        if (right === 0) this.clearChecked('right');
      },
      clearChecked(type) {
        if (type === 'left' || type === 'all') this.data1 = this.setActive(this.data1, -1);
        if (type === 'right' || type === 'all') this.value1 = this.setActive(this.value1, -1);
      },
      AtoB(a, b, all) {
        if (this.disabled1) return;
        const value = $cloneJson(this[b]);
        const data = $cloneJson(this[a]).filter(
          (a) => {
            const active = typeof all === 'boolean' ? all : a.active;
            if (active) {
              // a.active = false;
              value.push(a);
            }
            return !active;
          }
        );
        this[a] = data;
        this[b] = value;
        if (a === 'value1') this.setValue(data);
        if (a === 'data1') this.setValue(value);
      },
      search(name, val) {
        for (const i in this[name]) {
          let b = this.getDisplayName(this[name][i].data).indexOf(val) !== -1;
          if (b === false) b = this[name][i].pinyin.indexOf(val.toUpperCase()) !== -1;
          this[name][i].hide = b;
        }
      },
      itemUpAndDown(name, type) {
        let data = $cloneJson(this[name]);
        let newData = [];
        if (type === 'down') data = data.reverse();
        data.forEach(
          (a) => {
            const last = newData.length - 1;
            if (a.active && newData[last] && !newData[last].active) {
              newData.splice(last, 0, a);
            } else {
              newData.push(a);
            }
          }
        );
        if (type === 'down') newData = newData.reverse();
        this[name] = newData;
        if (name === 'value1') this.setValue(newData);
      },
      fromBottom(list) {
        setTimeout(
          () => {
            let H = 0;
            $(this.$refs.transfer).find(list).children().each(
              function () {
                H += $(this).outerHeight();
              }
            );
            $(this.$refs.transfer).find(list).scrollTop(H);
          }
        );
      }
    },
    watch: {
      data(val, old) {
        if (val === old) return;
        this.update();
      },
      value(val, old) {
        if (val === old || this.lock) return this.lock = false;
        this.update();
      },
      disabled(val) {
        if (typeof val !== 'boolean') return console.warn('para-transfer disabled is boolean');
        this.disabled1 = val;
        if (!val) {
          this.setActive(this.data1, -1);
          this.setActive(this.value1, -1);
        }
      },
      labelKey(val) {
        if (typeof val !== 'string') return console.warn('para-transfer data-key is string');
        this.update();
      },
      valueKey(val) {
        if (typeof val !== 'boolean') return console.warn('para-transfer value-key is string');
        this.update();
      },
      /* 搜索监听 */
      searchLeft(val) {
        this.search('data1', val);
      },
      searchRight(val) {
        this.search('value1', val);
      },
      leftSearch(val) {
        this.searchLeft = val;
      },
      rightSearch(val) {
        this.searchRight = val;
      }
    }
  };
</script>
