import { Subject, Subscription } from 'rxjs';
import { debounceTime, filter, takeUntil, take, switchMap, delay } from 'rxjs/operators';
import { trigger, transition } from '@angular/animations';
import { coerceArray, coerceBooleanProperty } from '@angular/cdk/coercion';
import { ESCAPE } from '@angular/cdk/keycodes';
import { CdkConnectedOverlay, OverlayModule } from '@angular/cdk/overlay';
import { Location, CommonModule } from '@angular/common';
import { EventEmitter, ChangeDetectorRef, Optional, Input, ViewChild, Output, Component, ViewEncapsulation, ChangeDetectionStrategy, NgModule } from '@angular/core';
import { fromOutsideClick, fadeIn, fadeOut } from '@ng-tangram/components/core';

var NtOverlayPosition;
(function (NtOverlayPosition) {
    NtOverlayPosition["Bottom"] = "bottom";
    NtOverlayPosition["BottomLeft"] = "bottomLeft";
    NtOverlayPosition["BottomRight"] = "bottomRight";
    NtOverlayPosition["Top"] = "top";
    NtOverlayPosition["TopLeft"] = "topLeft";
    NtOverlayPosition["TopRight"] = "topRight";
    NtOverlayPosition["Left"] = "left";
    NtOverlayPosition["LeftTop"] = "leftTop";
    NtOverlayPosition["LeftBottom"] = "leftBottom";
    NtOverlayPosition["Right"] = "right";
    NtOverlayPosition["RightTop"] = "rightTop";
    NtOverlayPosition["RightBottom"] = "rightBottom";
})(NtOverlayPosition || (NtOverlayPosition = {}));
var NtOverlayOrientation;
(function (NtOverlayOrientation) {
    NtOverlayOrientation["Vertical"] = "vertical";
    NtOverlayOrientation["Horizontal"] = "horizontal";
})(NtOverlayOrientation || (NtOverlayOrientation = {}));
const [BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT, TOP_LEFT, TOP_CENTER, TOP_RIGHT, LEFT_TOP, LEFT_CENTER, LEFT_BOTTOM, RIGHT_TOP, RIGHT_CENTER, RIGHT_BOTTOM] = [
    getConnectionPositionPair('start', 'bottom', 'start', 'top'),
    getConnectionPositionPair('center', 'bottom', 'center', 'top'),
    getConnectionPositionPair('end', 'bottom', 'end', 'top'),
    getConnectionPositionPair('start', 'top', 'start', 'bottom'),
    getConnectionPositionPair('center', 'top', 'center', 'bottom'),
    getConnectionPositionPair('end', 'top', 'end', 'bottom'),
    getConnectionPositionPair('start', 'top', 'end', 'top'),
    getConnectionPositionPair('start', 'center', 'end', 'center'),
    getConnectionPositionPair('start', 'bottom', 'end', 'bottom'),
    getConnectionPositionPair('end', 'top', 'start', 'top'),
    getConnectionPositionPair('end', 'center', 'start', 'center'),
    getConnectionPositionPair('end', 'bottom', 'start', 'bottom')
];
const NT_OVERLAY_POSITION_PAIRS = {
    bottom: [
        BOTTOM_CENTER, BOTTOM_LEFT, BOTTOM_RIGHT,
        TOP_CENTER, TOP_LEFT, TOP_RIGHT,
        RIGHT_CENTER, RIGHT_TOP, RIGHT_BOTTOM,
        LEFT_CENTER, LEFT_TOP, LEFT_BOTTOM
    ],
    bottomLeft: [
        BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT,
        TOP_LEFT, TOP_CENTER, TOP_RIGHT,
        RIGHT_CENTER, RIGHT_TOP, RIGHT_BOTTOM,
        LEFT_CENTER, LEFT_TOP, LEFT_BOTTOM
    ],
    bottomRight: [
        BOTTOM_RIGHT, BOTTOM_CENTER, BOTTOM_LEFT,
        TOP_RIGHT, TOP_CENTER, TOP_LEFT,
        RIGHT_CENTER, RIGHT_TOP, RIGHT_BOTTOM,
        LEFT_CENTER, LEFT_TOP, LEFT_BOTTOM
    ],
    top: [
        TOP_CENTER, TOP_LEFT, TOP_RIGHT,
        BOTTOM_CENTER, BOTTOM_LEFT, BOTTOM_RIGHT,
        LEFT_CENTER, LEFT_TOP, LEFT_BOTTOM,
        RIGHT_CENTER, RIGHT_TOP, RIGHT_BOTTOM
    ],
    topLeft: [
        TOP_LEFT, TOP_CENTER, TOP_RIGHT,
        BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT,
        LEFT_CENTER, LEFT_TOP, LEFT_BOTTOM,
        RIGHT_CENTER, RIGHT_TOP, RIGHT_BOTTOM
    ],
    topRight: [
        TOP_RIGHT, TOP_CENTER, TOP_LEFT,
        BOTTOM_RIGHT, BOTTOM_CENTER, BOTTOM_LEFT,
        LEFT_CENTER, LEFT_TOP, LEFT_BOTTOM,
        RIGHT_CENTER, RIGHT_TOP, RIGHT_BOTTOM
    ],
    left: [
        LEFT_CENTER, LEFT_TOP, LEFT_BOTTOM,
        TOP_LEFT, TOP_CENTER, TOP_RIGHT,
        BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT,
        RIGHT_CENTER, RIGHT_TOP, RIGHT_BOTTOM
    ],
    leftTop: [
        LEFT_TOP, LEFT_CENTER, LEFT_BOTTOM,
        TOP_LEFT, TOP_CENTER, TOP_RIGHT,
        BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT,
        RIGHT_TOP, RIGHT_CENTER, RIGHT_BOTTOM
    ],
    leftBottom: [
        LEFT_BOTTOM, LEFT_CENTER, LEFT_TOP,
        TOP_LEFT, TOP_CENTER, TOP_RIGHT,
        BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT,
        RIGHT_BOTTOM, RIGHT_CENTER, RIGHT_TOP
    ],
    right: [
        RIGHT_CENTER, RIGHT_TOP, RIGHT_BOTTOM,
        TOP_LEFT, TOP_CENTER, TOP_RIGHT,
        BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT,
        LEFT_CENTER, LEFT_TOP, LEFT_BOTTOM
    ],
    rightTop: [
        RIGHT_TOP, RIGHT_CENTER, RIGHT_BOTTOM,
        TOP_LEFT, TOP_CENTER, TOP_RIGHT,
        BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT,
        LEFT_TOP, LEFT_CENTER, LEFT_BOTTOM
    ],
    rightBottom: [
        RIGHT_BOTTOM, RIGHT_CENTER, RIGHT_TOP,
        TOP_LEFT, TOP_CENTER, TOP_RIGHT,
        BOTTOM_LEFT, BOTTOM_CENTER, BOTTOM_RIGHT,
        LEFT_BOTTOM, LEFT_CENTER, LEFT_TOP
    ],
};
function getConnectionPositionPair(originX, originY, overlayX, overlayY) {
    return { originX, originY, overlayX, overlayY };
}
function getPositionClassName(pair) {
    return `${pair.originX}-${pair.originY}-${pair.overlayX}-${pair.overlayY}`;
}
function getPositionOrientation(position) {
    return Object.keys(NT_OVERLAY_POSITION_PAIRS).indexOf(position) > 5
        ? NtOverlayOrientation.Horizontal
        : NtOverlayOrientation.Vertical;
}

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
let NtOverlayComponent = class NtOverlayComponent {
    constructor(_changeDetectorRef, location) {
        this._changeDetectorRef = _changeDetectorRef;
        this._destroy = new Subject();
        this._debounceClose = new EventEmitter();
        this._positionChange = new EventEmitter();
        this._locationChanges = Subscription.EMPTY;
        this._opened = false;
        this._markClosed = true;
        this._position = NtOverlayPosition.BottomLeft;
        this._positionPairs = NT_OVERLAY_POSITION_PAIRS[this._position];
        this._paddingClass = getPositionClassName(this._positionPairs[0]);
        this._fixed = false;
        this._arrow = false;
        this._nospacing = false;
        this._overlayClass = '';
        this._backdrop = false;
        this.afterOpen = new EventEmitter();
        this.afterClosed = new EventEmitter();
        this.beforeOpen = new EventEmitter();
        this.beforeClosed = new EventEmitter();
        this.overlayEnter = new EventEmitter();
        this.overlayLeave = new EventEmitter();
        this.positionChange = new EventEmitter();
        this.keydownEvents = new EventEmitter();
        this._debounceClose
            .pipe(debounceTime(100), filter(() => this._markClosed), takeUntil(this._destroy))
            .subscribe(() => this.close());
        this._positionChange
            .pipe(filter(position => position !== this._paddingClass), takeUntil(this._destroy))
            .subscribe(position => this._paddingClass = position);
        if (location) {
            this._locationChanges = location.subscribe(() => this.close());
        }
    }
    get opened() { return this._opened; }
    set origin(value) { this._origin = value; }
    get origin() { return this._origin; }
    set position(value) {
        if (value) {
            this._position = value;
            this._positionPairs = NT_OVERLAY_POSITION_PAIRS[value];
        }
        else {
            this._position = NtOverlayPosition.BottomLeft;
        }
    }
    get positionPairs() { return this._positionPairs; }
    set positionPairs(value) {
        this._positionPairs = coerceArray(value);
    }
    get paddingClass() { return this._paddingClass; }
    get fixed() { return this._fixed; }
    set fixed(value) {
        this._fixed = coerceBooleanProperty(value);
    }
    get arrow() { return this._arrow; }
    set arrow(value) {
        this._arrow = coerceBooleanProperty(value);
    }
    get nospacing() { return this._nospacing; }
    set nospacing(value) {
        this._nospacing = coerceBooleanProperty(value);
    }
    get overlayClass() { return this._overlayClass; }
    set overlayClass(value) {
        this._overlayClass = value;
    }
    get backdrop() { return this._backdrop; }
    set backdrop(value) {
        this._backdrop = coerceBooleanProperty(value);
    }
    ngAfterViewInit() {
        this.cdkConnectedOverlay.attach
            .pipe(take(1), switchMap(() => this.cdkConnectedOverlay.overlayRef.keydownEvents()), takeUntil(this._destroy))
            .subscribe(event => {
            if (event.keyCode === ESCAPE) {
                this.close();
            }
            this.keydownEvents.next(event);
        });
        this.cdkConnectedOverlay.attach
            .pipe(delay(0), takeUntil(this._destroy))
            .subscribe(() => this._subscribeOutsideClickEvent());
        this.cdkConnectedOverlay.detach
            .pipe(takeUntil(this._destroy))
            .subscribe(() => this._unsubscribeOutsideClickEvent());
    }
    ngOnChanges(changes) {
        const change = changes.position || changes.fixed || changes.positionPairs;
        if (change && !change.firstChange) {
            this._setPosition();
        }
    }
    ngOnDestroy() {
        this._destroy.next();
        this._destroy.complete();
        this._locationChanges.unsubscribe();
    }
    open() {
        this._opened = true;
        this._markClosed = false;
        this._changeDetectorRef.markForCheck();
    }
    close() {
        this._opened = false;
        this._markClosed = true;
        this._changeDetectorRef.markForCheck();
    }
    toggle() {
        this.opened ? this.close() : this.open();
    }
    markOpen() {
        this.open();
    }
    markClose() {
        this._markClosed = true;
        this._debounceClose.next();
    }
    forceUpdatePosition() {
        var _a;
        if (this.opened) {
            (_a = this.cdkConnectedOverlay.overlayRef) === null || _a === void 0 ? void 0 : _a.updatePosition();
        }
    }
    onAnimationStart(event) {
        if (event.toState === null) {
            this.beforeOpen.next();
        }
        else if (event.toState === 'void') {
            this.beforeClosed.next();
        }
    }
    onAnimationDone(event) {
        if (event.toState === null) {
            this.afterOpen.next();
        }
        else if (event.toState === 'void') {
            this.afterClosed.next();
        }
    }
    onOverlayPositionChange(event) {
        this._positionChange.next(getPositionClassName(event.connectionPair));
    }
    _setPosition() {
        this._positionPairs = this.fixed ?
            this._positionPairs.slice(0, 1) :
            this._positionPairs;
        this._paddingClass = getPositionClassName(this._positionPairs[0]);
    }
    _subscribeOutsideClickEvent() {
        if (!this._outsideClickSubscription) {
            this._outsideClickSubscription = fromOutsideClick([
                this.cdkConnectedOverlay.overlayRef.overlayElement,
                this.origin.elementRef.nativeElement
            ])
                .pipe(takeUntil(this._destroy))
                .subscribe(() => this.close());
        }
    }
    _unsubscribeOutsideClickEvent() {
        if (this._outsideClickSubscription) {
            this._outsideClickSubscription.unsubscribe();
            this._outsideClickSubscription = null;
        }
    }
};
NtOverlayComponent.ctorParameters = () => [
    { type: ChangeDetectorRef },
    { type: Location, decorators: [{ type: Optional }] }
];
__decorate([
    Input()
], NtOverlayComponent.prototype, "origin", null);
__decorate([
    Input()
], NtOverlayComponent.prototype, "position", null);
__decorate([
    Input()
], NtOverlayComponent.prototype, "positionPairs", null);
__decorate([
    Input()
], NtOverlayComponent.prototype, "fixed", null);
__decorate([
    Input()
], NtOverlayComponent.prototype, "arrow", null);
__decorate([
    Input()
], NtOverlayComponent.prototype, "nospacing", null);
__decorate([
    Input()
], NtOverlayComponent.prototype, "overlayClass", null);
__decorate([
    Input()
], NtOverlayComponent.prototype, "backdrop", null);
__decorate([
    ViewChild(CdkConnectedOverlay, { static: true })
], NtOverlayComponent.prototype, "cdkConnectedOverlay", void 0);
__decorate([
    Output()
], NtOverlayComponent.prototype, "afterOpen", void 0);
__decorate([
    Output()
], NtOverlayComponent.prototype, "afterClosed", void 0);
__decorate([
    Output()
], NtOverlayComponent.prototype, "beforeOpen", void 0);
__decorate([
    Output()
], NtOverlayComponent.prototype, "beforeClosed", void 0);
__decorate([
    Output()
], NtOverlayComponent.prototype, "overlayEnter", void 0);
__decorate([
    Output()
], NtOverlayComponent.prototype, "overlayLeave", void 0);
__decorate([
    Output()
], NtOverlayComponent.prototype, "positionChange", void 0);
__decorate([
    Output()
], NtOverlayComponent.prototype, "keydownEvents", void 0);
NtOverlayComponent = __decorate([
    Component({
        selector: 'nt-overlay, [nt-overlay]',
        template: "<ng-template\n  cdk-connected-overlay\n  [cdkConnectedOverlayOpen]=\"opened\"\n  [cdkConnectedOverlayHasBackdrop]=\"backdrop\"\n  [cdkConnectedOverlayPositions]=\"positionPairs\"\n  [cdkConnectedOverlayOrigin]=\"origin\"\n  (positionChange)=\"onOverlayPositionChange($event)\"\n  (backdropClick)=\"close()\">\n  <div class=\"nt-overlay-container {{paddingClass}} {{overlayClass}}\"\n    (mouseenter)=\"overlayEnter.emit($event)\"\n    (mouseleave)=\"overlayLeave.emit($event)\"\n    (click)=\"$event.stopPropagation()\"\n    [class.nospacing]=\"nospacing\"\n    [@fade]\n    (@fade.start)=\"onAnimationStart($event)\"\n    (@fade.done)=\"onAnimationDone($event)\">\n    <div class=\"nt-overlay-shadow\"></div>\n    <div class=\"nt-overlay-arrow\" *ngIf=\"arrow\"></div>\n    <div class=\"nt-overlay-pane\">\n      <ng-content></ng-content>\n    </div>\n  </div>\n</ng-template>\n",
        animations: [
            trigger('fade', [
                transition('void => *', fadeIn(.15)),
                transition('* => void', fadeOut(.15))
            ])
        ],
        encapsulation: ViewEncapsulation.None,
        changeDetection: ChangeDetectionStrategy.OnPush
    }),
    __param(1, Optional())
], NtOverlayComponent);

var __decorate$1 = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
let NtOverlayModule = class NtOverlayModule {
};
NtOverlayModule = __decorate$1([
    NgModule({
        imports: [CommonModule, OverlayModule],
        exports: [NtOverlayComponent],
        declarations: [NtOverlayComponent],
    })
], NtOverlayModule);

export { BOTTOM_CENTER, BOTTOM_LEFT, BOTTOM_RIGHT, LEFT_BOTTOM, LEFT_CENTER, LEFT_TOP, NT_OVERLAY_POSITION_PAIRS, NtOverlayComponent, NtOverlayModule, NtOverlayOrientation, NtOverlayPosition, RIGHT_BOTTOM, RIGHT_CENTER, RIGHT_TOP, TOP_CENTER, TOP_LEFT, TOP_RIGHT, getConnectionPositionPair, getPositionClassName, getPositionOrientation };
//# sourceMappingURL=overlay.js.map
