<template>
  <div
    class="org-select el-select major-select el-select--small"
    @click="switchOpen"
  >
    <div v-if="multiple" class="el-select__tags">
      <el-tag
        v-for="item in selectedList"
        :key="item.id"
        @close="deleteTag($event, item)"
        >{{ item.name }}</el-tag
      >
    </div>
    <div
      :class="[
        'el-input el-input--small el-input--suffix',
        { 'is-focus': isFocus }
      ]"
      @mouseenter="inputHovering = true"
      @mouseleave="inputHovering = false"
    >
      <input
        ref="inputRef"
        type="text"
        autocomplete="off"
        :placeholder="placeholder"
        class="el-input__inner"
        :value="selectedOrg.name"
        readonly
      />
      <span class="el-input__suffix">
        <span class="el-input__suffix-inner">
          <i
            v-show="!showClose"
            :class="[
              'el-select__caret',
              'el-input__icon',
              'el-icon-arrow-up',
              { 'is-reverse': visible }
            ]"
          ></i>
          <i
            v-if="showClose"
            class="el-select__caret el-input__icon el-icon-circle-close"
            @click="handleClearClick"
          ></i>
        </span>
      </span>
    </div>

    <el-popover
      popper-class="org-popover"
      placement="bottom-start"
      trigger="manual"
      v-model="visible"
    >
      <div ref="popoverRef" slot="reference"></div>
      <div class="org-popover-tree" v-clickoutside="handleClose">
        <el-tree
          ref="OrgTree"
          :data="orgs"
          default-expand-all
          node-key="id"
          :props="defaultProps"
          check-on-click-node
          :expand-on-click-node="false"
          @node-click="nodeClick"
        >
          <span
            :class="['custom-tree-node', { 'is-select': checkSelected(data) }]"
            slot-scope="{ node, data }"
          >
            <span>{{ node.label }}</span>
            <span>
              <i class="el-icon-check"></i>
            </span>
          </span>
        </el-tree>
      </div>
    </el-popover>
  </div>
</template>

<script>
import { organizationList } from "../../modules/base/api";
import Clickoutside from "element-ui/src/utils/clickoutside";

export default {
  name: "org-select",
  props: {
    value: {
      type: [Array, String]
    },
    placeholder: { type: String, default: "请选择" },
    multiple: {
      type: Boolean,
      default: false
    },
    disabled: {
      type: Boolean,
      default: false
    },
    clearable: {
      type: Boolean,
      default: true
    }
  },
  directives: { Clickoutside },
  data() {
    return {
      selectedOrg: {},
      selectedOrgList: [],
      selectedOrgIds: [],
      visible: false,
      isFocus: false,
      inputHovering: false,
      orgs: [],
      defaultProps: {
        label: "name"
      }
    };
  },
  computed: {
    showClose() {
      let hasValue = this.multiple
        ? Array.isArray(this.value) && this.value.length > 0
        : this.value !== undefined && this.value !== null && this.value !== "";
      let criteria = this.clearable && this.inputHovering && hasValue;
      return criteria;
    }
  },
  watch: {
    value(val, oldval) {
      if (val !== oldval) this.initSelected(val);
    }
  },
  mounted() {
    this.getList();
  },
  methods: {
    async getList() {
      const orgs = await organizationList();
      this.orgs = orgs || [];

      if (this.orgs.length) {
        this.orgs[0].children.sort((a, b) => {
          if (a.type === "PRINTING_HOUSE") return 1;
          if (b.type === "PRINTING_HOUSE") return -1;

          return 0;
        });
      }
      if (this.value) this.initSelected(this.value);
    },
    switchOpen() {
      if (this.visible) {
        this.handleClose();
      } else {
        this.handleOpen();
      }
    },
    handleOpen() {
      this.isFocus = true;
      setTimeout(() => {
        this.visible = true;
      }, 200);
    },
    handleClose() {
      this.visible = false;
      this.isFocus = false;
    },
    getSelectedData(selectedIds) {
      let selectedData = [];
      if (!selectedIds.length) return [];

      const findTree = list => {
        list.forEach(item => {
          if (selectedIds.includes(item.id)) {
            selectedData.push({ ...item });
          }
          if (item.children && item.children.length) {
            findTree(item.children);
          }
        });
      };

      findTree(this.orgs);

      return selectedData;
    },
    initSelected(val) {
      if (!this.orgs.length) return;
      if (this.multiple) {
        const selectedIds = val || [];
        const selectedData = this.getSelectedData(selectedIds);
        this.selectedOrg = {};
        this.selectedOrgList = selectedData;
      } else {
        const selectedIds = val ? [val] : [];
        const selectedData = this.getSelectedData(selectedIds);
        if (selectedData.length) {
          this.selectedOrg = { ...selectedData[0] };
          this.selectedOrgList = selectedData;
        } else {
          this.selectedOrg = {};
          this.selectedOrgList = [];
        }
      }
      this.updateSelectOrgIds();
      this.emitChange();
    },
    nodeClick(data) {
      if (!this.multiple) {
        this.selectedOrg = { ...data };
        this.selectedOrgList = [{ ...data }];
        this.updateSelectOrgIds();
        this.visible = false;
        this.emitChange();
        return;
      }

      if (this.selectedOrgIds.includes(data.id)) {
        this.selectedOrgList = this.selectedOrgList.filter(
          item => item.id !== data.id
        );
      } else {
        this.selectedOrgList.push({ ...data });
      }
      this.updateSelectOrgIds();
      this.emitChange();
    },
    updateSelectOrgIds() {
      this.selectedOrgIds = this.selectedOrgList.map(item => item.id);
    },
    checkSelected(data) {
      return this.selectedOrgIds.includes(data.id);
    },
    deleteTag(event, data) {
      if (this.selectedOrgIds.includes(data.id)) {
        this.selectedOrgList = this.selectedOrgList.filter(
          item => item.id !== data.id
        );
        this.updateSelectOrgIds();
        this.emitChange();
      }
      event.stopPropagation();
    },
    handleClearClick(event) {
      event.stopPropagation();
      this.selectedOrgList = [];
      this.selectedOrg = {};
      this.updateSelectOrgIds();
      this.emitChange();
      this.handleClose();
    },
    emitChange() {
      this.$emit(
        "input",
        this.multiple ? this.selectedOrgIds : this.selectedOrgIds[0]
      );
      this.$emit(
        "change",
        this.multiple ? this.selectedOrgList : this.selectedOrgList[0]
      );
    }
  }
};
</script>

<style lang="scss">
.org-select {
  width: 220px;
}
.org-popover {
  &.el-popover {
    width: 300px;
    padding: 0;
  }

  &-tree {
    max-height: 300px;
    overflow: auto;
    padding: 5px 0;
  }

  .custom-tree-node {
    .el-icon-check {
      display: none;
    }

    &.is-select {
      color: #3a5ae5;
      .el-icon-check {
        display: block;
      }
    }
  }
}
</style>
