
var defaultProps = {
    component: 'span',
    childFactory: function childFactory(child) {
        return child;
    }
};

class TransitionGroup extends React.Component {
    constructor(props, context) {
        super(props, context)
        this.childRefs = Object.create(null);
        this.state = {
            children: _ChildMapping.getChildMapping(props.children)
        };
    }
    performAppear(key, component) {
        this.currentlyTransitioningKeys[key] = true;

        if (component.componentWillAppear) {
            component.componentWillAppear(this._handleDoneAppearing.bind(this, key, component));
        } else {
            this._handleDoneAppearing(key, component);
        }
    }

    _handleDoneAppearing(key, component) {
        if (component.componentDidAppear) {
            component.componentDidAppear();
        }

        delete this.currentlyTransitioningKeys[key];

        var currentChildMapping = _ChildMapping.getChildMapping(this.props.children);

        if (!currentChildMapping || !currentChildMapping.hasOwnProperty(key)) {
            // This was removed before it had fully appeared. Remove it.
            this.performLeave(key, component);
        }
    }

    performEnter(key, component) {
        this.currentlyTransitioningKeys[key] = true;
        console.log(key, component, this.childRefs)
        if (component.componentWillEnter) {
            component.componentWillEnter(this._handleDoneEntering.bind(this, key, component));
        } else {
            this._handleDoneEntering(key, component);
        }
    }

    _handleDoneEntering(key, component) {
        if (component.componentDidEnter) {
            component.componentDidEnter();
        }

        delete this.currentlyTransitioningKeys[key];

        var currentChildMapping = _ChildMapping.getChildMapping(this.props.children);

        if (!currentChildMapping || !currentChildMapping.hasOwnProperty(key)) {
            // This was removed before it had fully entered. Remove it.
            this.performLeave(key, component);
        }
    }

    performLeave(key, component) {
        this.currentlyTransitioningKeys[key] = true;

        if (component.componentWillLeave) {
            component.componentWillLeave(this._handleDoneLeaving.bind(this, key, component));
        } else {
            // Note that this is somewhat dangerous b/c it calls setState()
            // again, effectively mutating the component before all the work
            // is done.
            this._handleDoneLeaving(key, component);
        }
    }

    _handleDoneLeaving(key, component) {
        if (component.componentDidLeave) {
            component.componentDidLeave();
        }

        delete this.currentlyTransitioningKeys[key];

        var currentChildMapping = _ChildMapping.getChildMapping(this.props.children);

        if (currentChildMapping && currentChildMapping.hasOwnProperty(key)) {
            // This entered again before it fully left. Add it again.
            this.keysToEnter.push(key);
        } else {
            this.setState(function (state) {
                var newChildren = Object.assign({}, state.children);
                delete newChildren[key];
                return { children: newChildren };
            });
        }
    }
    componentWillMount() {
        this.currentlyTransitioningKeys = {};
        this.keysToEnter = [];
        this.keysToLeave = [];
    }
    componentDidMount() {
        var initialChildMapping = this.state.children;
        console.log(initialChildMapping)
        for (var key in initialChildMapping) {
            if (initialChildMapping[key]) {
                this.performAppear(key, this.childRefs[key]);
            }
        }
    }

    componentWillReceiveProps(nextProps) {
        var nextChildMapping = (0, _ChildMapping.getChildMapping)(nextProps.children);
        var prevChildMapping = this.state.children;

        this.setState({
            children: (0, _ChildMapping.mergeChildMappings)(prevChildMapping, nextChildMapping)
        });

        for (var key in nextChildMapping) {
            var hasPrev = prevChildMapping && prevChildMapping.hasOwnProperty(key);
            if (nextChildMapping[key] && !hasPrev && !this.currentlyTransitioningKeys[key]) {
                this.keysToEnter.push(key);
            }
        }

        for (var _key in prevChildMapping) {
            var hasNext = nextChildMapping && nextChildMapping.hasOwnProperty(_key);
            if (prevChildMapping[_key] && !hasNext && !this.currentlyTransitioningKeys[_key]) {
                this.keysToLeave.push(_key);
            }
        }
    }

    componentDidUpdate() {
        var this2 = this;

        var keysToEnter = this.keysToEnter;
        this.keysToEnter = [];
        keysToEnter.forEach(function (key) {
            return this2.performEnter(key, this2.childRefs[key]);
        });

        var keysToLeave = this.keysToLeave;
        this.keysToLeave = [];
        keysToLeave.forEach(function (key) {
            return this2.performLeave(key, this2.childRefs[key]);
        });
    }

    render() {
        var this3 = this;

        // TODO: we could get rid of the need for the wrapper node
        // by cloning a single child
        var childrenToRender = [];

        var _loop = function _loop(key) {
            var child = this3.state.children[key];
            if (child) {
                var isCallbackRef = typeof child.ref !== 'string';
                var factoryChild = this3.props.childFactory(child);
                var ref = function ref(r) {
                    this3.childRefs[key] = r;
                };

                if (factoryChild === child && isCallbackRef) {
                    ref = (0, _chainFunction2.default)(child.ref, ref);
                }

                childrenToRender.push(React.cloneElement(factoryChild, {
                    key: key,
                    ref: ref
                }));
            }
        };

        for (var key in this.state.children) {
            _loop(key);
        }

        // Do not forward TransitionGroup props to primitive DOM nodes
        var props = Object.assign({}, this.props);
        delete props.transitionLeave;
        delete props.transitionName;
        delete props.transitionAppear;
        delete props.transitionEnter;
        delete props.childFactory;
        delete props.transitionLeaveTimeout;
        delete props.transitionEnterTimeout;
        delete props.transitionAppearTimeout;
        delete props.component;

        return React.createElement(this.props.component, props, childrenToRender);
    }
}

TransitionGroup.defaultProps = defaultProps;