<template>
  <div
    class="hn-easy-tree"
    :class="{
      'hn-easy-tree--highlight-current': highlightCurrent,
    }"
    role="tree"
  >
    <hn-tree-node
      v-for="child in root.childNodes"
      :key="getNodeKey(child)"
      :node="child"
      :props="props"
      :render-after-expand="renderAfterExpand"
      :render-content="renderContent"
      :show-branch="showBranch"
      @node-expand="handleNodeExpand">
    </hn-tree-node>
    <div class="hn-easy-tree__empty-block" v-if="isEmpty">
      <span class="hn-easy-tree__empty-text">{{ emptyText }}</span>
    </div>
  </div>
</template>

<script>
  import emitter from 'heiner-ui/src/mixins/emitter';
  import {t} from 'heiner-ui/src/locale';
  import HnTreeNode from './tree-node.vue';
  import TreeStore from './model/tree-store';
  import { getNodeKey } from './model/util';

  export default {
    name: 'HnEasyTree',

    mixins: [emitter],

    components: {
      HnTreeNode
    },

    data() {
      return {
        store: null,
        root: null,
        currentNode: null,
        treeItems: null
      };
    },

    props: {
      data: {
        type: Array
      },
      emptyText: {
        type: String,
        default() {
          return t('hn.easyTree.emptyText');
        }
      },
      renderAfterExpand: {
        type: Boolean,
        default: true
      },
      nodeKey: String,
      defaultExpandAll: Boolean,
      expandOnClickNode: {
        type: Boolean,
        default: true
      },
      currentNodeKey: [String, Number],
      renderContent: Function,
      props: {
        default() {
          return {
            children: 'children',
            label: 'label',
            disabled: 'disabled'
          };
        }
      },
      highlightCurrent: {
        type: Boolean,
        default: true
      },
      accordion: Boolean,
      indent: {
        type: Number,
        default: 26
      },
      iconClass: String,
      showBranch: {
        type: Boolean,
        default: true
      }
    },

    computed: {
      children: {
        set(value) {
          this.data = value;
        },
        get() {
          return this.data;
        }
      },

      treeItemArray() {
        return Array.prototype.slice.call(this.treeItems);
      },

      isEmpty() {
        const { childNodes } = this.root;
        return !childNodes || childNodes.length === 0;
      }
    },

    watch: {
      data(newVal) {
        this.store.setData(newVal);
      }
    },

    methods: {
      getNodeKey(node) {
        return getNodeKey(this.nodeKey, node.data);
      },

      getCurrentNode() {
        const currentNode = this.store.getCurrentNode();
        return currentNode ? currentNode.data : null;
      },

      getCurrentKey() {
        if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in getCurrentKey');
        const currentNode = this.getCurrentNode();
        return currentNode ? currentNode[this.nodeKey] : null;
      },

      setCurrentNode(node) {
        if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCurrentNode');
        this.store.setUserCurrentNode(node);
      },

      setCurrentKey(key) {
        if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCurrentKey');
        this.store.setCurrentNodeKey(key);
      },

      getNode(data) {
        return this.store.getNode(data);
      },

      remove(data) {
        this.store.remove(data);
      },

      append(data, parentNode) {
        this.store.append(data, parentNode);
      },

      handleNodeExpand(nodeData, node, instance) {
        this.broadcast('HnTreeNode', 'tree-node-expand', node);
        this.$emit('node-expand', nodeData, node, instance);
      },

      handleKeydown(ev) {
        const currentItem = ev.target;
        if (currentItem.className.indexOf('hn-easy-tree-node') === -1) return;
        const keyCode = ev.keyCode;
        this.treeItems = this.$el.querySelectorAll('.hn-easy-tree-node[role=treeitem]');
        const currentIndex = this.treeItemArray.indexOf(currentItem);
        let nextIndex;
        if ([38, 40].indexOf(keyCode) > -1) { // up、down
          ev.preventDefault();
          if (keyCode === 38) { // up
            nextIndex = currentIndex !== 0 ? currentIndex - 1 : 0;
          } else {
            nextIndex = (currentIndex < this.treeItemArray.length - 1) ? currentIndex + 1 : 0;
          }
          this.treeItemArray[nextIndex].focus(); // 选中
        }
        if ([37, 39].indexOf(keyCode) > -1) { // left、right 展开
          ev.preventDefault();
          currentItem.click(); // 选中
        }
      }
    },

    created() {
      this.isTree = true;

      this.store = new TreeStore({
        key: this.nodeKey,
        data: this.data,
        props: this.props,
        currentNodeKey: this.currentNodeKey,
        defaultExpandAll: this.defaultExpandAll,
        showBranch: this.showBranch
      });

      this.root = this.store.root;
    },

    mounted() {
      this.$el.addEventListener('keydown', this.handleKeydown);
    },

    updated() {
      this.treeItems = this.$el.querySelectorAll('[role=treeitem]');
    }
  };
</script>

