import * as tslib_1 from "tslib";
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Fabric } from '../../Fabric';
import { BaseComponent, classNamesFunction, customizable, getDocument, createRef, setPortalAttribute, setVirtualParent } from '../../Utilities';
import { registerLayer, getDefaultTarget, unregisterLayer } from './Layer.notification';
var getClassNames = classNamesFunction();
var LayerBase = /** @class */ (function (_super) {
    tslib_1.__extends(LayerBase, _super);
    function LayerBase(props) {
        var _this = _super.call(this, props) || this;
        _this._rootElement = createRef();
        /**
         * rootElement wrapper for setting virtual parent as soon as root element ref is available.
         */
        _this._handleRootElementRef = function (ref) {
            _this._rootElement(ref);
            if (ref) {
                // TODO: Calling _setVirtualParent in this ref wrapper SHOULD allow us to remove
                //    other calls to _setVirtualParent throughout this class. However,
                //    as this is an immediate fix for a P0 issue the existing _setVirtualParent
                //    calls are left for now to minimize potential regression.
                _this._setVirtualParent();
            }
        };
        /**
         * Helper to stop events from bubbling up out of Layer.
         */
        _this._filterEvent = function (ev) {
            // We should just be able to check ev.bubble here and only stop events that are bubbling up. However, even though mouseenter and
            //    mouseleave do NOT bubble up, they are showing up as bubbling. Therefore we stop events based on event name rather than ev.bubble.
            if (ev.type !== 'mouseenter' && ev.type !== 'mouseleave') {
                ev.stopPropagation();
            }
        };
        _this.state = {
            hasMounted: false
        };
        _this._warnDeprecations({
            onLayerMounted: 'onLayerDidMount'
        });
        if (_this.props.hostId) {
            registerLayer(_this.props.hostId, _this);
        }
        return _this;
    }
    LayerBase.prototype.componentWillMount = function () {
        this._layerElement = this._getLayerElement();
    };
    LayerBase.prototype.componentWillUpdate = function () {
        if (!this._layerElement) {
            this._layerElement = this._getLayerElement();
        }
    };
    LayerBase.prototype.componentDidMount = function () {
        // We can safely set state immediately because the ref wrapper will make sure the virtual
        //    parent has been set before componentDidMount is called.
        this.setState({ hasMounted: true });
        this._setVirtualParent();
        var _a = this.props, onLayerDidMount = _a.onLayerDidMount, onLayerMounted = _a.onLayerMounted;
        if (onLayerMounted) {
            onLayerMounted();
        }
        if (onLayerDidMount) {
            onLayerDidMount();
        }
    };
    LayerBase.prototype.componentWillUnmount = function () {
        this._removeLayerElement();
        var _a = this.props, onLayerWillUnmount = _a.onLayerWillUnmount, hostId = _a.hostId;
        if (onLayerWillUnmount) {
            onLayerWillUnmount();
        }
        if (hostId) {
            unregisterLayer(hostId, this);
        }
    };
    LayerBase.prototype.componentDidUpdate = function () {
        this._setVirtualParent();
    };
    LayerBase.prototype.render = function () {
        var classNames = this._getClassNames();
        var eventBubblingEnabled = this.props.eventBubblingEnabled;
        var hasMounted = this.state.hasMounted;
        return (React.createElement("span", { className: "ms-layer", ref: this._handleRootElementRef }, this._layerElement &&
            hasMounted &&
            ReactDOM.createPortal(eventBubblingEnabled ? (React.createElement(Fabric, { className: classNames.content }, this.props.children)) : (React.createElement(Fabric, { className: classNames.content, onClick: this._filterEvent, onContextMenu: this._filterEvent, onDoubleClick: this._filterEvent, onDrag: this._filterEvent, onDragEnd: this._filterEvent, onDragEnter: this._filterEvent, onDragExit: this._filterEvent, onDragLeave: this._filterEvent, onDragOver: this._filterEvent, onDragStart: this._filterEvent, onDrop: this._filterEvent, onMouseDown: this._filterEvent, onMouseEnter: this._filterEvent, onMouseLeave: this._filterEvent, onMouseMove: this._filterEvent, onMouseOver: this._filterEvent, onMouseOut: this._filterEvent, onMouseUp: this._filterEvent, onKeyDown: this._filterEvent, onKeyPress: this._filterEvent, onKeyUp: this._filterEvent, onFocus: this._filterEvent, onBlur: this._filterEvent, onChange: this._filterEvent, onInput: this._filterEvent, onInvalid: this._filterEvent, onSubmit: this._filterEvent }, this.props.children)), this._layerElement)));
    };
    LayerBase.prototype._getClassNames = function () {
        var _a = this.props, className = _a.className, styles = _a.styles, theme = _a.theme;
        var classNames = getClassNames(styles, {
            theme: theme,
            className: className,
            isNotHost: !this.props.hostId
        });
        return classNames;
    };
    LayerBase.prototype._setVirtualParent = function () {
        if (this._rootElement && this._rootElement.current && this._layerElement) {
            setVirtualParent(this._layerElement, this._rootElement.current);
        }
    };
    LayerBase.prototype._getLayerElement = function () {
        var host = this._getHost();
        var classNames = this._getClassNames();
        if (host !== this._host) {
            this._removeLayerElement();
        }
        if (host) {
            this._host = host;
            if (!this._layerElement) {
                var doc = getDocument();
                if (!doc) {
                    return;
                }
                this._layerElement = doc.createElement('div');
                this._layerElement.className = classNames.root;
                setPortalAttribute(this._layerElement);
                host.appendChild(this._layerElement);
            }
        }
        return this._layerElement;
    };
    LayerBase.prototype._removeLayerElement = function () {
        if (this._layerElement) {
            this.props.onLayerWillUnmount();
            var parentNode = this._layerElement.parentNode;
            if (parentNode) {
                parentNode.removeChild(this._layerElement);
            }
            this._layerElement = undefined;
        }
    };
    LayerBase.prototype._getHost = function () {
        var hostId = this.props.hostId;
        var doc = getDocument();
        if (!doc) {
            return undefined;
        }
        if (hostId) {
            return doc.getElementById(hostId);
        }
        else {
            var defaultHostSelector = getDefaultTarget();
            return defaultHostSelector ? doc.querySelector(defaultHostSelector) : doc.body;
        }
    };
    LayerBase.defaultProps = {
        onLayerDidMount: function () { return undefined; },
        onLayerWillUnmount: function () { return undefined; }
    };
    LayerBase = tslib_1.__decorate([
        customizable('Layer', ['theme', 'hostId'])
    ], LayerBase);
    return LayerBase;
}(BaseComponent));
export { LayerBase };
//# sourceMappingURL=Layer.base.js.map