import React from 'react'
import newEventActions from 'actions/newEvent'
import treeStores from 'stores/tree'
import {
  getEventBlockByBid,
  emptyCon,
  genConObj,
  consAstToArray
} from 'stores/funcs/newEvent'
import newEventStores from 'stores/newEvent'
import { cpJson, shallowEqualImmutable } from 'utils/utils'
import { BLOCK_OP_TYPE } from 'const/const'
import BlockEventConItem from './BlockConConItem'

export default class BlockConCons extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      cons: this.getCons()
    }

    this.onEventChange = this.onEventChange.bind(this)
    this.getCons = this.getCons.bind(this)
    this.changeConsAst = this.changeConsAst.bind(this)
    this.addBlockCon = this.addBlockCon.bind(this)
    this.delBlockCon = this.delBlockCon.bind(this)
  }

  shouldComponentUpdate(nextProps, nextState) {
    return (
      !shallowEqualImmutable(this.props, nextProps) ||
      !shallowEqualImmutable(this.state, nextState)
    )
  }

  componentDidMount() {
    this.unsubscribe = newEventStores.listen(this.onEventChange)
  }

  componentWillUnmount() {
    this.unsubscribe()
  }

  componentDidUpdate(preProps) {
    if (preProps.bid !== this.props.bid) {
      this.setState({
        cons: this.getCons()
      })
    }
  }

  onEventChange(status) {
    let obj = {}
    if (status && status.types) {
      if (
        status.types.includes('updateBlockProp') &&
        this.props.bid === status.data.affectBlockId &&
        status.data.prop === 'cons'
      ) {
        // 这里需要强制更新, 因为cons是个对象
        this.forceUpdate()
      }
    }
    if (Object.keys(obj).length > 0) {
      this.setState(obj)
    }
  }

  getCons() {
    let result = []
    let nodeId = this.props.eventNodeId || treeStores.curEventNodeId
    let block = getEventBlockByBid(this.props.bid, nodeId)
    if (
      block &&
      (block.op === BLOCK_OP_TYPE.IF || block.op === BLOCK_OP_TYPE.ELSE)
    ) {
      let conObj = block.args[0]
      result = consAstToArray(conObj)
    }
    return result
  }

  changeConsAst() {
    // 将cons数组转为ast格式
    let cons = cpJson(this.state.cons)
    let ors = []
    let ands = []
    cons.forEach((con, index) => {
      if (con.flag !== 'or') {
        ands.push(con)
      } else {
        ors.push(ands)
        ands = []
        ands.push(con)
      }
      if (index === cons.length - 1) {
        ors.push(ands)
      }
    })

    let consAst = {}
    if (ors.length > 1) {
      // 有or
      consAst.op = 'or'
      consAst.args = []
      ors.forEach(orItem => {
        if (orItem.length > 1) {
          // 多个条件
          let andObj = {
            op: 'and',
            args: []
          }
          orItem.forEach(conItem => {
            let conObj = genConObj(conItem)
            andObj.args.push(conObj)
          })
          consAst.args.push(andObj)
        } else {
          // 单个条件
          let conObj = genConObj(orItem[0])
          consAst.args.push(conObj)
        }
      })
    } else {
      // 没有or
      consAst.op = 'and'
      consAst.args = []
      let andArray = ors[0]
      if (andArray.length > 1) {
        // 多个条件
        andArray.forEach(conItem => {
          let conObj = genConObj(conItem)
          consAst.args.push(conObj)
        })
      } else {
        // 单个条件
        consAst = genConObj(andArray[0])
      }
    }

    let nodeId = this.props.eventNodeId || treeStores.curEventNodeId
    newEventActions.updateBlockProp({
      nodeId,
      blockId: this.props.bid,
      prop: 'cons',
      value: consAst,
      trigger: true,
      addRecord: true
    })
  }

  addBlockCon() {
    let cons = this.state.cons
    let newEmptyCon = emptyCon()
    cons.push(newEmptyCon)
  }

  delBlockCon({ index, resetLast }) {
    let cons = this.state.cons
    if (resetLast && cons.length === 1) {
      cons[0] = emptyCon()
    } else {
      cons.splice(index, 1)
    }
    if (cons.length === 1) {
      cons[0].flag = 'and'
    }
  }

  render() {
    let cons = (
      <div className="con-items-wrap">
        {this.state.cons.map((con, index) => {
          return (
            <BlockEventConItem
              index={index}
              con={con}
              key={index}
              layer={this.props.layer}
              groupLayer={this.props.groupLayer}
              nestGroupLayer={this.props.nestGroupLayer}
              extraGapGroupLayer={this.props.extraGapGroupLayer}
              bid={this.props.bid}
              eventNodeId={this.props.eventNodeId}
              onConsChange={this.changeConsAst}
              onAddBlockCon={this.addBlockCon}
              onDelBlockCon={this.delBlockCon}
            />
          )
        })}
      </div>
    )

    return (
      <div className="con-cons flex-1">
        {!this.state.cons || this.state.cons.length === 0 ? null : cons}
      </div>
    )
  }
}
