import React, { Component } from 'react'

type WithCutdownProps = {
  renderView: (remainTime: number) => React.ReactNode
  seconds: number
  duration: number
  onEnd?: () => void
  onCutDown?: (count: number) => void
  onBack?: () => void // app切换后台 再 回来
}

const MaxTimeout = 2500

export default class WithCutdown extends Component<WithCutdownProps, any> {
  static defaultProps = {
    renderView: (remainTime: number) => {},
    seconds: 0,
    duration: 1000,
    onEnd: () => {},
  }

  timer: ReturnType<typeof setTimeout> | null

  constructor(props: WithCutdownProps) {
    super(props)
    this.init(props, true)
  }

  init(props: WithCutdownProps, syncTag: boolean, cb?: () => void) {
    const { seconds, onCutDown } = props
    if (syncTag) {
      this.state = { remainTime: seconds }
    } else {
      const oldProps = this.props
      // 当前秒数大于实际秒数时，更新时间,
      if (Number(oldProps.seconds) > Number(seconds)) {
        this.setState({ remainTime: seconds }, cb)
        onCutDown && onCutDown(seconds)
      }
    }
  }

  componentWillReceiveProps(nextProps: WithCutdownProps) {
    this.init(nextProps, false, () => {
      this.beginWork()
    })
  }

  componentWillUnmount() {
    this.clearTimer()
  }

  componentDidMount() {
    this.beginWork()
  }

  clearTimer() {
    this.timer && clearTimeout(this.timer)
    this.timer = null
  }

  beginWork() {
    const this$1 = this
    const { onEnd, duration, seconds, onCutDown, onBack } = this.props
    let t1: number

    // recursive
    function calc(remainTime: number) {
      this$1.timer = setTimeout(() => {
        const now = Date.now()
        if (t1 == null) {
          t1 = now
        } else {
          const delta = now - t1
          if (delta > MaxTimeout) {
            onBack && onBack()
          }
          t1 = now
        }

        if (remainTime > 0) {
          --remainTime
          this$1.setState({ remainTime })
          onCutDown && onCutDown(remainTime)
          calc(remainTime)
        } else {
          onEnd && onEnd()
          this$1.clearTimer()
        }
      }, duration)
    }

    this.clearTimer()

    if (seconds > 0) {
      calc(seconds)
    } else {
      onEnd && onEnd()
    }
  }

  render() {
    return this.props.renderView(this.state.remainTime)
  }
}
