<template>
  <div class="uif-tree-item" v-if="data">
    <div class="uif-tree-line" :class="classes" :style="styles" @click="onLineClick">
      <div class="uif-tree-line-icon">
        <u-icon v-if="loading" class="loading" type="circle-rotate" scene="action"></u-icon>
        <u-icon v-else-if="children.length || needAsyncLoad" class="expand" type="chevron-right" scene="action"
              @click.stop="onChangeExpand"></u-icon>
      </div>
      <div v-if="data[labelKey]" class="uif-tree-line-label" @click="onLabelClick">{{data[labelKey]}}</div>
      <base-slot slot-name="tree-item" :params="data"></base-slot>
    </div>
    <u-slide-down :value="isExpand" v-if="children.length">
      <template v-for="(child, i) in children">
        <u-tree-item :key="i" v-bind="$props" :data="child" :index="index + 1" v-on="$listeners"></u-tree-item>
      </template>
    </u-slide-down>
  </div>
</template>

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

export default {
  name: 'u-tree-item',
  components: {
    UIcon,
    BaseSlot,
    USlideDown
  },
  props: {
    // 节点数据
    data: {
      type: Object,
      default () {
        return {}
      }
    },
    // 子节点Key
    childrenKey: {
      type: String,
      default: 'children'
    },
    // 选中节点数据
    active: {
      default: null
    },
    // 唯一标识，用于model
    idKey: {
      type: String,
      default: ''
    },
    // 文本Key
    labelKey: {
      type: String,
      default: 'label'
    },
    // 异步加载数据
    getDataList: {
      type: Function,
      default: null
    },
    // 层级
    index: {
      type: Number,
      default: 0
    },
    // 层级递推宽度
    ladder: {
      type: [Number, String],
      default: 10
    },
    // 点击整行展开
    lineExpand: {
      type: Boolean,
      default: true
    },
    // 异步加载
    asyncLoad: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      loading: false,
      noData: false
    }
  },
  computed: {
    // 展开
    isExpand () {
      return this.data._expand
    },
    // 子节点
    children () {
      return this.data[this.childrenKey] || []
    },
    classes () {
      const id = this.idKey ? this.data[this.idKey] : this.data
      return {
        'uif-tree-line-loading': this.loading,
        'uif-tree-line-expand': this.isExpand,
        'uif-tree-line-active': this.active === id
      }
    },
    styles () {
      return {
        paddingLeft: px(this.index * toNumber(this.ladder))
      }
    },
    // 需要异步加载
    needAsyncLoad () {
      return this.asyncLoad && !this.children.length && !this.data._noData
    }
  },
  created () {
  },
  mounted () {
  },
  methods: {
    onChangeExpand () {
      if (this.loading) {
        return false
      }
      if (!this.isExpand && this.needAsyncLoad) {
        // 展开，需要异步加载
        this.loading = true
        this.getAsyncDataList()
      } else {
        this.changeExpand(!this.isExpand)
      }
    },
    changeExpand (value) {
      this.$set(this.data, '_expand', value)
    },
    // 异步加载数据
    getAsyncDataList () {
      this.$emit('load', this.data, (children) => {
        this.loading = false
        if (isArray(children) && children.length) {
          this.$set(this.data, this.childrenKey, children)
          this.$nextTick(() => this.onChangeExpand())
        } else {
          this.$set(this.data, '_noData', true)
        }
      })
    },
    onLineClick () {
      if (this.data.disabled) return false
      if (this.lineExpand) {
        this.onChangeExpand()
      }
      // 激活
      const active = this.idKey ? this.data[this.idKey] : this.data
      this.$emit('choose', active)
      // 行点击
      this.$emit('line-click', this.data)
      // 最后一个节点点击
      if (!this.children.length) {
        this.$emit('line-child-click', this.data)
      }
    },
    onLabelClick () {
      if (this.data.disabled) return false
      this.$emit('label-click', this.data)
    }
  }
}
</script>
