'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _raf = require('raf');

var _raf2 = _interopRequireDefault(_raf);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var Transition = function (_React$Component) {
    _inherits(Transition, _React$Component);

    function Transition(props, context) {
        _classCallCheck(this, Transition);

        var _this = _possibleConstructorReturn(this, (Transition.__proto__ || Object.getPrototypeOf(Transition)).call(this, props, context));

        _this.state = props.children ? new AppearState(props, false) : new InitEmptyState();
        _this._setEnterState = _this._setEnterState.bind(_this);
        return _this;
    }

    _createClass(Transition, [{
        key: 'componentDidMount',
        value: function componentDidMount() {
            var _this2 = this;

            var props = this.props;
            this._isMounted = true;

            if (props.children) {
                props.onWillEnter && props.onWillEnter();
                setTimeout(function () {
                    return _this2._setEnterState();
                }, 0);
            }
        }
    }, {
        key: 'componentWillReceiveProps',
        value: function componentWillReceiveProps(nextProps) {
            var _this3 = this;

            if (this._isRemoving || nextProps.children === undefined || nextProps.children === this.state.children) {
                return;
            }

            var nextChildren = nextProps.children || null;

            if (!this.state.children && nextChildren) {
                this._showNewChildren(nextProps);
                return;
            }

            if (this.state.children && !nextChildren) {
                this._removeOldChildren();

                return;
            }

            if (this.state.children !== nextChildren) {
                this.props.isImmediatelyUpdate ? this._showNewChildren(nextProps, true, true) : this._removeOldChildren(function () {
                    setTimeout(function () {
                        return _this3._showNewChildren(nextProps, true);
                    }, nextProps.updateDelay);
                }, true);
            }
        }
    }, {
        key: 'componentWillUnmount',
        value: function componentWillUnmount() {
            this._isMounted = false;
        }
    }, {
        key: '_showNewChildren',
        value: function _showNewChildren(props, isUpdate, isSkipAppear) {
            var _this4 = this;

            if (this._isMounted && isSkipAppear) {
                this.setState({
                    children: props.children || null
                });

                return;
            }

            props.onWillEnter && props.onWillEnter();

            (0, _raf2.default)(function () {
                return _this4._isMounted && _this4.setState(new AppearState(props, isUpdate), _this4._setEnterState);
            });
        }
    }, {
        key: '_setEnterState',
        value: function _setEnterState() {
            var _this5 = this;

            var onDidEnter = this.props.onDidEnter;


            (0, _raf2.default)(function () {
                _this5._isMounted && _this5.setState({
                    isEnter: true,
                    isAppear: false
                }, function () {
                    var timeout = _this5._getTimeout('enter');
                    setTimeout(function () {
                        return _this5.setState({ isDidEnter: true }, function () {
                            return onDidEnter && onDidEnter();
                        });
                    }, timeout);
                });
            });
        }
    }, {
        key: '_removeOldChildren',
        value: function _removeOldChildren(callback, isUpdate) {
            var _this6 = this;

            var props = this.props;

            if (!this._isMounted || this._isRemoving) {
                return;
            }

            var timeout = this._getTimeout('leave');

            this._isRemoving = true;

            props.onWillLeave && props.onWillLeave();

            (0, _raf2.default)(function () {
                return _this6._isMounted && _this6.setState({ isEnter: false, isLeave: true, isUpdate: !!isUpdate, isDidEnter: false }, function () {
                    setTimeout(function () {
                        if (callback) {
                            props.onDidLeave && props.onDidLeave();
                            callback();
                            _this6._isRemoving = false;

                            return;
                        }

                        (0, _raf2.default)(function () {
                            return _this6._isMounted && _this6.setState({
                                children: null,
                                isEnter: false,
                                isLeave: false,
                                isUpdate: !!isUpdate
                            }, function () {
                                _this6._isRemoving = false;
                                props.onDidLeave && props.onDidLeave();
                            });
                        });
                    }, timeout);
                });
            });
        }
    }, {
        key: '_getTimeout',
        value: function _getTimeout(stage) {
            var props = this.props;

            return props[stage + 'Timeout'] === undefined ? props.timeout : props[stage + 'Timeout'];
        }
    }, {
        key: 'render',
        value: function render() {
            if (!this.state.children) {
                return null;
            }

            var _state = this.state,
                isEnter = _state.isEnter,
                isLeave = _state.isLeave,
                isUpdate = _state.isUpdate,
                isAppear = _state.isAppear;


            return this.state.children({ isEnter: isEnter, isLeave: isLeave, isUpdate: isUpdate, isAppear: isAppear });
        }
    }]);

    return Transition;
}(_react2.default.Component);

Transition.defaultProps = {
    timeout: 250,
    updateDelay: 50,
    isImmediatelyUpdate: true
};
exports.default = Transition;


function AppearState(props, isUpdate) {
    this.children = props.children;
    this.isEnter = false;
    this.isAppear = true;
    this.isLeave = false;
    this.isUpdate = !!isUpdate;
    this.isDidEnter = false;
}

function InitEmptyState() {
    this.children = null;
    this.isEnter = false;
    this.isLeave = true;
    this.isAppear = false;
    this.isUpdate = false;
    this.isDidEnter = false;
}