import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { get, set, isEqual } from 'lodash'
import TreeNode from './TreeNode'

// 组件
class OrganizationTree extends Component {
  componentDidMount () {
    this.checkExpand()
  }

  componentDidUpdate (prevProps) {
    if (!isEqual(prevProps, this.props)) {
      this.checkExpand()
    }
  }

  getObjPathVal = (obj, path) => {
    return get(obj, path)
  }

  setObjPathVal = (obj, path, value) => {
    return set(obj, path, value)
  }

  checkExpand = () => {
    const { data, expandLevel } = this.props
    expandLevel !== false && this.setExpand(data, expandLevel === 0 ? true : expandLevel)
  }

  setExpand = (data, level, deep = 1) => {
    if (level === true || deep < level) {
      const { node } = this.props
      if (Array.isArray(data)) {
        data.forEach(item => {
          // 如果初始数据中有配默认 expand ，则保留默认配置
          const expandStatus = this.getObjPathVal(item, node.expand)
          this.setObjPathVal(item, node.expand, expandStatus !== undefined ? !!expandStatus : true)

          const childrenList = this.getObjPathVal(item, node.children)
          childrenList && this.setExpand(childrenList, level, deep + 1)
        })
      } else {
        // 如果初始数据中有配默认 expand，则保留默认配置
        const expandStatus = this.getObjPathVal(data, node.expand)
        this.setObjPathVal(data, node.expand, expandStatus !== undefined ? !!expandStatus : true)

        const childrenList = this.getObjPathVal(data, node.children)
        childrenList && this.setExpand(childrenList, level, deep + 1)
      }
      this.forceUpdate()
    }
  }

  collapse = (list) => {
    const { node } = this.props
    list.forEach(child => {
      this.setObjPathVal(child, node.expand, false)
      const childrenList = this.getObjPathVal(child, node.children)
      Array.isArray(childrenList) && this.collapse(childrenList)
    })
  }

  toggleExpand = (e, nodeData) => {
    const { node } = this.props
    const expandStatus = this.getObjPathVal(nodeData, node.expand)
    this.setObjPathVal(nodeData, node.expand, !expandStatus)

    // 展开的节点将其收起
    const childrenList = this.getObjPathVal(nodeData, node.children)
    if (expandStatus && childrenList) {
      this.collapse(childrenList)
    }
    this.forceUpdate()

    // 对外暴露 onExpand 事件
    const { onExpand } = this.props
    onExpand instanceof Function && onExpand(e, !expandStatus, nodeData)
  }

  render () {
    const { horizontal } = this.props
    return (
      <div className='org-tree-container'>
        <div className={`org-tree ${horizontal ? 'horizontal' : ''}`}>
          <TreeNode
            {...this.props}
            onExpand={this.toggleExpand}
          />
        </div>
      </div>
    )
  }
}

OrganizationTree.propTypes = {
  data: PropTypes.object,
  node: PropTypes.object,
  horizontal: PropTypes.bool,
  collapsable: PropTypes.bool,
  expandLevel: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
  renderContent: PropTypes.func,
  labelClassName: PropTypes.string,
  onClick: PropTypes.func,
  onExpand: PropTypes.func
}

OrganizationTree.defaultProps = {
  // 数据源别名
  node: {
    id: 'id',
    label: 'label',
    expand: 'expand',
    children: 'children'
  },
  // 默认横向展开
  horizontal: false,
  // 默认可折叠/展开
  collapsable: true,
  // true 展开全部，false 收起全部，数字则代表展开层级
  expandLevel: true
}

export default OrganizationTree
