import Count from 'countup.js';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import warning from 'warning';

class CountUp extends Component {
  static propTypes = {
    decimal: PropTypes.string,
    decimals: PropTypes.number,
    delay: PropTypes.number,
    easingFn: PropTypes.func,
    end: PropTypes.number.isRequired,
    formattingFn: PropTypes.func,
    onEnd: PropTypes.func,
    onStart: PropTypes.func,
    prefix: PropTypes.string,
    redraw: PropTypes.bool,
    separator: PropTypes.string,
    start: PropTypes.number,
    suffix: PropTypes.string,
    style: PropTypes.object,
    useEasing: PropTypes.bool,
  };

  componentDidMount() {
    const { autostart, delay } = this.props;
    this.instance = this.createInstance();

    if (autostart || delay === 0) this.start();

    if (delay) setTimeout(this.start, delay * 1000);
  }

  shouldComponentUpdate(nextProps) {
    const hasCertainPropsChanged =
      this.props.duration !== nextProps.duration ||
      this.props.end !== nextProps.end ||
      this.props.start !== nextProps.start;

    return this.props.redraw || hasCertainPropsChanged;
  }

  componentDidUpdate(prevProps) {
    // If duration or start has changed, there's no way to update the duration
    // or start value. So we need to re-create the CountUp instance in order to
    // restart it.
    if (
      this.props.duration !== prevProps.duration ||
      this.props.start !== prevProps.start
    ) {
      this.instance = this.createInstance();
      this.start();
    }

    // Only end value has changed, so reset and and re-animate with the updated
    // end value.
    if (this.props.end !== prevProps.end) {
      this.instance.reset();
      this.instance.update(this.props.end);
    }
  }

  createInstance = () => {
    // Warn when user didn't use containerRef at all
    warning(
      this.containerRef.current &&
        this.containerRef.current instanceof HTMLElement,
      `Couldn't find attached element to hook the CountUp instance into! Try to attach "containerRef" from the render prop to a an HTMLElement, eg. <span ref={containerRef} />.`,
    );

    const {
      decimal,
      decimals,
      duration,
      easingFn,
      end,
      formattingFn,
      prefix,
      separator,
      start,
      suffix,
      useEasing,
    } = this.props;

    return new Count(
      this.containerRef.current,
      start,
      end,
      decimals,
      duration,
      {
        decimal,
        easingFn,
        formattingFn,
        separator,
        prefix,
        suffix,
        useEasing,
        useGrouping: !!separator,
      },
    );
  };

  pauseResume = (...args) => {
    const { onPauseResume } = this.props;

    if (typeof onPauseResume === 'function') onPauseResume(this);

    this.instance.pauseResume(...args);
  };

  reset = (...args) => {
    const { onReset } = this.props;

    if (typeof onReset === 'function') onReset(this);

    this.instance.reset(...args);
  };

  restart = () => {
    this.reset();
    this.start();
  };

  start = () => {
    const { onEnd, onStart } = this.props;
    const { pauseResume, reset, restart: start, update } = this;

    this.instance.start(
      typeof onEnd === 'function'
        ? () => onEnd({ pauseResume, reset, start, update })
        : undefined,
    );
    if (typeof onStart === 'function')
      onStart({ pauseResume, reset, start, update });
  };

  update = (...args) => {
    const { onUpdate } = this.props;

    if (typeof onUpdate === 'function') onUpdate(this);
  };

  containerRef = React.createRef();

  render() {
    const { children, className, style } = this.props;
    const { containerRef, pauseResume, reset, restart: start, update } = this;

    if (typeof children === 'function') {
      return children({ containerRef, pauseResume, reset, start, update });
    }

    return <span className={className} ref={containerRef} style={style} />;
  }
}

CountUp.defaultProps = {
  decimal: '.',
  decimals: 0,
  delay: null,
  duration: null,
  easingFn: null,
  formattingFn: null,
  onEnd: null,
  onPauseResume: null,
  onReset: null,
  onStart: null,
  onUpdate: null,
  prefix: '',
  separator: '',
  start: 0,
  suffix: '',
  redraw: true,
  style: undefined,
  useEasing: true,
};

export default CountUp;

@@ -3705,39 +3705,32 @@
 , reset, restart
-: start
 , update %7D = thi
@@ -3728,24 +3728,24 @@
 e %7D = this;%0A
+
 %0A    if (typ
@@ -3798,16 +3798,36 @@
 ildren(%7B
+%0A        countUpRef:
  contain
@@ -3824,32 +3824,40 @@
 f: containerRef,
+%0A       
  pauseResume, re
@@ -3853,37 +3853,77 @@
 eResume,
- reset, start, update
+%0A        reset,%0A        start: restart,%0A        update,%0A     
  %7D);%0A   

Rename exposed ref to countUpRef