import React from 'react';
import { requestFrame, cancelFrame } from 'utils/animframe';

class Fader extends React.Component {
  constructor(props) {
    super(props);

    this.nextFrame = null;
    this.duration = props.duration;
    this.lastTime = null;

    this.state = {
      progress: props.visible ? this.duration : 0,
      direction: 0
    };
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.visible === true && this.props.visible === false) {
      this.startAnim(1);
    } else if (nextProps.visible === false && this.props.visible === true) {
      this.startAnim(-1);
    }
  }

  componentWillUnmount() {
    cancelFrame(this.nextFrame);
    this.nextFrame = null;
  }

  handleFrame() {
    const currTime = Date.now();
    const timeDiff = Math.min(100, currTime - this.lastTime);
    this.lastTime = currTime;

    let { direction, progress } = this.state;
    if (direction === 1) {
      // Fading in
      progress = Math.min(this.duration, progress + timeDiff) | 0;

      if (progress === this.duration) {
        direction = 0;
      }

      this.setState({ direction, progress });
    } else if (direction === -1) {
      // Fading out
      progress = Math.max(0, progress - timeDiff) | 0;

      if (progress === 0) {
        direction = 0;
      }

      this.setState({ direction, progress });
    }

    if (direction !== 0) {
      this.nextFrame = requestFrame(() => this.handleFrame());
    }
  }

  startAnim(direction) {
    this.setState({ direction: direction });

    if (this.nextFrame) {
      cancelFrame(this.nextFrame);
    }

    this.lastTime = Date.now();
    this.nextFrame = requestFrame(() => this.handleFrame());
  }

  render() {
    if (this.state.progress === 0) {
      return null;
    }

    return (
      <div style={{opacity: this.state.progress / this.duration}}>
        {this.props.children}
      </div>
    );
  }
}

Fader.propTypes = {
  children: React.PropTypes.object,
  duration: React.PropTypes.number.isRequired,
  visible: React.PropTypes.bool.isRequired
};

export default Fader;
