define(["require", "exports", "tslib", "react", "../../Utilities", "../../utilities/positioning", "./PositioningContainer/index", "./Beak/Beak", "../../common/DirectionalHint", "./Coachmark.styles", "../../FocusTrapZone"], function (require, exports, tslib_1, React, Utilities_1, positioning_1, index_1, Beak_1, DirectionalHint_1, Coachmark_styles_1, FocusTrapZone_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var getClassNames = Utilities_1.classNamesFunction();
    exports.COACHMARK_ATTRIBUTE_NAME = 'data-coachmarkid';
    var CoachmarkBase = /** @class */ (function (_super) {
        tslib_1.__extends(CoachmarkBase, _super);
        function CoachmarkBase(props) {
            var _this = _super.call(this, props) || this;
            /**
             * The cached HTMLElement reference to the Entity Inner Host
             * element.
             */
            _this._entityHost = React.createRef();
            _this._entityInnerHostElement = React.createRef();
            _this._translateAnimationContainer = React.createRef();
            _this._ariaAlertContainer = React.createRef();
            _this._childrenContainer = React.createRef();
            _this._positioningContainer = React.createRef();
            _this.dismiss = function (ev) {
                var onDismiss = _this.props.onDismiss;
                if (onDismiss) {
                    onDismiss(ev);
                }
            };
            _this._onKeyDown = function (e) {
                // Open coachmark if user presses ALT + C (arbitrary keypress for now)
                if ((e.altKey && e.which === Utilities_1.KeyCodes.c) ||
                    (e.which === Utilities_1.KeyCodes.enter &&
                        _this._translateAnimationContainer.current &&
                        _this._translateAnimationContainer.current.contains(e.target))) {
                    _this._onFocusHandler();
                }
            };
            _this._onFocusHandler = function () {
                if (_this.state.isCollapsed) {
                    _this._openCoachmark();
                }
            };
            _this._onPositioned = function (positionData) {
                _this._async.requestAnimationFrame(function () {
                    _this.setState({
                        targetAlignment: positionData.alignmentEdge,
                        targetPosition: positionData.targetEdge
                    });
                });
            };
            _this._setBeakPosition = function () {
                var beakLeft;
                var beakTop;
                var beakRight;
                var beakBottom;
                var transformOriginX;
                var transformOriginY;
                var targetAlignment = _this.state.targetAlignment;
                var distanceAdjustment = '3px'; // Adjustment distance for Beak to shift towards Coachmark bubble.
                switch (_this._beakDirection) {
                    // If Beak is pointing Up or Down
                    case positioning_1.RectangleEdge.top:
                    case positioning_1.RectangleEdge.bottom:
                        // If there is no target alignment, then beak is X-axis centered in callout
                        if (!targetAlignment) {
                            beakLeft = "calc(50% - " + Beak_1.BEAK_WIDTH / 2 + "px)";
                            transformOriginX = 'center';
                        }
                        else {
                            // Beak is aligned to the left of target
                            if (targetAlignment === positioning_1.RectangleEdge.left) {
                                beakLeft = Coachmark_styles_1.COACHMARK_WIDTH / 2 - Beak_1.BEAK_WIDTH / 2 + "px";
                                transformOriginX = 'left';
                            }
                            else {
                                // Beak is aligned to the right of target
                                beakRight = Coachmark_styles_1.COACHMARK_WIDTH / 2 - Beak_1.BEAK_WIDTH / 2 + "px";
                                transformOriginX = 'right';
                            }
                        }
                        if (_this._beakDirection === positioning_1.RectangleEdge.top) {
                            beakTop = distanceAdjustment;
                            transformOriginY = 'top';
                        }
                        else {
                            beakBottom = distanceAdjustment;
                            transformOriginY = 'bottom';
                        }
                        break;
                    // If Beak is pointing Left or Right
                    case positioning_1.RectangleEdge.left:
                    case positioning_1.RectangleEdge.right:
                        // If there is no target alignment, then beak is Y-axis centered in callout
                        if (!targetAlignment) {
                            beakTop = "calc(50% - " + Beak_1.BEAK_WIDTH / 2 + "px)";
                            transformOriginY = "center";
                        }
                        else {
                            // Beak is aligned to the top of target
                            if (targetAlignment === positioning_1.RectangleEdge.top) {
                                beakTop = Coachmark_styles_1.COACHMARK_WIDTH / 2 - Beak_1.BEAK_WIDTH / 2 + "px";
                                transformOriginY = "top";
                            }
                            else {
                                // Beak is aligned to the bottom of target
                                beakBottom = Coachmark_styles_1.COACHMARK_WIDTH / 2 - Beak_1.BEAK_WIDTH / 2 + "px";
                                transformOriginY = "bottom";
                            }
                        }
                        if (_this._beakDirection === positioning_1.RectangleEdge.left) {
                            if (Utilities_1.getRTL()) {
                                beakRight = distanceAdjustment;
                            }
                            else {
                                beakLeft = distanceAdjustment;
                            }
                            transformOriginX = 'left';
                        }
                        else {
                            if (Utilities_1.getRTL()) {
                                beakLeft = distanceAdjustment;
                            }
                            else {
                                beakRight = distanceAdjustment;
                            }
                            transformOriginX = 'right';
                        }
                        break;
                }
                _this.setState({
                    beakLeft: beakLeft,
                    beakRight: beakRight,
                    beakBottom: beakBottom,
                    beakTop: beakTop,
                    transformOrigin: transformOriginX + " " + transformOriginY
                });
            };
            _this._openCoachmark = function () {
                _this.setState({
                    isCollapsed: false
                });
                if (_this.props.onAnimationOpenStart) {
                    _this.props.onAnimationOpenStart();
                }
                _this._entityInnerHostElement.current &&
                    _this._entityInnerHostElement.current.addEventListener('transitionend', function () {
                        // Need setTimeout to trigger narrator
                        _this._async.setTimeout(function () {
                            if (_this._entityInnerHostElement.current) {
                                Utilities_1.focusFirstChild(_this._entityInnerHostElement.current);
                            }
                        }, 1000);
                        if (_this.props.onAnimationOpenEnd) {
                            _this.props.onAnimationOpenEnd();
                        }
                    });
            };
            _this._warnDeprecations({
                teachingBubbleRef: undefined,
                collapsed: 'isCollapsed',
                beakWidth: undefined,
                beakHeight: undefined,
                width: undefined,
                height: undefined
            });
            // Set defaults for state
            _this.state = {
                isCollapsed: props.isCollapsed,
                isBeaconAnimating: true,
                isMeasuring: true,
                entityInnerHostRect: {
                    width: 0,
                    height: 0
                },
                isMouseInProximity: false,
                isMeasured: false
            };
            return _this;
        }
        Object.defineProperty(CoachmarkBase.prototype, "_beakDirection", {
            get: function () {
                var targetPosition = this.state.targetPosition;
                if (targetPosition === undefined) {
                    return positioning_1.RectangleEdge.bottom;
                }
                return positioning_1.getOppositeEdge(targetPosition);
            },
            enumerable: true,
            configurable: true
        });
        CoachmarkBase.prototype.render = function () {
            var _a = this.props, beaconColorOne = _a.beaconColorOne, beaconColorTwo = _a.beaconColorTwo, children = _a.children, target = _a.target, color = _a.color, positioningContainerProps = _a.positioningContainerProps, ariaDescribedBy = _a.ariaDescribedBy, ariaDescribedByText = _a.ariaDescribedByText, ariaLabelledBy = _a.ariaLabelledBy, ariaLabelledByText = _a.ariaLabelledByText, ariaAlertText = _a.ariaAlertText, delayBeforeCoachmarkAnimation = _a.delayBeforeCoachmarkAnimation, styles = _a.styles, theme = _a.theme, className = _a.className;
            var _b = this.state, beakLeft = _b.beakLeft, beakTop = _b.beakTop, beakRight = _b.beakRight, beakBottom = _b.beakBottom, isCollapsed = _b.isCollapsed, isBeaconAnimating = _b.isBeaconAnimating, isMeasuring = _b.isMeasuring, entityInnerHostRect = _b.entityInnerHostRect, transformOrigin = _b.transformOrigin, alertText = _b.alertText, isMeasured = _b.isMeasured;
            // Defaulting the main background before passing it to the styles because it is used for `Beak` too.
            var defaultColor = color;
            if (!defaultColor && theme) {
                defaultColor = theme.semanticColors.primaryButtonBackground;
            }
            var classNames = getClassNames(styles, {
                theme: theme,
                beaconColorOne: beaconColorOne,
                beaconColorTwo: beaconColorTwo,
                className: className,
                isCollapsed: isCollapsed,
                isBeaconAnimating: isBeaconAnimating,
                isMeasuring: isMeasuring,
                color: defaultColor,
                transformOrigin: transformOrigin,
                isMeasured: isMeasured,
                entityHostHeight: entityInnerHostRect.height + "px",
                entityHostWidth: entityInnerHostRect.width + "px",
                width: Coachmark_styles_1.COACHMARK_WIDTH + "px",
                height: Coachmark_styles_1.COACHMARK_HEIGHT + "px",
                delayBeforeCoachmarkAnimation: delayBeforeCoachmarkAnimation + "ms"
            });
            var finalHeight = isCollapsed ? Coachmark_styles_1.COACHMARK_HEIGHT : entityInnerHostRect.height;
            return (React.createElement(index_1.PositioningContainer, tslib_1.__assign({ target: target, offsetFromTarget: Beak_1.BEAK_HEIGHT, componentRef: this._positioningContainer, finalHeight: finalHeight, onPositioned: this._onPositioned, bounds: this._getBounds() }, positioningContainerProps),
                React.createElement("div", { className: classNames.root },
                    ariaAlertText && (React.createElement("div", { className: classNames.ariaContainer, role: "alert", ref: this._ariaAlertContainer, "aria-hidden": !isCollapsed }, alertText)),
                    React.createElement("div", { className: classNames.pulsingBeacon }),
                    React.createElement("div", { className: classNames.translateAnimationContainer, ref: this._translateAnimationContainer },
                        React.createElement("div", { className: classNames.scaleAnimationLayer },
                            React.createElement("div", { className: classNames.rotateAnimationLayer },
                                this._positioningContainer.current && isCollapsed && (React.createElement(Beak_1.Beak, { left: beakLeft, top: beakTop, right: beakRight, bottom: beakBottom, direction: this._beakDirection, color: defaultColor })),
                                React.createElement("div", { className: classNames.entityHost, ref: this._entityHost, tabIndex: -1, "data-is-focusable": true, role: "dialog", "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy },
                                    isCollapsed && [
                                        ariaLabelledBy && (React.createElement("p", { id: ariaLabelledBy, key: 0, className: classNames.ariaContainer }, ariaLabelledByText)),
                                        ariaDescribedBy && (React.createElement("p", { id: ariaDescribedBy, key: 1, className: classNames.ariaContainer }, ariaDescribedByText))
                                    ],
                                    React.createElement(FocusTrapZone_1.FocusTrapZone, { isClickableOutsideFocusTrap: true, forceFocusInsideTrap: false },
                                        React.createElement("div", { className: classNames.entityInnerHost, ref: this._entityInnerHostElement },
                                            React.createElement("div", { className: classNames.childrenContainer, ref: this._childrenContainer, "aria-hidden": isCollapsed }, children))))))))));
        };
        // tslint:disable-next-line function-name
        CoachmarkBase.prototype.UNSAFE_componentWillReceiveProps = function (newProps) {
            if (this.props.isCollapsed && !newProps.isCollapsed) {
                // The coachmark is about to open
                this._openCoachmark();
            }
        };
        CoachmarkBase.prototype.shouldComponentUpdate = function (newProps, newState) {
            return !Utilities_1.shallowCompare(newProps, this.props) || !Utilities_1.shallowCompare(newState, this.state);
        };
        CoachmarkBase.prototype.componentDidUpdate = function (prevProps, prevState) {
            if (prevState.targetAlignment !== this.state.targetAlignment || prevState.targetPosition !== this.state.targetPosition) {
                this._setBeakPosition();
            }
            if (prevProps.preventDismissOnLostFocus !== this.props.preventDismissOnLostFocus) {
                this._addListeners();
            }
        };
        CoachmarkBase.prototype.componentDidMount = function () {
            var _this = this;
            this._async.requestAnimationFrame(function () {
                if (_this._entityInnerHostElement.current && _this.state.entityInnerHostRect.width + _this.state.entityInnerHostRect.width === 0) {
                    _this.setState({
                        isMeasuring: false,
                        entityInnerHostRect: {
                            width: _this._entityInnerHostElement.current.offsetWidth,
                            height: _this._entityInnerHostElement.current.offsetHeight
                        },
                        isMeasured: true
                    });
                    _this._setBeakPosition();
                    _this.forceUpdate();
                }
                _this._addListeners();
                // We don't want to the user to immediately trigger the Coachmark when it's opened
                _this._async.setTimeout(function () {
                    _this._addProximityHandler(_this.props.mouseProximityOffset);
                }, _this.props.delayBeforeMouseOpen);
                // Need to add setTimeout to have narrator read change in alert container
                if (_this.props.ariaAlertText) {
                    _this._async.setTimeout(function () {
                        if (_this.props.ariaAlertText && _this._ariaAlertContainer.current) {
                            _this.setState({
                                alertText: _this.props.ariaAlertText
                            });
                        }
                    }, 0);
                }
                if (!_this.props.preventFocusOnMount) {
                    _this._async.setTimeout(function () {
                        if (_this._entityHost.current) {
                            _this._entityHost.current.focus();
                        }
                    }, 1000);
                }
            });
        };
        CoachmarkBase.prototype._addListeners = function () {
            var preventDismissOnLostFocus = this.props.preventDismissOnLostFocus;
            var currentDoc = Utilities_1.getDocument();
            this._events.off();
            if (currentDoc) {
                this._events.on(currentDoc, 'keydown', this._onKeyDown, true);
                if (!preventDismissOnLostFocus) {
                    this._events.on(currentDoc, 'click', this._dismissOnLostFocus, true);
                    this._events.on(currentDoc, 'focus', this._dismissOnLostFocus, true);
                }
            }
        };
        CoachmarkBase.prototype._dismissOnLostFocus = function (ev) {
            var clickTarget = ev.target;
            var clickedOutsideCallout = this._translateAnimationContainer.current && !Utilities_1.elementContains(this._translateAnimationContainer.current, clickTarget);
            var target = this.props.target;
            if (clickedOutsideCallout && clickTarget !== target && !Utilities_1.elementContains(target, clickTarget)) {
                this.dismiss(ev);
            }
        };
        CoachmarkBase.prototype._getBounds = function () {
            var _a = this.props, isPositionForced = _a.isPositionForced, positioningContainerProps = _a.positioningContainerProps;
            if (isPositionForced) {
                // If directionalHint direction is the top or bottom auto edge, then we want to set the left/right bounds
                // to the window x-axis to have auto positioning work correctly.
                if (positioningContainerProps &&
                    (positioningContainerProps.directionalHint === DirectionalHint_1.DirectionalHint.topAutoEdge ||
                        positioningContainerProps.directionalHint === DirectionalHint_1.DirectionalHint.bottomAutoEdge)) {
                    return {
                        left: 0,
                        top: -Infinity,
                        bottom: Infinity,
                        right: window.innerWidth,
                        width: window.innerWidth,
                        height: Infinity
                    };
                }
                else {
                    return {
                        left: -Infinity,
                        top: -Infinity,
                        bottom: Infinity,
                        right: Infinity,
                        width: Infinity,
                        height: Infinity
                    };
                }
            }
            else {
                return undefined;
            }
        };
        CoachmarkBase.prototype._addProximityHandler = function (mouseProximityOffset) {
            var _this = this;
            if (mouseProximityOffset === void 0) { mouseProximityOffset = 0; }
            /**
             * An array of cached ids returned when setTimeout runs during
             * the window resize event trigger.
             */
            var timeoutIds = [];
            // Take the initial measure out of the initial render to prevent
            // an unnecessary render.
            this._async.setTimeout(function () {
                _this._setTargetElementRect();
                // When the window resizes we want to async
                // get the bounding client rectangle.
                // Every time the event is triggered we want to
                // setTimeout and then clear any previous instances
                // of setTimeout.
                _this._events.on(window, 'resize', function () {
                    timeoutIds.forEach(function (value) {
                        clearInterval(value);
                    });
                    timeoutIds.push(_this._async.setTimeout(function () {
                        _this._setTargetElementRect();
                    }, 100));
                });
            }, 10);
            // Every time the document's mouse move is triggered
            // we want to check if inside of an element and
            // set the state with the result.
            this._events.on(document, 'mousemove', function (e) {
                if (_this.state.isCollapsed) {
                    var mouseY = e.clientY;
                    var mouseX = e.clientX;
                    _this._setTargetElementRect();
                    var isMouseInProximity = _this._isInsideElement(mouseX, mouseY, mouseProximityOffset);
                    if (isMouseInProximity !== _this.state.isMouseInProximity) {
                        _this._openCoachmark();
                    }
                }
                if (_this.props.onMouseMove) {
                    _this.props.onMouseMove(e);
                }
            });
        };
        CoachmarkBase.prototype._setTargetElementRect = function () {
            if (this._translateAnimationContainer && this._translateAnimationContainer.current) {
                this._targetElementRect = this._translateAnimationContainer.current.getBoundingClientRect();
            }
        };
        CoachmarkBase.prototype._isInsideElement = function (mouseX, mouseY, mouseProximityOffset) {
            if (mouseProximityOffset === void 0) { mouseProximityOffset = 0; }
            return (mouseX > this._targetElementRect.left - mouseProximityOffset &&
                mouseX < this._targetElementRect.left + this._targetElementRect.width + mouseProximityOffset &&
                mouseY > this._targetElementRect.top - mouseProximityOffset &&
                mouseY < this._targetElementRect.top + this._targetElementRect.height + mouseProximityOffset);
        };
        CoachmarkBase.defaultProps = {
            isCollapsed: true,
            mouseProximityOffset: 10,
            delayBeforeMouseOpen: 3600,
            delayBeforeCoachmarkAnimation: 0,
            isPositionForced: true,
            positioningContainerProps: {
                directionalHint: DirectionalHint_1.DirectionalHint.bottomAutoEdge
            }
        };
        return CoachmarkBase;
    }(Utilities_1.BaseComponent));
    exports.CoachmarkBase = CoachmarkBase;
});
//# sourceMappingURL=Coachmark.base.js.map