import { OverlayConfig, Overlay, OverlayModule } from '@angular/cdk/overlay';
import { BasePortalOutlet, CdkPortalOutlet, ComponentPortal, TemplatePortal, PortalInjector, PortalModule } from '@angular/cdk/portal';
import { Location, CommonModule } from '@angular/common';
import { Component, EventEmitter, ViewChild, ViewEncapsulation, InjectionToken, TemplateRef, Optional, Inject, Injector, Injectable, NgModule } from '@angular/core';
import { trigger, transition } from '@angular/animations';
import { fadeInY, fadeOutY } from '@ng-tangram/components/core';
import { Subject, Subscription } from 'rxjs';
import { filter, take } from 'rxjs/operators';
import { ESCAPE } from '@angular/cdk/keycodes';

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;
};
let NtModalBodyComponent = class NtModalBodyComponent {
};
NtModalBodyComponent = __decorate([
    Component({
        selector: 'nt-modal-body',
        template: `<ng-content></ng-content>`,
        host: {
            'class': 'nt-modal-body'
        }
    })
], NtModalBodyComponent);

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 NtModalFooterComponent = class NtModalFooterComponent {
};
NtModalFooterComponent = __decorate$1([
    Component({
        selector: 'nt-modal-footer',
        template: `<ng-content></ng-content>`,
        host: {
            'class': 'nt-modal-footer'
        }
    })
], NtModalFooterComponent);

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;
};
let NtModalHeaderComponent = class NtModalHeaderComponent {
};
NtModalHeaderComponent = __decorate$2([
    Component({
        selector: 'nt-modal-header',
        template: `<ng-content></ng-content>`,
        host: {
            class: 'nt-modal-header'
        }
    })
], NtModalHeaderComponent);

var __decorate$3 = (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;
};
function throwNtModalContentAlreadyAttachedError() {
    throw Error('Attempting to attach modal content after content is already attached');
}
let NtModalComponent = class NtModalComponent extends BasePortalOutlet {
    constructor() {
        super();
        this.state = 'enter';
        this.animationStateChanged = new EventEmitter();
    }
    set config(value) { this._config = value; }
    get config() { return this._config; }
    attachComponentPortal(portal) {
        if (this._portalOutlet.hasAttached()) {
            throwNtModalContentAlreadyAttachedError();
        }
        return this._portalOutlet.attachComponentPortal(portal);
    }
    attachTemplatePortal(portal) {
        if (this._portalOutlet.hasAttached()) {
            throwNtModalContentAlreadyAttachedError();
        }
        return this._portalOutlet.attachTemplatePortal(portal);
    }
    onAnimationDone(event) {
        this.animationStateChanged.emit(event);
    }
    onAnimationStart(event) {
        this.animationStateChanged.emit(event);
    }
    exit() {
        this.state = 'exit';
    }
};
__decorate$3([
    ViewChild(CdkPortalOutlet, { static: true })
], NtModalComponent.prototype, "_portalOutlet", void 0);
NtModalComponent = __decorate$3([
    Component({
        selector: 'nt-modal',
        template: `
    <ng-template cdkPortalOutlet></ng-template>
    <button *ngIf="config.closable" (click)="exit()" class="close-button" type="button">
      <span aria-hidden="true">&times;</span>
    </button>
  `,
        encapsulation: ViewEncapsulation.None,
        animations: [
            trigger('fade', [
                transition('void => *', fadeInY({ a: '-10%', b: 0 }, .2)),
                transition('* => exit', fadeOutY({ a: 0, b: '-10%' }, .2))
            ])
        ],
        host: {
            'class': 'reveal',
            '[class.reveal-transparent]': '_config.transparent',
            '[style.width]': '_config.width',
            '[style.height]': '_config.height',
            '[@fade]': 'state',
            '(@fade.start)': 'onAnimationStart($event)',
            '(@fade.done)': 'onAnimationDone($event)',
        }
    })
], NtModalComponent);

class NtModalConfig {
    constructor() {
        this.top = '80px';
        this.width = '600px';
        this.height = 'auto';
        this.maxWidth = '80vw';
        this.closable = true;
        this.data = {};
        this.panelClass = 'tm-file-preview-modal-panel';
        this.hasBackdrop = true;
        this.backdropClass = 'dark-backdrop';
        this.centerVertically = false;
        this.transparent = false;
    }
}

let uniqueId = 0;
class NtModalRef {
    constructor(_overlayRef, _containerInstance, location, id = `nt-modal-${uniqueId++}`) {
        this._overlayRef = _overlayRef;
        this._containerInstance = _containerInstance;
        this.id = id;
        this.closable = this._containerInstance.config.closable;
        this._afterOpen = new Subject();
        this._afterClosed = new Subject();
        this._beforeClose = new Subject();
        this._locationChanges = Subscription.EMPTY;
        _containerInstance.animationStateChanged
            .pipe(filter(event => event.phaseName === 'done' && event.toState === 'enter'), take(1))
            .subscribe(() => {
            this._afterOpen.next();
            this._afterOpen.complete();
        });
        _containerInstance.animationStateChanged
            .pipe(filter(event => event.phaseName === 'done' && event.toState === 'exit'), take(1))
            .subscribe(() => {
            this._overlayRef.dispose();
            this._locationChanges.unsubscribe();
            this._afterClosed.next(this._result);
            this._afterClosed.complete();
            this.componentInstance = null;
        });
        _overlayRef.keydownEvents()
            .pipe(filter(event => event.keyCode === ESCAPE && !!this.closable))
            .subscribe(() => this.close());
        if (location) {
            this._locationChanges = location.subscribe(() => this.close());
        }
    }
    close(modalResult) {
        this._result = modalResult;
        this._containerInstance.animationStateChanged
            .pipe(filter(event => event.phaseName === 'start'), take(1))
            .subscribe(() => {
            this._beforeClose.next(modalResult);
            this._beforeClose.complete();
            this._overlayRef.detachBackdrop();
        });
        this._containerInstance.exit();
    }
    afterOpen() {
        return this._afterOpen.asObservable();
    }
    afterClosed() {
        return this._afterClosed.asObservable();
    }
    beforeClose() {
        return this._beforeClose.asObservable();
    }
    backdropClick() {
        return this._overlayRef.backdropClick();
    }
    keydownEvents() {
        return this._overlayRef.keydownEvents();
    }
    updateSize(width = 'auto', height = 'auto') {
        this._getPositionStrategy().width(width).height(height);
        this._overlayRef.updatePosition();
        return this;
    }
    _getPositionStrategy() {
        return this._overlayRef.getConfig().positionStrategy;
    }
}

var __decorate$4 = (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); }
};
const NT_MODAL_DATA = new InjectionToken('nt-modal-data');
const NT_MODAL_DEFAULT_CONFIG = new InjectionToken('nt-model-default-config');
let NtModal = class NtModal {
    constructor(_location, _defaultConfig, _overlay, _injector) {
        this._location = _location;
        this._defaultConfig = _defaultConfig;
        this._overlay = _overlay;
        this._injector = _injector;
        this._openModalsAtThisLevel = [];
        this._afterAllClosedAtThisLevel = new Subject();
        this._afterOpenAtThisLevel = new Subject();
    }
    open(content, config = {}) {
        config = Object.assign(Object.assign({}, this._defaultConfig || new NtModalConfig()), config);
        const overlayRef = this._createOverlay(config);
        const modalContainerRef = this._attachModalContainer(overlayRef, config);
        const modalRef = this._attachModalContent(content, modalContainerRef, overlayRef, config);
        this._openModalsAtThisLevel.push(modalRef);
        modalRef.afterClosed().subscribe(() => this._removeOpenModal(modalRef));
        this._afterOpenAtThisLevel.next(modalRef);
        return modalRef;
    }
    _createOverlay(config) {
        const overlayConfig = this._getOverlayConfig(config);
        return this._overlay.create(overlayConfig);
    }
    _attachModalContainer(overlayRef, config) {
        const containerPortal = new ComponentPortal(NtModalComponent, null);
        const containerRef = overlayRef.attach(containerPortal);
        containerRef.instance.config = config;
        return containerRef.instance;
    }
    _attachModalContent(content, modalContainer, overlayRef, config) {
        const modalRef = new NtModalRef(overlayRef, modalContainer, this._location, config.id);
        if (config.hasBackdrop) {
            overlayRef.backdropClick().subscribe(() => {
                if (modalRef.closable) {
                    modalRef.close();
                }
            });
        }
        if (content instanceof TemplateRef) {
            modalContainer.attachTemplatePortal(new TemplatePortal(content, null, { $implicit: config.data, modalRef }));
        }
        else {
            const injector = this._createInjector(config, modalRef, modalContainer);
            const contentRef = modalContainer.attachComponentPortal(new ComponentPortal(content, undefined, injector));
            modalRef.componentInstance = contentRef.instance;
        }
        return modalRef;
    }
    _removeOpenModal(modalRef) {
        const index = this._openModalsAtThisLevel.indexOf(modalRef);
        if (index > -1) {
            this._openModalsAtThisLevel.splice(index, 1);
            if (!this._openModalsAtThisLevel.length) {
                this._afterAllClosedAtThisLevel.next();
            }
        }
    }
    _createInjector(config, modalRef, modalContainer) {
        const injector = config && config.viewContainerRef && config.viewContainerRef.injector;
        const injectionTokens = new WeakMap();
        injectionTokens.set(NtModalRef, modalRef);
        injectionTokens.set(NtModalComponent, modalContainer);
        injectionTokens.set(NT_MODAL_DATA, config.data);
        return new PortalInjector(injector || this._injector, injectionTokens);
    }
    _getOverlayConfig(config) {
        const positionStrategy = this._overlay.position()
            .global()
            .centerHorizontally();
        const overlayConfig = new OverlayConfig({
            hasBackdrop: config.hasBackdrop,
            backdropClass: config.backdropClass,
            panelClass: config.panelClass,
            scrollStrategy: this._overlay.scrollStrategies.block(),
            minWidth: config.minWidth,
            minHeight: config.minHeight,
            maxWidth: config.maxWidth,
            maxHeight: config.maxHeight,
            positionStrategy: config.centerVertically
                ? positionStrategy.centerVertically()
                : positionStrategy.top(config.top)
        });
        return overlayConfig;
    }
};
NtModal.ctorParameters = () => [
    { type: Location, decorators: [{ type: Optional }] },
    { type: NtModalConfig, decorators: [{ type: Optional }, { type: Inject, args: [NT_MODAL_DEFAULT_CONFIG,] }] },
    { type: Overlay },
    { type: Injector }
];
NtModal = __decorate$4([
    Injectable(),
    __param(0, Optional()),
    __param(1, Optional()), __param(1, Inject(NT_MODAL_DEFAULT_CONFIG))
], NtModal);

var __decorate$5 = (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;
};
const EXPORTS_DECLARATIONS = [
    NtModalComponent,
    NtModalHeaderComponent,
    NtModalBodyComponent,
    NtModalFooterComponent
];
let NtModalModule = class NtModalModule {
};
NtModalModule = __decorate$5([
    NgModule({
        imports: [
            CommonModule,
            PortalModule,
            OverlayModule
        ],
        declarations: EXPORTS_DECLARATIONS,
        exports: EXPORTS_DECLARATIONS,
        entryComponents: [NtModalComponent],
        providers: [NtModal]
    })
], NtModalModule);

export { NT_MODAL_DATA, NT_MODAL_DEFAULT_CONFIG, NtModal, NtModalBodyComponent, NtModalComponent, NtModalConfig, NtModalFooterComponent, NtModalHeaderComponent, NtModalModule, NtModalRef, throwNtModalContentAlreadyAttachedError };
//# sourceMappingURL=modal.js.map
