// @flow

import React, { Component } from 'react'
import moment from 'moment'

const COUNTDOWN_NOT_STARTED = 1
const COUNTDOWN_STARTED = 2
const COUNTDOWN_FINISHED = 3

type Props = {
  format: {
    day?: string,
    hour?: string,
    minute?: string,
    second?: string
  },
  interval: number,
  leadingZero?: boolean,
  onFinished?: Function,
  startDelay?: number,
  targetDate: string,
  timeSeparator?: string
}

type State = {
  intervalId: ?number,
  remainingTime: number,
  status: number
}

const calculateRemainingTime = targetDate => {
  return -1 * moment().diff(targetDate)
}

const addLeadingZero = (value: number) => {
  if (value < 10) {
    return '0' + value.toString()
  }
  return value
}

class Countdown extends Component<Props, State> {
  static defaultProps = {
    format: {
      hour: 'HH',
      minute: 'MM',
      second: 'SS'
    },
    interval: 1000,
    startDelay: 0,
    leadingZero: false,
    timeSeparator: ' '
  }

  state: State = {
    intervalId: null,
    remainingTime: 0,
    status: COUNTDOWN_NOT_STARTED
  }

  componentDidMount = () => {
    setTimeout(() => {
      const timer = setInterval(() => {
        this.tick()
      }, this.props.interval)

      this.setState({
        status: COUNTDOWN_STARTED,
        intervalId: timer
      })

      this.tick()
    }, this.props.startDelay)
  }

  componentWillUnmount = () => {
    if (this.state.intervalId) {
      clearInterval(this.state.intervalId)
    }
  }

  tick = () => {
    this.setState({
      remainingTime: calculateRemainingTime(this.props.targetDate)
    })

    if (this.state.remainingTime <= 0) {
      this.setState({
        status: COUNTDOWN_FINISHED
      })

      if (this.props.onFinished) {
        this.props.onFinished()
      }
      if (this.state.intervalId) {
        clearInterval(this.state.intervalId)
      }
    }
  }

  renderRemainingTime = () => {
    let html = []
    const { format, leadingZero, timeSeparator } = this.props
    const { remainingTime } = this.state

    if (format.day) {
      let days = Math.trunc(moment.duration(remainingTime).asDays())
      days = days >= 0 ? days : 0
      if (leadingZero) {
        days = addLeadingZero(days)
      }
      html.push(
        <span className="react-cntdwn-day" key="day">
          {days}d
          {timeSeparator}
        </span>
      )
    }

    if (format.hour) {
      let hours = moment.duration(remainingTime).get('hours')
      hours = hours >= 0 ? hours : 0
      if (leadingZero) {
        hours = addLeadingZero(hours)
      }
      html.push(
        <span className="react-cntdwn-hour" key="hour">
          {hours}hr
          {timeSeparator}
        </span>
      )
    }

    if (format.minute) {
      let minutes = moment.duration(remainingTime).get('minutes')
      minutes = minutes >= 0 ? minutes : 0
      if (leadingZero) {
        minutes = addLeadingZero(minutes)
      }
      html.push(
        <span className="react-cntdwn-minute" key="minute">
          {minutes}min
          {timeSeparator}
        </span>
      )
    }

    if (format.second) {
      let seconds = moment.duration(remainingTime).get('seconds')
      seconds = seconds >= 0 ? seconds : 0
      if (leadingZero) {
        seconds = addLeadingZero(seconds)
      }
      html.push(
        <span className="react-cntdwn-second" key="second">
          {seconds}sec
        </span>
      )
    }

    return html
  }

  render() {
    return this.state.status === COUNTDOWN_NOT_STARTED ? (
      <span />
    ) : (
      <div className="react-cntdwn-timer">{this.renderRemainingTime()}</div>
    )
  }
}

export default Countdown
