import { Directive, TemplateRef, EventEmitter, Component, ViewEncapsulation, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, ContentChild, Input, Output, HostListener, ElementRef, NgZone, ViewContainerRef, Optional, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { __classPrivateFieldGet, __classPrivateFieldSet } from 'tslib';
import { v4 } from 'uuid';
import { DeviceDetectorService } from 'ngx-device-detector';
import { BehaviorSubject, Subscription, Subject, merge, fromEvent } from 'rxjs';
import { Directionality } from '@angular/cdk/bidi';
import { OverlayConfig, Overlay } from '@angular/cdk/overlay';
import { Platform } from '@angular/cdk/platform';
import { TemplatePortal } from '@angular/cdk/portal';
import { mapTo, filter, debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { A11yModule } from '@angular/cdk/a11y';

class PopoverContentDirective {
    constructor(templateRef) {
        this.templateRef = templateRef;
    }
}
PopoverContentDirective.decorators = [
    { type: Directive, args: [{
                selector: '[sdPopoverContent]'
            },] }
];
PopoverContentDirective.ctorParameters = () => [
    { type: TemplateRef }
];

var _previousPanelClass, _xPosition;
class PopoverComponent {
    constructor(cdRef, deviceService) {
        this.cdRef = cdRef;
        this.deviceService = deviceService;
        this.classList = {};
        this.panelId = `sd-popover-panel-${v4()}`;
        this.isMobileOrTablet = false;
        this.mouseState$ = new BehaviorSubject(false);
        this.trigger = null;
        _previousPanelClass.set(this, void 0);
        this.width = 'sm';
        this.height = 'auto';
        this.type = 'normal';
        _xPosition.set(this, void 0);
        this.closed = new EventEmitter();
        this.opened = new EventEmitter();
        this.close = () => {
            this.mouseState$.next(false);
            this.closed.emit();
        };
        this.setPositionClasses = (pos = this.position) => {
            var _a;
            const classes = this.classList;
            classes['sd-popover-above'] = pos === 'above';
            classes['sd-popover-below'] = pos === 'below';
            (_a = this.cdRef) === null || _a === void 0 ? void 0 : _a.markForCheck();
        };
        this.addArrowTranslateX = (offset) => {
            const arrowElement = document.querySelector(`#${this.panelId} .sd-popover-arrow`);
            if (arrowElement && offset) {
                try {
                    const style = window.getComputedStyle(arrowElement);
                    const matrix = new WebKitCSSMatrix(style.transform);
                    const translateX = matrix.m41 + offset;
                    const translateY = matrix.m42;
                    arrowElement.style.transform = `translateX(${translateX}px) translateY(${translateY}px)`;
                }
                catch (error) { }
            }
        };
        this.setMouseState = (visible) => {
            if (!visible) {
                // chỉ được tắt khi đang không focus element nào bên trong panel
                // tránh lỗi có control mở overlay khiến cho mất mouseenter ở panel
                const activeElement = document.activeElement;
                const panelElement = this.panel.nativeElement;
                if (panelElement === null || panelElement === void 0 ? void 0 : panelElement.contains(activeElement)) {
                    return;
                }
            }
            this.mouseState$.next(visible);
        };
        this.isMobileOrTablet = !deviceService.isDesktop();
    }
    set panelClass(classes) {
        const previousPanelClass = __classPrivateFieldGet(this, _previousPanelClass);
        if (previousPanelClass && previousPanelClass.length) {
            previousPanelClass.split(' ').forEach((className) => {
                this.classList[className] = false;
            });
        }
        __classPrivateFieldSet(this, _previousPanelClass, classes);
        if (classes && classes.length) {
            classes.split(' ').forEach((className) => {
                this.classList[className] = true;
            });
        }
    }
    ;
    get position() {
        return __classPrivateFieldGet(this, _xPosition);
    }
    set position(value) {
        __classPrivateFieldSet(this, _xPosition, value);
        this.setPositionClasses();
    }
    _hostClick(targetElement) {
        var _a;
        if ((_a = this.panel) === null || _a === void 0 ? void 0 : _a.nativeElement) {
            const isInside = this.panel.nativeElement.contains(targetElement);
            if (!isInside) {
                this.setMouseState(false);
            }
        }
    }
    ngOnChanges(changes) {
        if (changes.type) {
            const type = changes.type.currentValue;
            const preType = changes.type.previousValue;
            if (preType) {
                this.classList[`sd-popover--${preType}`] = false;
            }
            if (type) {
                this.classList[`sd-popover--${type}`] = true;
            }
        }
    }
    ngOnInit() {
        this.setPositionClasses();
        this.width = this.width || '80vw';
        if (!this.isMobileOrTablet) {
            switch (this.width) {
                case 'lg':
                    this.width = '80vw';
                    break;
                case 'md':
                    this.width = '60vw';
                    break;
                case 'sm':
                    this.width = '40vw';
                    break;
            }
        }
    }
    ngOnDestroy() {
        this.closed.complete();
        this.opened.complete();
        this.mouseState$.complete();
    }
}
_previousPanelClass = new WeakMap(), _xPosition = new WeakMap();
PopoverComponent.decorators = [
    { type: Component, args: [{
                selector: 'sd-popover',
                template: "<ng-template let-data=\"data\">\r\n  <div\r\n    class=\"sd-popover-panel mat-elevation-z6\"\r\n    [id]=\"panelId\"\r\n    [ngClass]=\"classList\"\r\n    tabindex=\"-1\"\r\n    role=\"menu\"\r\n    (mouseenter)=\"setMouseState(true)\"\r\n    (mouseleave)=\"setMouseState(false)\"\r\n    cdkTrapFocus\r\n    #panel\r\n  >\r\n    <div class=\"sd-popover-content\">\r\n      <ng-container *ngIf=\"popoverContent?.templateRef\">\r\n        <ng-container *ngTemplateOutlet=\"popoverContent.templateRef; context:{data: data}\"></ng-container>\r\n      </ng-container>\r\n      <ng-content></ng-content>\r\n    </div>\r\n    <div class=\"sd-popover-arrow\"></div>\r\n  </div>\r\n</ng-template>",
                encapsulation: ViewEncapsulation.None,
                exportAs: 'sdPopover',
                changeDetection: ChangeDetectionStrategy.OnPush,
                styles: [".text-black400{color:#757575}.sd-popover-panel{background:#fff;height:100%;position:relative;width:100%}.sd-popover-panel .sd-popover-arrow{clear:both;height:0;left:50%;position:absolute;width:0}.sd-popover-panel.sd-popover-above .sd-popover-arrow{border-color:#fff transparent transparent;border-style:solid;border-width:12px 12px 0;top:100%;transform:translateX(-6px) translateY(-1px)}.sd-popover-panel.sd-popover-above:after{content:\" \";display:block;height:16px;position:absolute;width:100%}.sd-popover-panel.sd-popover-below .sd-popover-arrow{border-color:transparent transparent #fff;border-style:solid;border-width:0 12px 12px;bottom:100%;transform:translateX(-6px) translateY(1px)}.sd-popover-panel.sd-popover-below:before{content:\" \";display:block;height:16px;position:absolute;width:100%}.sd-popover-panel .sd-popover-content{height:100%}.sd-popover--normal{background:#fff;color:#000}.sd-popover--normal.sd-popover-above .sd-popover-arrow{border-color:#fff transparent transparent;border-style:solid;border-width:12px 12px 0;top:100%}.sd-popover--normal.sd-popover-below .sd-popover-arrow{border-color:transparent transparent #fff;border-style:solid;border-width:0 12px 12px;bottom:100%}.sd-popover--primary{background:#e7e9ff;color:#2962ff}.sd-popover--primary.sd-popover-above .sd-popover-arrow{border-color:#e7e9ff transparent transparent;border-style:solid;border-width:12px 12px 0;top:100%}.sd-popover--primary.sd-popover-below .sd-popover-arrow{border-color:transparent transparent #e7e9ff;border-style:solid;border-width:0 12px 12px;bottom:100%}.sd-popover--info{background:#e7e9ff;color:#2962ff}.sd-popover--info.sd-popover-above .sd-popover-arrow{border-color:#e7e9ff transparent transparent;border-style:solid;border-width:12px 12px 0;top:100%}.sd-popover--info.sd-popover-below .sd-popover-arrow{border-color:transparent transparent #e7e9ff;border-style:solid;border-width:0 12px 12px;bottom:100%}.sd-popover--success{background:#dbefdc;color:#4caf50}.sd-popover--success.sd-popover-above .sd-popover-arrow{border-color:#dbefdc transparent transparent;border-style:solid;border-width:12px 12px 0;top:100%}.sd-popover--success.sd-popover-below .sd-popover-arrow{border-color:transparent transparent #dbefdc;border-style:solid;border-width:0 12px 12px;bottom:100%}.sd-popover--warning{background:#ffeacc;color:#ff9600}.sd-popover--warning.sd-popover-above .sd-popover-arrow{border-color:#ffeacc transparent transparent;border-style:solid;border-width:12px 12px 0;top:100%}.sd-popover--warning.sd-popover-below .sd-popover-arrow{border-color:transparent transparent #ffeacc;border-style:solid;border-width:0 12px 12px;bottom:100%}.sd-popover--danger{background:#fed5d0;color:#f82c13}.sd-popover--danger.sd-popover-above .sd-popover-arrow{border-color:#fed5d0 transparent transparent;border-style:solid;border-width:12px 12px 0;top:100%}.sd-popover--danger.sd-popover-below .sd-popover-arrow{border-color:transparent transparent #fed5d0;border-style:solid;border-width:0 12px 12px;bottom:100%}.sd-popover-content{padding:16px}"]
            },] }
];
PopoverComponent.ctorParameters = () => [
    { type: ChangeDetectorRef },
    { type: DeviceDetectorService }
];
PopoverComponent.propDecorators = {
    templateRef: [{ type: ViewChild, args: [TemplateRef,] }],
    panel: [{ type: ViewChild, args: ['panel',] }],
    popoverContent: [{ type: ContentChild, args: [PopoverContentDirective,] }],
    panelClass: [{ type: Input, args: ['class',] }],
    width: [{ type: Input }],
    height: [{ type: Input }],
    type: [{ type: Input }],
    position: [{ type: Input }],
    closed: [{ type: Output }],
    opened: [{ type: Output }],
    _hostClick: [{ type: HostListener, args: ['document:click', ['$event.target'],] }]
};

var _overlayRef, _popoverClose$, _portal, _destroy$, _popover, _setIsPopoverOpen, _getPortal, _createOverlay, _setPosition, _getOverlayConfig, _subscribeToPositions, _destroyPopover;
class PopoverTriggerDirective {
    constructor(_overlay, _element, _ngZone, viewContainerRef, elementRef, platform, _dir) {
        this._overlay = _overlay;
        this._element = _element;
        this._ngZone = _ngZone;
        this.viewContainerRef = viewContainerRef;
        this.elementRef = elementRef;
        this.platform = platform;
        this._dir = _dir;
        _overlayRef.set(this, null);
        _popoverClose$.set(this, Subscription.EMPTY);
        _portal.set(this, void 0);
        _destroy$.set(this, new Subject());
        this.popoverOpen = false;
        _popover.set(this, void 0);
        this.disabled = false;
        this.popoverOpened = new EventEmitter();
        this.popoverClosed = new EventEmitter();
        this.openPopover = () => {
            if (this.popoverOpen) {
                return;
            }
            const overlayRef = __classPrivateFieldGet(this, _createOverlay).call(this);
            const overlayConfig = overlayRef.getConfig();
            const positionStrategy = overlayConfig.positionStrategy;
            __classPrivateFieldGet(this, _setPosition).call(this, positionStrategy);
            overlayConfig.hasBackdrop = false;
            overlayRef.attach(__classPrivateFieldGet(this, _getPortal).call(this));
            this.popover.trigger = this;
            __classPrivateFieldGet(this, _setIsPopoverOpen).call(this, true);
            this.popover.opened.next(this.popoverData);
        };
        this.closePopover = () => {
            this.popover.closed.emit();
        };
        _setIsPopoverOpen.set(this, (isOpen) => {
            this.popoverOpen = isOpen;
            this.popoverOpen ? this.popoverOpened.emit() : this.popoverClosed.emit();
        });
        _getPortal.set(this, () => {
            var _a;
            if (!__classPrivateFieldGet(this, _portal) ||
                __classPrivateFieldGet(this, _portal).templateRef !== this.popover.templateRef ||
                ((_a = __classPrivateFieldGet(this, _portal).context) === null || _a === void 0 ? void 0 : _a.data) !== this.popoverData) {
                __classPrivateFieldSet(this, _portal, new TemplatePortal(this.popover.templateRef, this.viewContainerRef, {
                    data: this.popoverData
                }));
            }
            return __classPrivateFieldGet(this, _portal);
        });
        _createOverlay.set(this, () => {
            if (!__classPrivateFieldGet(this, _overlayRef)) {
                const config = __classPrivateFieldGet(this, _getOverlayConfig).call(this);
                __classPrivateFieldGet(this, _subscribeToPositions).call(this, config.positionStrategy);
                __classPrivateFieldSet(this, _overlayRef, this._overlay.create(config));
            }
            return __classPrivateFieldGet(this, _overlayRef);
        });
        _setPosition.set(this, (positionStrategy) => {
            let originX = "center";
            let originY = "top";
            let overlayX = "center";
            let overlayY = "bottom";
            let offsetX = 0;
            let offsetY = 16;
            switch (this.popover.position) {
                case "above":
                    originY = "top";
                    overlayY = "bottom";
                    break;
                case "below":
                    originY = "bottom";
                    overlayY = "top";
                    break;
            }
            positionStrategy.withPositions([
                // theo input
                { originX, originY, overlayX, overlayY, offsetY: originY == "top" ? -offsetY : offsetY },
                // giữa trên
                {
                    originX: "center",
                    originY: "top",
                    overlayX: "center",
                    overlayY: "bottom",
                    offsetX,
                    offsetY: -offsetY,
                },
                // giữa dưới
                {
                    originX: "center",
                    originY: "bottom",
                    overlayX: "center",
                    overlayY: "top",
                    offsetX,
                    offsetY,
                },
            ]);
        });
        _getOverlayConfig.set(this, () => {
            return new OverlayConfig({
                positionStrategy: this._overlay
                    .position()
                    .flexibleConnectedTo(this._element)
                    .withLockedPosition()
                    .withGrowAfterOpen()
                    .withTransformOriginOn(".sd-popover-panel"),
                backdropClass: "cdk-overlay-transparent-backdrop",
                panelClass: this.popover.panelClass,
                direction: this._dir,
                width: this.popover.width,
                height: this.popover.height,
            });
        });
        _subscribeToPositions.set(this, (position) => {
            if (this.popover.setPositionClasses) {
                position.positionChanges.subscribe((change) => {
                    var _a;
                    const pos = change.connectionPair.overlayY === "top" ? "below" : "above";
                    if (this._ngZone) {
                        this._ngZone.run(() => this.popover.setPositionClasses(pos));
                    }
                    else {
                        this.popover.setPositionClasses(pos);
                    }
                    const originElement = this.elementRef.nativeElement;
                    const overlayElement = (_a = this.viewContainerRef.get(0)) === null || _a === void 0 ? void 0 : _a.rootNodes[0];
                    if (originElement && overlayElement) {
                        const originRect = originElement.getBoundingClientRect();
                        const overlayRect = overlayElement.getBoundingClientRect();
                        const originLeft = originRect.left + originRect.width / 2;
                        const overlayLeft = overlayRect.left + overlayRect.width / 2;
                        const offset = originLeft - overlayLeft;
                        this.popover.addArrowTranslateX(offset);
                    }
                });
            }
        });
        _destroyPopover.set(this, () => {
            if (!__classPrivateFieldGet(this, _overlayRef) || !this.popoverOpen) {
                return;
            }
            __classPrivateFieldGet(this, _overlayRef).detach();
            __classPrivateFieldGet(this, _setIsPopoverOpen).call(this, false);
        });
    }
    get popover() {
        return __classPrivateFieldGet(this, _popover);
    }
    set popover(popover) {
        if (!popover || popover === __classPrivateFieldGet(this, _popover)) {
            return;
        }
        __classPrivateFieldSet(this, _popover, popover);
        __classPrivateFieldGet(this, _popoverClose$).unsubscribe();
        if (popover) {
            __classPrivateFieldSet(this, _popoverClose$, popover.closed.subscribe(() => {
                __classPrivateFieldGet(this, _destroyPopover).call(this);
            }));
        }
    }
    ngAfterViewInit() {
        if (this.popover) {
            const nativeElement = this.elementRef.nativeElement;
            const hostMouseState$ = merge(fromEvent(nativeElement, "mouseenter").pipe(mapTo(true)), fromEvent(nativeElement, "mouseleave").pipe(mapTo(false)));
            const popoverMouseState$ = this.popover.mouseState$.pipe(
            // chỉ lấy luồng emit open bởi chính trigger (tránh lỗi nhiều trigger cho một popover)
            filter((v) => !this.popover.trigger || this.popover.trigger == this));
            const mergedMouseState$ = merge(popoverMouseState$, hostMouseState$);
            mergedMouseState$
                .pipe(debounceTime(100), distinctUntilChanged(), filter(() => this.platform.isBrowser), takeUntil(__classPrivateFieldGet(this, _destroy$)))
                .subscribe((visible) => {
                if (visible && !this.disabled) {
                    this.openPopover();
                }
                else {
                    this.closePopover();
                }
            });
        }
    }
    ngOnDestroy() {
        __classPrivateFieldGet(this, _destroy$).next();
        __classPrivateFieldGet(this, _destroy$).complete();
        if (__classPrivateFieldGet(this, _overlayRef)) {
            __classPrivateFieldGet(this, _overlayRef).dispose();
            __classPrivateFieldSet(this, _overlayRef, null);
        }
    }
}
_overlayRef = new WeakMap(), _popoverClose$ = new WeakMap(), _portal = new WeakMap(), _destroy$ = new WeakMap(), _popover = new WeakMap(), _setIsPopoverOpen = new WeakMap(), _getPortal = new WeakMap(), _createOverlay = new WeakMap(), _setPosition = new WeakMap(), _getOverlayConfig = new WeakMap(), _subscribeToPositions = new WeakMap(), _destroyPopover = new WeakMap();
PopoverTriggerDirective.decorators = [
    { type: Directive, args: [{
                selector: "[sdPopoverTriggerFor]",
                host: {
                    "aria-haspopup": "true",
                    class: "sd-popover-trigger",
                },
                exportAs: "sdPopoverTrigger",
            },] }
];
PopoverTriggerDirective.ctorParameters = () => [
    { type: Overlay },
    { type: ElementRef },
    { type: NgZone },
    { type: ViewContainerRef },
    { type: ElementRef },
    { type: Platform },
    { type: Directionality, decorators: [{ type: Optional }] }
];
PopoverTriggerDirective.propDecorators = {
    popover: [{ type: Input, args: ["sdPopoverTriggerFor",] }],
    popoverData: [{ type: Input, args: ["sdPopoverData",] }],
    disabled: [{ type: Input, args: ["sdPopoverDisabled",] }],
    popoverOpened: [{ type: Output }],
    popoverClosed: [{ type: Output }]
};

class SdPopoverModule {
}
SdPopoverModule.decorators = [
    { type: NgModule, args: [{
                declarations: [
                    PopoverComponent,
                    PopoverTriggerDirective,
                    PopoverContentDirective
                ],
                imports: [
                    CommonModule,
                    A11yModule
                ],
                exports: [
                    PopoverComponent,
                    PopoverTriggerDirective,
                    PopoverContentDirective
                ]
            },] }
];

/*
 * Public API Surface of superdev-angular-core
 */

/**
 * Generated bundle index. Do not edit.
 */

export { PopoverComponent, PopoverContentDirective, PopoverTriggerDirective, SdPopoverModule };
//# sourceMappingURL=sd-angular-core-popover.js.map
