<template>
  <div class="uif-tree-item">
    <div class="uif-tree-data" :class="classes" :style="styles" @click="onTreeClick">
      <div class="uif-tree-data-left" v-if="mode !== 'simple'">
        <u-icon v-if="loading" class="loading" type="loading"></u-icon>
        <u-icon v-else class="expand" type="chevron-right" scene="action" :disabled="noData" @click="onHandleClick"></u-icon>
      </div>
      <div class="uif-tree-data-label" @click="onClick">
        <base-slot v-if="slotFunction" :slot-function="slotFunction" :params="data"></base-slot>
        <span v-else-if="labelKey">{{data[labelKey]}}</span>
      </div>
    </div>
    <u-slide-down :value="isExpand">
      <template v-for="(item, i) in children">
        <u-tree-item :key="i" v-bind="$props" :data="item" :level="level + 1" v-on="$listeners"></u-tree-item>
      </template>
    </u-slide-down>
  </div>
</template>

<script>
import USlideDown from '@uif/hq/lib/components/slide-down'
import BaseSlot from '@uif/hq/lib/components/base-slot'
import UIcon from '@uif/hq/lib/components/icon'
import {px, oneOf} from '@uif/hq/lib/utils/assist'
import {toNumber} from '@uif/hq/lib/utils/format'
import {isArray} from '@uif/hq/lib/utils/array'

export default {
  name: 'u-tree-item',
  components: {
    UIcon,
    BaseSlot,
    USlideDown
  },
  props: {
    mode: {
      validator (value) {
        return oneOf(value, ['handle', 'simple', 'full'])
      },
      default: 'handle'
    },
    // 节点数据
    data: {
      type: Object,
      default: null
    },
    // 文本Key
    labelKey: {
      type: String,
      default: 'label'
    },
    // 唯一标识，用于model
    idKey: {
      type: String,
      default: 'value'
    },
    // 子节点Key
    childrenKey: {
      type: String,
      default: 'children'
    },
    // 选中节点数据
    active: {
      default: null
    },
    // 自定义slot
    slotFunction: {
      type: Function,
      default: null
    },
    // 异步加载数据
    getDataList: {
      type: Function,
      default: null
    },
    // 层级
    level: {
      type: Number,
      default: 0
    },
    // 层级递推
    levelSize: {
      type: [Number, String],
      default: 10
    }
  },
  data () {
    return {
      loading: false
    }
  },
  computed: {
    styles () {
      return {
        paddingLeft: px(this.level * toNumber(this.levelSize))
      }
    },
    classes () {
      const id = this.idKey ? this.data[this.idKey] : null
      return [
        {
          'data-expand': this.isExpand,
          'data-active': this.active && this.active === id
        }
      ]
    },
    // 子节点
    children () {
      return this.data[this.childrenKey] || []
    },
    // 无数据
    noData () {
      return this.getDataList ? this.data._noData : this.children.length <= 0
    },
    // 展开
    isExpand () {
      return !!this.data._expand
    },
    // 需要异步加载
    needLoadDataList () {
      return this.getDataList && !this.data._noData && this.children.length <= 0
    }
  },
  created () {
  },
  mounted () {
  },
  methods: {
    onHandleClick () {
      if (this.mode === 'handle') {
        this.onExpandChange()
      }
    },
    onTreeClick () {
      if (this.mode !== 'handle') {
        this.onExpandChange()
      }
    },
    onExpandChange () {
      if (this.data.disabled || this.noData) {
        return false
      }
      if (!this.isExpand && this.needLoadDataList) {
        // 展开，需要异步加载
        this.loading = true
        this.getDataList(this.data, this.getDataNext)
      } else {
        this.changeExpand(!this.isExpand)
      }
    },
    // 获取数据回调函数
    getDataNext (children) {
      this.loading = false
      if (isArray(children) && children.length) {
        this.$set(this.data, this.childrenKey, children)
        this.$nextTick(() => this.changeExpand(true))
      } else {
        this.$set(this.data, '_noData', true)
      }
    },
    // 点击事件
    onClick () {
      if (this.data.disabled) return false
      this.$emit('click', this.data)
      this.setActive()
    },
    // 展开收起
    changeExpand (value) {
      this.$set(this.data, '_expand', value)
    },
    // 设置选中
    setActive () {
      if (this.idKey in this.data) {
        this.$emit('select', this.data[this.idKey])
      }
    }
  }
}
</script>
