import { Subject, Subscription } from 'rxjs';
import { filter, take } from 'rxjs/operators';
import { ESCAPE } from '@angular/cdk/keycodes';
import { trigger, transition } from '@angular/animations';
import { CdkPortalOutlet, BasePortalOutlet, ComponentPortal, TemplatePortal, PortalModule } from '@angular/cdk/portal';
import { EventEmitter, ViewChild, Component, ViewEncapsulation, TemplateRef, ElementRef, Optional, Input, Directive, NgModule } from '@angular/core';
import { fadeIn, fadeOut } from '@ng-tangram/components/core';
import { OverlayConfig, Overlay, OverlayContainer, OverlayModule } from '@angular/cdk/overlay';
import { Location, CommonModule } from '@angular/common';

var uniqueId = 0;
var NtContextMenuRef = (function () {
    function NtContextMenuRef(_overlayRef, _containerInstance, location, id) {
        var _this = this;
        if (id === void 0) { id = "nt-contextmenu-" + uniqueId++; }
        this._overlayRef = _overlayRef;
        this._containerInstance = _containerInstance;
        this.id = id;
        this._afterOpen = new Subject();
        this._afterClosed = new Subject();
        this._beforeClose = new Subject();
        this._locationChanges = Subscription.EMPTY;
        NtContextMenuRef.currentRef = this;
        _containerInstance.animationStateChanged
            .pipe(filter(function (event) { return event.phaseName === 'done' && event.toState === 'enter'; }), take(1))
            .subscribe(function () {
            _this._afterOpen.next();
            _this._afterOpen.complete();
        });
        _containerInstance.animationStateChanged
            .pipe(filter(function (event) { return event.phaseName === 'done' && event.toState === 'exit'; }), take(1))
            .subscribe(function () {
            _this._overlayRef.dispose();
            _this._locationChanges.unsubscribe();
            _this._afterClosed.next();
            _this._afterClosed.complete();
            _this.templateInstance = null;
        });
        _overlayRef.keydownEvents()
            .pipe(filter(function (event) { return event.keyCode === ESCAPE; }))
            .subscribe(function () { return _this.close(); });
        if (location) {
            this._locationChanges = location.subscribe(function () { return _this.close(); });
        }
    }
    NtContextMenuRef.prototype.close = function () {
        var _this = this;
        this._containerInstance.animationStateChanged
            .pipe(filter(function (event) { return event.phaseName === 'start'; }), take(1))
            .subscribe(function () {
            _this._beforeClose.next();
            _this._beforeClose.complete();
            _this._overlayRef.detachBackdrop();
        });
        this._containerInstance.exit();
    };
    NtContextMenuRef.prototype.afterOpen = function () {
        return this._afterOpen.asObservable();
    };
    NtContextMenuRef.prototype.afterClosed = function () {
        return this._afterClosed.asObservable();
    };
    NtContextMenuRef.prototype.beforeClose = function () {
        return this._beforeClose.asObservable();
    };
    NtContextMenuRef.prototype.backdropClick = function () {
        return this._overlayRef.backdropClick();
    };
    NtContextMenuRef.prototype.keydownEvents = function () {
        return this._overlayRef.keydownEvents();
    };
    NtContextMenuRef.prototype._getPositionStrategy = function () {
        return this._overlayRef.getConfig().positionStrategy;
    };
    return NtContextMenuRef;
}());

var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
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 NtContextMenuComponent = (function (_super) {
    __extends(NtContextMenuComponent, _super);
    function NtContextMenuComponent() {
        var _this = _super.call(this) || this;
        _this.state = 'enter';
        _this.animationStateChanged = new EventEmitter();
        return _this;
    }
    NtContextMenuComponent.prototype.attachComponentPortal = function (portal) {
        if (this._portalOutlet.hasAttached()) {
            throw new Error('Attempting to attach context menu content after content is already attached');
        }
        return this._portalOutlet.attachComponentPortal(portal);
    };
    NtContextMenuComponent.prototype.attachTemplatePortal = function (portal) {
        if (this._portalOutlet.hasAttached()) {
            throw new Error('Attempting to attach context menu content after content is already attached');
        }
        return this._portalOutlet.attachTemplatePortal(portal);
    };
    NtContextMenuComponent.prototype.onAnimationDone = function (event) {
        this.animationStateChanged.emit(event);
    };
    NtContextMenuComponent.prototype.onAnimationStart = function (event) {
        this.animationStateChanged.emit(event);
    };
    NtContextMenuComponent.prototype.exit = function () {
        this.state = 'exit';
    };
    NtContextMenuComponent.prototype._onInteractionEvent = function (event) {
        event.stopPropagation();
        return false;
    };
    __decorate([
        ViewChild(CdkPortalOutlet, { static: true })
    ], NtContextMenuComponent.prototype, "_portalOutlet", void 0);
    NtContextMenuComponent = __decorate([
        Component({
            selector: 'nt-contextmenu',
            template: "\n    <div class=\"nt-overlay-container start-bottom-start-top\">\n      <div class=\"nt-overlay-shadow\"></div>\n      <div class=\"nt-overlay-pane\">\n        <ng-template cdkPortalOutlet></ng-template>\n      </div>\n    </div>\n  ",
            encapsulation: ViewEncapsulation.None,
            animations: [
                trigger('fade', [
                    transition('void => *', fadeIn(.05)),
                    transition('* => exit', fadeOut(.1))
                ])
            ],
            host: {
                'class': 'nt-contextmenu',
                '(contextmenu)': '_onInteractionEvent($event)',
                '[@fade]': 'state',
                '(@fade.start)': 'onAnimationStart($event)',
                '(@fade.done)': 'onAnimationDone($event)',
            }
        })
    ], NtContextMenuComponent);
    return NtContextMenuComponent;
}(BasePortalOutlet));

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;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var NtContextMenuDirective = (function () {
    function NtContextMenuDirective(_location, _elementRef, _overlay, _overlayContainer) {
        this._location = _location;
        this._elementRef = _elementRef;
        this._overlay = _overlay;
        this._overlayContainer = _overlayContainer;
    }
    Object.defineProperty(NtContextMenuDirective.prototype, "template", {
        get: function () { return this._template; },
        set: function (value) {
            if (value instanceof TemplateRef) {
                this._template = value;
            }
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(NtContextMenuDirective.prototype, "data", {
        get: function () { return this._data; },
        set: function (value) { this._data = value; },
        enumerable: true,
        configurable: true
    });
    NtContextMenuDirective.prototype._open = function (event) {
        if (NtContextMenuRef.currentRef) {
            NtContextMenuRef.currentRef.close();
        }
        if (event) {
            var overlayRef = this._createOverlay(event.offsetX, event.offsetY, event.target);
            var menuContainerRef = this._attachModalContainer(overlayRef);
            var menuRef = this._attachModalContent(this.template, menuContainerRef, overlayRef);
        }
        return false;
    };
    NtContextMenuDirective.prototype._createOverlay = function (x, y, element) {
        var elementRef = this._elementRef;
        if (element && element !== elementRef.nativeElement) {
            elementRef = new ElementRef(element);
        }
        var overlayConfig = this._getOverlayConfig(x, y, elementRef);
        return this._overlay.create(overlayConfig);
    };
    NtContextMenuDirective.prototype._attachModalContainer = function (overlayRef) {
        var containerPortal = new ComponentPortal(NtContextMenuComponent, null);
        var containerRef = overlayRef.attach(containerPortal);
        return containerRef.instance;
    };
    NtContextMenuDirective.prototype._attachModalContent = function (content, menuContainer, overlayRef) {
        var menuRef = new NtContextMenuRef(overlayRef, menuContainer, this._location);
        var overlayClose = function () {
            menuRef.close();
            return false;
        };
        overlayRef.backdropClick().subscribe(overlayClose);
        if (overlayRef.backdropElement) {
            overlayRef.backdropElement.oncontextmenu = overlayClose;
        }
        menuContainer.attachTemplatePortal(new TemplatePortal(content, null, { $implicit: this.data, menuRef: menuRef }));
        return menuRef;
    };
    NtContextMenuDirective.prototype._getOverlayConfig = function (x, y, elementRef) {
        var position = {
            originX: 'start', originY: 'top',
            overlayX: 'start', overlayY: 'top'
        };
        var positionStrategy = this._overlay
            .position()
            .flexibleConnectedTo(elementRef)
            .withPositions([position])
            .withDefaultOffsetX(x)
            .withDefaultOffsetY(y);
        var overlayConfig = new OverlayConfig({
            scrollStrategy: this._overlay.scrollStrategies.block(),
            positionStrategy: positionStrategy,
            hasBackdrop: true
        });
        return overlayConfig;
    };
    NtContextMenuDirective.ctorParameters = function () { return [
        { type: Location, decorators: [{ type: Optional }] },
        { type: ElementRef },
        { type: Overlay },
        { type: OverlayContainer }
    ]; };
    __decorate$1([
        Input()
    ], NtContextMenuDirective.prototype, "template", null);
    __decorate$1([
        Input()
    ], NtContextMenuDirective.prototype, "data", null);
    NtContextMenuDirective = __decorate$1([
        Directive({
            selector: '[ntContextMenu]',
            host: {
                '(contextmenu)': '_open($event)'
            }
        }),
        __param(0, Optional())
    ], NtContextMenuDirective);
    return NtContextMenuDirective;
}());

var __decorate$2 = (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 NtContextMenuModule = (function () {
    function NtContextMenuModule() {
    }
    NtContextMenuModule = __decorate$2([
        NgModule({
            imports: [
                CommonModule,
                PortalModule,
                OverlayModule
            ],
            exports: [NtContextMenuDirective],
            declarations: [
                NtContextMenuComponent,
                NtContextMenuDirective
            ]
        })
    ], NtContextMenuModule);
    return NtContextMenuModule;
}());

export { NtContextMenuComponent, NtContextMenuDirective, NtContextMenuModule, NtContextMenuRef };
//# sourceMappingURL=contextmenu.js.map
