import React from 'react'
import cls from 'classnames'
import ResizeObserver from 'resize-observer-polyfill'
import treeStores from 'stores/tree'
import newEventStores from 'stores/newEvent'
import { getEventNodeById, minScrollJengaPanel } from 'stores/funcs/newEvent'
import { nodeIsSystem, nodeIsInModule } from 'stores/funcs/nodeType'
import JengaItemTitle from './JengaItemTitle'
import JengaItemEvent from './JengaItemEvent'

export default class JengaItem extends React.Component {
  constructor(props) {
    super(props)
    this.curEventNodeId = newEventStores.curEventNodeId
    this.state = {
      isActive: this.isCurEventNodeId(this.curEventNodeId),
      isEnable: this.isEnable(),
      sysList: this.getCurSysList()
    }

    this.onTreeChange = this.onTreeChange.bind(this)
    this.onEventChange = this.onEventChange.bind(this)
    this.onActiveObserver = this.onActiveObserver.bind(this)
    this.onInactiveObserver = this.onInactiveObserver.bind(this)
    this.onResize = this.onResize.bind(this)

    this.isCurEventNodeId = this.isCurEventNodeId.bind(this)
    this.isEnable = this.isEnable.bind(this)
    this.getCurSysList = this.getCurSysList.bind(this)
    this.updateCurSysList = this.updateCurSysList.bind(this)
    this.getSysList = this.getSysList.bind(this)
    this.getModuleSysList = this.getModuleSysList.bind(this)
  }

  componentDidMount() {
    window.addEventListener('resize', this.onResize)
    this.unsubscribe = newEventStores.listen(this.onEventChange)
    this.unsubscribeTree = treeStores.listen(this.onTreeChange)
    this.onActiveObserver()
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.onResize)
    this.unsubscribe()
    this.unsubscribeTree()
    this.onInactiveObserver()
  }

  componentDidUpdate(preProps) {
    if (preProps.eventNodeId !== this.props.eventNodeId) {
      this.setState({
        isActive: this.isCurEventNodeId(this.curEventNodeId),
        isEnable: this.isEnable(),
        sysList: this.getCurSysList()
      })
    }
  }

  onTreeChange(status) {
    let obj = {}
    if (status && status.types) {
      if (
        status.types.includes('curNodeIdList') ||
        status.types.includes('curRootId')
      ) {
        obj.sysList = this.getCurSysList()
      }
    }
    if (Object.keys(obj).length > 0) {
      this.setState(obj)
    }
  }

  onEventChange(status) {
    let obj = {}
    if (status && status.types) {
      if (status.types.includes('curEventNodeId')) {
        if (this.curEventNodeId !== status.data.curEventNodeId) {
          let curEventNodeId = status.data.curEventNodeId
          if (this.isCurEventNodeId(status.data.curEventNodeId)) {
            this.updateCurSysList(obj, curEventNodeId, this.curEventNodeId)
          }
          this.curEventNodeId = curEventNodeId
          let isEnable = this.isEnable()
          if (isEnable !== this.state.isEnable) {
            obj.isEnable = isEnable
          }
          let isActive = this.isCurEventNodeId(this.curEventNodeId)
          if (isActive !== this.state.isActive) {
            obj.isActive = isActive
          }
        }
      }
      if (status.types.includes('toggleEvent')) {
        if (status.data.affectEventNodeId === this.curEventNodeId) {
          if (status.data.prop === 'enable') {
            if (this.isCurEventNodeId(status.data.affectEventNodeId)) {
              let isEnable = this.isEnable()
              if (isEnable !== this.state.isEnable) {
                obj.isEnable = isEnable
              }
            }
          }
        }
      }
    }
    if (Object.keys(obj).length > 0) {
      this.setState(obj)
    }
  }

  isCurEventNodeId(curEventNodeId) {
    return !this.props.eventNodeId || this.props.eventNodeId === curEventNodeId
  }

  isEnable() {
    let isEnable = true
    let nodeId = this.props.eventNodeId || this.curEventNodeId
    if (nodeId) {
      let node = getEventNodeById(nodeId)
      if (node && node.events && node.events.enable === false) {
        isEnable = false
      }
    }
    return isEnable
  }

  onActiveObserver() {
    // 选择目标节点
    let target = document.querySelector('.jenga-item')
    // 创建观察者对象
    this.observer = new ResizeObserver(entries => {
      let entry = entries[0]
      if (entry.contentRect.height !== undefined) {
        minScrollJengaPanel()
      }
    })
    // 传入目标节点和观察选项
    this.observer.observe(target)
  }

  onInactiveObserver() {
    this.observer && this.observer.disconnect()
  }

  onResize() {
    minScrollJengaPanel()
  }

  getCurSysList() {
    let sysList = []
    let curEventNodeId = this.props.eventNodeId || this.curEventNodeId
    let moduleRootId = nodeIsInModule(curEventNodeId, true)
    // 当前的node是在module内刷新sysList
    if (moduleRootId) {
      sysList = this.getModuleSysList(moduleRootId)
    } else {
      // module内的重新获取sysList
      sysList = this.getSysList()
    }
    return sysList
  }

  updateCurSysList(obj, curNodeId, preNodeId) {
    let moduleRootId = nodeIsInModule(curNodeId, true)
    // 当前的node是在module内刷新sysList
    if (moduleRootId) {
      obj.sysList = this.getModuleSysList(moduleRootId)
    } else if (nodeIsInModule(preNodeId)) {
      // module内的重新获取sysList
      obj.sysList = this.getSysList()
    }
  }

  getSysList() {
    let result = []
    let list = treeStores.curNodeIdList
    for (let i = 0, len = list.length; i < len; i++) {
      let node = treeStores.getNodeById(list[i])
      if (node && node.type === 'data-module') {
        // 不计算内部的sys
        let lastNodeId = node.id
        while (node && node.children && node.children.length > 0) {
          node = treeStores.getNodeById(node.children[node.children.length - 1])
        }
        if (lastNodeId !== node.id) {
          lastNodeId = node.id
          let lastIndex = list.indexOf(lastNodeId)
          if (i < lastIndex && lastIndex < len) {
            i = lastIndex
          }
        }
      } else if (node && nodeIsSystem(node.type)) {
        result.push(list[i])
      }
    }
    return result
  }

  getModuleSysList(moduleRootId) {
    let result = []
    let loopNode = nodeId => {
      let node = treeStores.getNodeById(nodeId)
      if (node) {
        if (nodeIsSystem(node.type)) {
          result.push(node.id)
        }
        if (node.children) {
          node.children.forEach(childId => {
            loopNode(childId)
          })
        }
      }
    }
    loopNode(moduleRootId)
    return result
  }

  render() {
    return (
      <div
        className={cls('jenga-item', {
          active: this.state.isActive,
          disabled: !this.state.isEnable
        })}
      >
        <JengaItemTitle eventNodeId={this.props.eventNodeId} />
        <JengaItemEvent
          eventNodeId={this.props.eventNodeId}
          visibleBlockIds={this.props.visibleBlockIds}
        />
      </div>
    )
  }
}
