import * as i0 from '@angular/core';
import { Injectable, Directive, Inject, Input, HostBinding } from '@angular/core';
import { BehaviorSubject, Subject, fromEvent, merge, of } from 'rxjs';
import { delay, filter, takeUntil, switchMap, take } from 'rxjs/operators';
import { DOCUMENT } from '@angular/common';
import * as i1 from '@ironsource/fusion-ui/services/window';
import * as i2 from '@angular/platform-browser';
import { isNullOrUndefined } from '@ironsource/fusion-ui/utils';

var TooltipPosition;
(function (TooltipPosition) {
    TooltipPosition[TooltipPosition["Top"] = 0] = "Top";
    TooltipPosition[TooltipPosition["Right"] = 1] = "Right";
    TooltipPosition[TooltipPosition["Bottom"] = 2] = "Bottom";
    TooltipPosition[TooltipPosition["Left"] = 3] = "Left";
    TooltipPosition[TooltipPosition["TopFixed"] = 4] = "TopFixed";
    TooltipPosition[TooltipPosition["TopLeft"] = 5] = "TopLeft";
    TooltipPosition[TooltipPosition["TopRight"] = 6] = "TopRight";
    TooltipPosition[TooltipPosition["BottomLeft"] = 7] = "BottomLeft";
    TooltipPosition[TooltipPosition["BottomRight"] = 8] = "BottomRight";
})(TooltipPosition || (TooltipPosition = {}));
var TooltipType;
(function (TooltipType) {
    TooltipType[TooltipType["Html"] = 0] = "Html";
    TooltipType[TooltipType["Component"] = 1] = "Component";
})(TooltipType || (TooltipType = {}));

class TooltipService {
    constructor() {
        this.delayData$ = new BehaviorSubject({});
        this.tooltipData$ = this.delayData$.asObservable().pipe(delay(0));
        this.onDestroy$ = new Subject();
    }
    static { this.mouseOver$ = fromEvent(document.body, 'mouseover'); }
    ngOnDestroy() {
        this.onDestroy$.next();
        this.onDestroy$.complete();
    }
    getMouseHoverObservable(element) {
        return TooltipService.mouseOver$.pipe(filter((event) => TooltipService.isEventInElementRegion({ event, element })));
    }
    showTooltip(tooltipData) {
        this.delayData$.next(tooltipData);
    }
    closeTooltip() {
        this.delayData$.next({});
    }
    static isEventInElementRegion({ event, element }) {
        return element.contains(event.target);
    }
    static { this.ɵfac = function TooltipService_Factory(t) { return new (t || TooltipService)(); }; }
    static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TooltipService, factory: TooltipService.ɵfac, providedIn: 'root' }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TooltipService, [{
        type: Injectable,
        args: [{
                providedIn: 'root'
            }]
    }], null, null); })();

class TooltipBaseDirective {
    set fusionTooltip(tooltipContent) {
        if (!!tooltipContent) {
            this.clearTooltipContentListener$.next();
            this.fusionTooltipContent = tooltipContent;
            this.renderer.setAttribute(this.elementRef.nativeElement, 'role', 'tooltiped');
            this.onMouseEnterObservable$ = this.tooltipService.getMouseHoverObservable(this.elementRef.nativeElement);
            this.initListeners();
        }
    }
    constructor(elementRef, tooltipService, renderer, document) {
        this.elementRef = elementRef;
        this.tooltipService = tooltipService;
        this.renderer = renderer;
        this.document = document;
        this.tooltipPosition = TooltipPosition.Top;
        this.tooltipType = TooltipType.Html;
        this.tooltipComponentData = {};
        this.tooltipPreventToClose = false;
        this.emptyTooltip = ''; // remove existed title from parent element
        this.visible = false;
        this.onDestroy$ = new Subject();
        this.clearListeners$ = new Subject();
        this.clearTooltipContentListener$ = new Subject();
        this.clearHover$ = merge(this.clearTooltipContentListener$.asObservable(), this.onDestroy$.asObservable());
        this.takeUntil$ = merge(this.clearListeners$.asObservable(), this.onDestroy$.asObservable());
        this.fusionTooltipContent = '';
    }
    ngOnDestroy() {
        if (this.visible) {
            this.closeTooltip();
        }
        this.onDestroy$.next();
        this.onDestroy$.complete();
        this.clearListeners$.complete();
        this.clearTooltipContentListener$.complete();
    }
    initListeners() {
        this.onMouseEnterObservable$.pipe(takeUntil(this.clearHover$)).subscribe(() => {
            this.onHover();
        });
    }
    onHover() {
        const needToShow = this.calcTruncate();
        if (this.visible || !needToShow) {
            return;
        }
        this.visible = true;
        this.buildTooltipComponent();
        this.setMouseListeners();
    }
    closeTooltip() {
        this.visible = false;
        this.tooltipService.closeTooltip();
    }
    onHoverEnds() {
        if (this.visible) {
            this.closeTooltip();
        }
    }
    onClick(event) {
        if ((!!event && event.target.closest('fusion-icon[role="tooltiped"]') && this.visible) ||
            this.elementRef.nativeElement.offsetParent === null) {
            this.closeTooltip();
        }
    }
    buildTooltipComponent() {
        const tooltipData = {
            parentEl: this.elementRef,
            position: this.tooltipPosition,
            content: this.fusionTooltipContent,
            icon: this.tooltipIcon,
            width: this.tooltipWidth,
            type: this.tooltipType,
            componentData: this.tooltipComponentData
        };
        this.tooltipService.showTooltip(tooltipData);
    }
    setMouseListeners() {
        fromEvent(this.elementRef.nativeElement, 'click').pipe(takeUntil(this.takeUntil$)).subscribe(this.onClick.bind(this));
        fromEvent(this.elementRef.nativeElement, 'mouseleave')
            .pipe(switchMap((event) => {
            return this.haveToBeClosed(event);
        }), take(1))
            .subscribe(() => {
            this.onHoverEnds();
            this.clearListeners$.next();
        });
    }
    calcTruncate() {
        if (!this.fusionTooltipContent) {
            return false;
        }
        const nativeElement = this.elementRef.nativeElement;
        return !(nativeElement.className.includes('truncate') && nativeElement.clientWidth >= nativeElement.scrollWidth);
    }
    haveToBeClosed(event) {
        const marginSize = 10;
        const tooltipEl = this.document.querySelector('fusion-tooltip');
        let haveToBeClosed = true;
        if (this.tooltipPreventToClose && !!tooltipEl) {
            const rectTooltip = tooltipEl.getBoundingClientRect();
            haveToBeClosed = !(event.x >= rectTooltip.left - marginSize &&
                event.x <= rectTooltip.right + marginSize &&
                event.y >= rectTooltip.top - marginSize &&
                event.y <= rectTooltip.bottom + marginSize);
        }
        return haveToBeClosed ? of(event) : fromEvent(tooltipEl, 'mouseleave');
    }
    static { this.ɵfac = function TooltipBaseDirective_Factory(t) { return new (t || TooltipBaseDirective)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(TooltipService), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(DOCUMENT)); }; }
    static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: TooltipBaseDirective, hostVars: 1, hostBindings: function TooltipBaseDirective_HostBindings(rf, ctx) { if (rf & 2) {
            i0.ɵɵattribute("title", ctx.emptyTooltip);
        } }, inputs: { fusionTooltip: "fusionTooltip", tooltipWidth: "tooltipWidth", tooltipPosition: "tooltipPosition", tooltipType: "tooltipType", tooltipComponentData: "tooltipComponentData", tooltipIcon: "tooltipIcon", tooltipPreventToClose: "tooltipPreventToClose" } }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TooltipBaseDirective, [{
        type: Directive
    }], () => [{ type: i0.ElementRef }, { type: TooltipService }, { type: i0.Renderer2 }, { type: Document, decorators: [{
                type: Inject,
                args: [DOCUMENT]
            }] }], { fusionTooltip: [{
            type: Input
        }], tooltipWidth: [{
            type: Input
        }], tooltipPosition: [{
            type: Input
        }], tooltipType: [{
            type: Input
        }], tooltipComponentData: [{
            type: Input
        }], tooltipIcon: [{
            type: Input
        }], tooltipPreventToClose: [{
            type: Input
        }], emptyTooltip: [{
            type: HostBinding,
            args: ['attr.title']
        }] }); })();

const TOOLTIP_ARROW_SIZE = 6;
class TooltipBaseComponent {
    set tooltipData(newTooltipData) {
        this.hostEl = newTooltipData.parentEl;
        this.position = newTooltipData.position || TooltipPosition.Top;
        this.content =
            newTooltipData.type === TooltipType.Html
                ? this.sanitizer.bypassSecurityTrustHtml(newTooltipData.content)
                : newTooltipData.content;
        this.width = newTooltipData.width;
        this.icon = newTooltipData.icon;
        this.type = newTooltipData.type || TooltipType.Html;
        this.componentData = newTooltipData.componentData || {};
        const classToRemove = Array.from(this.tooltipElRef.nativeElement.classList).find((value) => value.includes('is-position-'));
        this.renderer.removeClass(this.tooltipElRef.nativeElement, classToRemove);
    }
    get hasIcon() {
        return !!this.icon;
    }
    get isHtml() {
        return this.type === TooltipType.Html;
    }
    constructor(injector, tooltipElRef, window, renderer, sanitizer) {
        this.tooltipElRef = tooltipElRef;
        this.window = window;
        this.renderer = renderer;
        this.sanitizer = sanitizer;
    }
    ngOnChanges(changes) {
        if (!changes.tooltipData.isFirstChange()) {
            this._setPosition();
        }
    }
    ngAfterViewInit() {
        this._setPosition();
    }
    /**
     * Reposition Tooltip Content
     */
    _setPosition() {
        if (!isNullOrUndefined(this.hostEl)) {
            const positionOffset = this._calcPosition(this.position, this.tooltipElRef.nativeElement, this.hostEl.nativeElement);
            const rect = this.hostEl.nativeElement.getBoundingClientRect();
            this.renderer.setStyle(this.tooltipElRef.nativeElement, 'top', rect.top + positionOffset.top + 'px');
            this.renderer.setStyle(this.tooltipElRef.nativeElement, 'left', rect.left + positionOffset.left + 'px');
        }
    }
    _adjustPosition(position, tooltipEl, hostEl) {
        // for fixed, not calculated Position type
        if (position === TooltipPosition.TopFixed) {
            return TooltipPosition.Top;
        }
        const tooltipWidth = this.width || 250;
        const hostRect = hostEl.getBoundingClientRect();
        const tooltipRect = tooltipEl.getBoundingClientRect();
        if (this.window.nativeWindow.innerWidth - tooltipWidth - hostRect.left <= 0) {
            // tooltip host on right side of page
            position = TooltipPosition.Left;
        }
        else if (hostRect.left - tooltipWidth <= 0) {
            // tooltip host on left side of page
            position = TooltipPosition.Right;
        }
        else if (hostRect.top - tooltipRect.height <= 0) {
            position = hostRect.left - tooltipWidth <= 0 ? TooltipPosition.Right : TooltipPosition.Left;
        }
        return position;
    }
    /**
     * Calculate position
     * @param TooltipPosition position
     */
    _calcPosition(position, tooltipEl, hostEl) {
        let shiftPosition;
        position = this._adjustPosition(position, tooltipEl, hostEl);
        this.renderer.addClass(this.tooltipElRef.nativeElement, 'is-position-' + TooltipPosition[position].toLowerCase());
        switch (position) {
            case TooltipPosition.Left:
                shiftPosition = {
                    top: hostEl.offsetHeight / 2 - tooltipEl.offsetHeight / 2,
                    left: 0 - tooltipEl.offsetWidth - TOOLTIP_ARROW_SIZE
                };
                break;
            case TooltipPosition.Right:
                shiftPosition = {
                    top: hostEl.offsetHeight / 2 - tooltipEl.offsetHeight / 2,
                    left: hostEl.offsetWidth + TOOLTIP_ARROW_SIZE
                };
                break;
            case TooltipPosition.Bottom:
                shiftPosition = {
                    top: hostEl.offsetHeight + TOOLTIP_ARROW_SIZE,
                    left: hostEl.offsetWidth / 2 - tooltipEl.offsetWidth / 2
                };
                break;
            default:
                // TooltipPosition.Top
                shiftPosition = {
                    top: 0 - tooltipEl.offsetHeight - TOOLTIP_ARROW_SIZE,
                    left: hostEl.offsetWidth / 2 - tooltipEl.offsetWidth / 2
                };
                break;
        }
        return shiftPosition;
    }
    static { this.ɵfac = function TooltipBaseComponent_Factory(t) { return new (t || TooltipBaseComponent)(i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i1.WindowService), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i2.DomSanitizer)); }; }
    static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: TooltipBaseComponent, hostVars: 2, hostBindings: function TooltipBaseComponent_HostBindings(rf, ctx) { if (rf & 2) {
            i0.ɵɵstyleProp("width", ctx.width, "px");
        } }, inputs: { tooltipData: "tooltipData" }, features: [i0.ɵɵNgOnChangesFeature] }); }
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TooltipBaseComponent, [{
        type: Directive
    }], () => [{ type: i0.Injector }, { type: i0.ElementRef }, { type: i1.WindowService }, { type: i0.Renderer2 }, { type: i2.DomSanitizer }], { tooltipData: [{
            type: Input
        }], width: [{
            type: HostBinding,
            args: ['style.width.px']
        }] }); })();

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

export { TooltipBaseComponent, TooltipBaseDirective, TooltipPosition, TooltipService, TooltipType };
//# sourceMappingURL=ironsource-fusion-ui-components-tooltip-common-base.mjs.map
