import { Overlay, OverlayPositionBuilder } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { NgTemplateOutlet, DOCUMENT, isPlatformBrowser } from '@angular/common';
import * as i0 from '@angular/core';
import { signal, computed, ChangeDetectionStrategy, Component, input, output, inject, ElementRef, Renderer2, DestroyRef, PLATFORM_ID, effect, Directive } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { zMergeClasses, zTransform } from '@shival99/z-ui/utils';
import { Subject, switchMap, of, timer, map, filter } from 'rxjs';
import { TranslatePipe } from '@ngx-translate/core';
import { cva } from 'class-variance-authority';

const zTooltipVariants = cva(['z-tooltip relative rounded-[0.3125rem] shadow-md', 'z-animate-in z-fade-in z-duration-150'], {
    variants: {
        zType: {
            default: 'bg-foreground text-background border border-foreground',
            dark: 'bg-slate-900 text-white border border-slate-700',
            light: 'bg-white text-slate-900 border border-slate-200',
            primary: 'bg-primary text-primary-foreground border border-primary',
            success: 'bg-green-600 text-white border border-green-600',
            warning: 'bg-amber-500 text-white border border-amber-500',
            error: 'bg-red-600 text-white border border-red-600',
            info: 'bg-blue-600 text-white border border-blue-600',
        },
        zSize: {
            sm: 'text-[0.625rem]',
            default: 'text-xs',
            lg: 'text-sm',
        },
        zPosition: {
            top: 'z-slide-in-from-top-2',
            'top-left': 'z-slide-in-from-top-2',
            'top-right': 'z-slide-in-from-top-2',
            bottom: 'z-slide-in-from-bottom-2',
            'bottom-left': 'z-slide-in-from-bottom-2',
            'bottom-right': 'z-slide-in-from-bottom-2',
            left: 'z-slide-in-from-left-2',
            'left-top': 'z-slide-in-from-left-2',
            'left-bottom': 'z-slide-in-from-left-2',
            right: 'z-slide-in-from-right-2',
            'right-top': 'z-slide-in-from-right-2',
            'right-bottom': 'z-slide-in-from-right-2',
        },
    },
    defaultVariants: {
        zType: 'default',
        zSize: 'default',
        zPosition: 'top',
    },
});
const zTooltipContentVariants = cva('relative z-10 rounded-[0.25rem] font-medium p-1.5 break-words leading-[1.7]', {
    variants: {
        zType: {
            default: 'bg-foreground',
            dark: 'bg-slate-900',
            light: 'bg-white',
            primary: 'bg-primary',
            success: 'bg-green-600',
            warning: 'bg-amber-500',
            error: 'bg-red-600',
            info: 'bg-blue-600',
        },
    },
    defaultVariants: {
        zType: 'default',
    },
});
const zTooltipArrowVariants = cva('absolute z-0 size-2.5 rotate-45 rounded-[0.1875rem]', {
    variants: {
        position: {
            top: '-bottom-1 left-1/2 -translate-x-1/2 border-r border-b',
            'top-left': '-bottom-1 left-3 border-r border-b',
            'top-right': '-bottom-1 right-3 border-r border-b',
            bottom: '-top-1 left-1/2 -translate-x-1/2 border-l border-t',
            'bottom-left': '-top-1 left-3 border-l border-t',
            'bottom-right': '-top-1 right-3 border-l border-t',
            left: 'top-1/2 -translate-y-1/2 -right-1 border-t border-r',
            'left-top': 'top-2 -right-1 border-t border-r',
            'left-bottom': 'bottom-2 -right-1 border-t border-r',
            right: 'top-1/2 -translate-y-1/2 -left-1 border-b border-l',
            'right-top': 'top-2 -left-1 border-b border-l',
            'right-bottom': 'bottom-2 -left-1 border-b border-l',
        },
        zType: {
            default: 'bg-foreground border-foreground',
            dark: 'bg-slate-900 border-slate-700',
            light: 'bg-white border-slate-200',
            primary: 'bg-primary border-primary',
            success: 'bg-green-600 border-green-600',
            warning: 'bg-amber-500 border-amber-500',
            error: 'bg-red-600 border-red-600',
            info: 'bg-blue-600 border-blue-600',
        },
    },
    defaultVariants: {
        position: 'top',
        zType: 'default',
    },
});
const zTooltipExitVariants = cva('z-animate-out z-fade-out', {
    variants: {
        zPosition: {
            top: 'z-slide-out-to-top-2',
            'top-left': 'z-slide-out-to-top-2',
            'top-right': 'z-slide-out-to-top-2',
            bottom: 'z-slide-out-to-bottom-2',
            'bottom-left': 'z-slide-out-to-bottom-2',
            'bottom-right': 'z-slide-out-to-bottom-2',
            left: 'z-slide-out-to-left-2',
            'left-top': 'z-slide-out-to-left-2',
            'left-bottom': 'z-slide-out-to-left-2',
            right: 'z-slide-out-to-right-2',
            'right-top': 'z-slide-out-to-right-2',
            'right-bottom': 'z-slide-out-to-right-2',
        },
    },
    defaultVariants: {
        zPosition: 'top',
    },
});

class ZTooltipContentComponent {
    content = signal('', ...(ngDevMode ? [{ debugName: "content" }] : []));
    position = signal('top', ...(ngDevMode ? [{ debugName: "position" }] : []));
    tooltipType = signal('default', ...(ngDevMode ? [{ debugName: "tooltipType" }] : []));
    tooltipSize = signal('default', ...(ngDevMode ? [{ debugName: "tooltipSize" }] : []));
    tooltipClass = signal('', ...(ngDevMode ? [{ debugName: "tooltipClass" }] : []));
    showArrow = signal(true, ...(ngDevMode ? [{ debugName: "showArrow" }] : []));
    maxWidth = signal('250px', ...(ngDevMode ? [{ debugName: "maxWidth" }] : []));
    state = signal('open', ...(ngDevMode ? [{ debugName: "state" }] : []));
    arrowOffset = signal(0, ...(ngDevMode ? [{ debugName: "arrowOffset" }] : []));
    classes = computed(() => {
        const baseClasses = zTooltipVariants({
            zType: this.tooltipType(),
            zSize: this.tooltipSize(),
            zPosition: this.position(),
        });
        const exitClasses = this.state() === 'closed' ? this._getExitAnimationClasses() : '';
        return zMergeClasses(baseClasses, exitClasses, this.tooltipClass());
    }, ...(ngDevMode ? [{ debugName: "classes" }] : []));
    _getExitAnimationClasses() {
        return zTooltipExitVariants({ zPosition: this.position() });
    }
    contentClasses = computed(() => zMergeClasses(zTooltipContentVariants({ zType: this.tooltipType() })), ...(ngDevMode ? [{ debugName: "contentClasses" }] : []));
    arrowClasses = computed(() => zMergeClasses(zTooltipArrowVariants({
        position: this.position(),
        zType: this.tooltipType(),
    })), ...(ngDevMode ? [{ debugName: "arrowClasses" }] : []));
    arrowStyle = computed(() => {
        const pos = this.position();
        const offset = this.arrowOffset();
        const isCornerPosition = pos.includes('-');
        if (isCornerPosition) {
            return {};
        }
        if (offset === 0) {
            return {};
        }
        if (pos === 'top' || pos === 'bottom') {
            return {
                left: `calc(50% + ${offset}px)`,
            };
        }
        if (pos === 'left' || pos === 'right') {
            return {
                top: `calc(50% + ${offset}px)`,
            };
        }
        return {};
    }, ...(ngDevMode ? [{ debugName: "arrowStyle" }] : []));
    isTemplateContent = computed(() => {
        const c = this.content();
        return c && typeof c !== 'string';
    }, ...(ngDevMode ? [{ debugName: "isTemplateContent" }] : []));
    isHtmlContent = computed(() => {
        const c = this.content();
        return typeof c === 'string' && c.includes('<');
    }, ...(ngDevMode ? [{ debugName: "isHtmlContent" }] : []));
    textOnlyContent = computed(() => {
        const c = this.content();
        if (typeof c === 'string' && c.includes('<')) {
            return this._stripHtmlTags(c);
        }
        return c;
    }, ...(ngDevMode ? [{ debugName: "textOnlyContent" }] : []));
    _stripHtmlTags(html) {
        const tempDiv = document.createElement('div');
        tempDiv.innerHTML = html;
        return tempDiv.textContent || tempDiv.innerText || '';
    }
    setProps(config) {
        this.content.set(config.content);
        this.position.set(config.position);
        if (config.type) {
            this.tooltipType.set(config.type);
        }
        if (config.size) {
            this.tooltipSize.set(config.size);
        }
        if (config.customClass) {
            this.tooltipClass.set(config.customClass);
        }
        if (config.arrow !== undefined) {
            this.showArrow.set(config.arrow);
        }
        if (config.maxWidth) {
            this.maxWidth.set(config.maxWidth);
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZTooltipContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: ZTooltipContentComponent, isStandalone: true, selector: "z-tooltip-content", host: { attributes: { "role": "tooltip" }, properties: { "class": "classes()", "style.maxWidth": "maxWidth()", "attr.data-state": "state()", "attr.data-position": "position()" } }, ngImport: i0, template: `
    <!-- Arrow layer - rotated square, partial border -->
    @if (showArrow()) {
      <div [class]="arrowClasses()" [style]="arrowStyle()"></div>
    }

    <!-- Content layer - covers arrow base -->
    <div [class]="contentClasses()">
      @if (isTemplateContent()) {
        <ng-container [ngTemplateOutlet]="$any(content())" />
      } @else if (isHtmlContent()) {
        {{ $any(textOnlyContent()) | translate }}
      } @else {
        {{ $any(content()) | translate }}
      }
    </div>
  `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZTooltipContentComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'z-tooltip-content',
                    imports: [NgTemplateOutlet, TranslatePipe],
                    standalone: true,
                    template: `
    <!-- Arrow layer - rotated square, partial border -->
    @if (showArrow()) {
      <div [class]="arrowClasses()" [style]="arrowStyle()"></div>
    }

    <!-- Content layer - covers arrow base -->
    <div [class]="contentClasses()">
      @if (isTemplateContent()) {
        <ng-container [ngTemplateOutlet]="$any(content())" />
      } @else if (isHtmlContent()) {
        {{ $any(textOnlyContent()) | translate }}
      } @else {
        {{ $any(content()) | translate }}
      }
    </div>
  `,
                    changeDetection: ChangeDetectionStrategy.OnPush,
                    host: {
                        '[class]': 'classes()',
                        '[style.maxWidth]': 'maxWidth()',
                        '[attr.data-state]': 'state()',
                        '[attr.data-position]': 'position()',
                        role: 'tooltip',
                    },
                }]
        }] });

function createTooltipPosition(position, offset) {
    const positions = {
        top: {
            originX: 'center',
            originY: 'top',
            overlayX: 'center',
            overlayY: 'bottom',
            offsetY: -offset,
        },
        'top-left': {
            originX: 'start',
            originY: 'top',
            overlayX: 'start',
            overlayY: 'bottom',
            offsetY: -offset,
        },
        'top-right': {
            originX: 'end',
            originY: 'top',
            overlayX: 'end',
            overlayY: 'bottom',
            offsetY: -offset,
        },
        bottom: {
            originX: 'center',
            originY: 'bottom',
            overlayX: 'center',
            overlayY: 'top',
            offsetY: offset,
        },
        'bottom-left': {
            originX: 'start',
            originY: 'bottom',
            overlayX: 'start',
            overlayY: 'top',
            offsetY: offset,
        },
        'bottom-right': {
            originX: 'end',
            originY: 'bottom',
            overlayX: 'end',
            overlayY: 'top',
            offsetY: offset,
        },
        left: {
            originX: 'start',
            originY: 'center',
            overlayX: 'end',
            overlayY: 'center',
            offsetX: -offset,
        },
        'left-top': {
            originX: 'start',
            originY: 'top',
            overlayX: 'end',
            overlayY: 'top',
            offsetX: -offset,
        },
        'left-bottom': {
            originX: 'start',
            originY: 'bottom',
            overlayX: 'end',
            overlayY: 'bottom',
            offsetX: -offset,
        },
        right: {
            originX: 'end',
            originY: 'center',
            overlayX: 'start',
            overlayY: 'center',
            offsetX: offset,
        },
        'right-top': {
            originX: 'end',
            originY: 'top',
            overlayX: 'start',
            overlayY: 'top',
            offsetX: offset,
        },
        'right-bottom': {
            originX: 'end',
            originY: 'bottom',
            overlayX: 'start',
            overlayY: 'bottom',
            offsetX: offset,
        },
    };
    return positions[position];
}
function getTooltipFallbackPositions(position, offset) {
    const fallbackOrder = {
        top: ['top', 'bottom', 'top-left', 'top-right', 'bottom-left', 'bottom-right'],
        'top-left': ['top-left', 'bottom-left', 'top', 'bottom', 'top-right', 'bottom-right'],
        'top-right': ['top-right', 'bottom-right', 'top', 'bottom', 'top-left', 'bottom-left'],
        bottom: ['bottom', 'top', 'bottom-left', 'bottom-right', 'top-left', 'top-right'],
        'bottom-left': ['bottom-left', 'top-left', 'bottom', 'top', 'bottom-right', 'top-right'],
        'bottom-right': ['bottom-right', 'top-right', 'bottom', 'top', 'bottom-left', 'top-left'],
        left: ['left', 'right', 'left-top', 'left-bottom', 'right-top', 'right-bottom'],
        'left-top': ['left-top', 'right-top', 'left', 'right', 'left-bottom', 'right-bottom'],
        'left-bottom': ['left-bottom', 'right-bottom', 'left', 'right', 'left-top', 'right-top'],
        right: ['right', 'left', 'right-top', 'right-bottom', 'left-top', 'left-bottom'],
        'right-top': ['right-top', 'left-top', 'right', 'left', 'right-bottom', 'left-bottom'],
        'right-bottom': ['right-bottom', 'left-bottom', 'right', 'left', 'right-top', 'left-top'],
    };
    const orderedPositions = fallbackOrder[position] ?? [position];
    return orderedPositions.map(pos => createTooltipPosition(pos, offset));
}
function getActualPosition(change) {
    const { originX, originY, overlayX, overlayY } = change.connectionPair;
    if (overlayY === 'bottom' && originY === 'top') {
        if (originX === 'start' && overlayX === 'start') {
            return 'top-left';
        }
        if (originX === 'end' && overlayX === 'end') {
            return 'top-right';
        }
        return 'top';
    }
    if (overlayY === 'top' && originY === 'bottom') {
        if (originX === 'start' && overlayX === 'start') {
            return 'bottom-left';
        }
        if (originX === 'end' && overlayX === 'end') {
            return 'bottom-right';
        }
        return 'bottom';
    }
    if (overlayX === 'end' && originX === 'start') {
        if (originY === 'top' && overlayY === 'top') {
            return 'left-top';
        }
        if (originY === 'bottom' && overlayY === 'bottom') {
            return 'left-bottom';
        }
        return 'left';
    }
    if (overlayX === 'start' && originX === 'end') {
        if (originY === 'top' && overlayY === 'top') {
            return 'right-top';
        }
        if (originY === 'bottom' && overlayY === 'bottom') {
            return 'right-bottom';
        }
        return 'right';
    }
    return 'top';
}

const Z_TOOLTIP_ANIMATION_DURATION = 150;

class ZTooltipDirective {
    zContent = input('', ...(ngDevMode ? [{ debugName: "zContent" }] : []));
    zPosition = input('top', ...(ngDevMode ? [{ debugName: "zPosition" }] : []));
    zTooltipPosition = input(...(ngDevMode ? [undefined, { debugName: "zTooltipPosition" }] : []));
    zTrigger = input('hover', ...(ngDevMode ? [{ debugName: "zTrigger" }] : []));
    zTooltipTrigger = input(...(ngDevMode ? [undefined, { debugName: "zTooltipTrigger" }] : []));
    zType = input('default', { ...(ngDevMode ? { debugName: "zType" } : {}), alias: 'zTooltipType' });
    zSize = input('default', { ...(ngDevMode ? { debugName: "zSize" } : {}), alias: 'zTooltipSize' });
    zClass = input('', ...(ngDevMode ? [{ debugName: "zClass" }] : []));
    zTooltipClass = input(...(ngDevMode ? [undefined, { debugName: "zTooltipClass" }] : []));
    zShowDelay = input(100, ...(ngDevMode ? [{ debugName: "zShowDelay" }] : []));
    zTooltipShowDelay = input(...(ngDevMode ? [undefined, { debugName: "zTooltipShowDelay" }] : []));
    zHideDelay = input(0, ...(ngDevMode ? [{ debugName: "zHideDelay" }] : []));
    zTooltipHideDelay = input(...(ngDevMode ? [undefined, { debugName: "zTooltipHideDelay" }] : []));
    zArrow = input(true, { ...(ngDevMode ? { debugName: "zArrow" } : {}), transform: zTransform });
    zTooltipArrow = input(undefined, ...(ngDevMode ? [{ debugName: "zTooltipArrow" }] : []));
    zDisabled = input(false, { ...(ngDevMode ? { debugName: "zDisabled" } : {}), transform: zTransform });
    zTooltipDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "zTooltipDisabled" }] : []));
    zOffset = input(8, ...(ngDevMode ? [{ debugName: "zOffset" }] : []));
    zTooltipOffset = input(...(ngDevMode ? [undefined, { debugName: "zTooltipOffset" }] : []));
    zAutoDetect = input(true, { ...(ngDevMode ? { debugName: "zAutoDetect" } : {}), transform: zTransform });
    zTriggerElement = input(null, ...(ngDevMode ? [{ debugName: "zTriggerElement" }] : []));
    zAlwaysShow = input(false, { ...(ngDevMode ? { debugName: "zAlwaysShow" } : {}), transform: zTransform });
    zMaxWidth = input('250px', ...(ngDevMode ? [{ debugName: "zMaxWidth" }] : []));
    _position = computed(() => this.zTooltipPosition() ?? this.zPosition(), ...(ngDevMode ? [{ debugName: "_position" }] : []));
    _trigger = computed(() => this.zTooltipTrigger() ?? this.zTrigger(), ...(ngDevMode ? [{ debugName: "_trigger" }] : []));
    _class = computed(() => this.zTooltipClass() ?? this.zClass(), ...(ngDevMode ? [{ debugName: "_class" }] : []));
    _showDelay = computed(() => this.zTooltipShowDelay() ?? this.zShowDelay(), ...(ngDevMode ? [{ debugName: "_showDelay" }] : []));
    _hideDelay = computed(() => this.zTooltipHideDelay() ?? this.zHideDelay(), ...(ngDevMode ? [{ debugName: "_hideDelay" }] : []));
    _arrow = computed(() => this.zTooltipArrow() ?? this.zArrow(), ...(ngDevMode ? [{ debugName: "_arrow" }] : []));
    _disabled = computed(() => this.zTooltipDisabled() ?? this.zDisabled(), ...(ngDevMode ? [{ debugName: "_disabled" }] : []));
    _offset = computed(() => this.zTooltipOffset() ?? this.zOffset(), ...(ngDevMode ? [{ debugName: "_offset" }] : []));
    zShow = output();
    zHide = output();
    _overlay = inject(Overlay);
    _overlayPositionBuilder = inject(OverlayPositionBuilder);
    _elementRef = inject((ElementRef));
    _renderer = inject(Renderer2);
    _destroyRef = inject(DestroyRef);
    _platformId = inject(PLATFORM_ID);
    _document = inject(DOCUMENT);
    _overlayRef = null;
    _componentRef = null;
    _delaySubject = new Subject();
    _listenerCleanups = [];
    _positionSubscription = null;
    _hideTimeout = null;
    _isVisible = signal(false, ...(ngDevMode ? [{ debugName: "_isVisible" }] : []));
    constructor() {
        effect(() => {
            if (this._disabled() || !this.zContent()) {
                this._delay(false, 0);
            }
        });
    }
    ngOnInit() {
        if (!isPlatformBrowser(this._platformId)) {
            return;
        }
        this._setupDelayMechanism();
        this._setupTriggers();
    }
    ngOnDestroy() {
        this._clearHideTimeout();
        this._delaySubject.complete();
        this._cleanupListeners();
        this._disposeOverlay();
    }
    show() {
        if (this._disabled() || !this.zContent()) {
            return;
        }
        if (!this.zAlwaysShow() && this.zAutoDetect() && !this._isTextTruncated()) {
            return;
        }
        if (this._isVisible()) {
            this._delay(true, 0);
            return;
        }
        this._delay(true, this._showDelay());
    }
    _isTextTruncated() {
        const hostEl = this._elementRef.nativeElement;
        const triggerEl = this.zTriggerElement();
        if (this._isElementTruncated(hostEl)) {
            return true;
        }
        const directChildren = hostEl.children;
        for (let i = 0; i < directChildren.length; i++) {
            const child = directChildren[i];
            if (this._isElementTruncated(child)) {
                return true;
            }
            const grandChildren = child.children;
            for (let j = 0; j < grandChildren.length; j++) {
                if (this._isElementTruncated(grandChildren[j])) {
                    return true;
                }
            }
        }
        if (triggerEl && triggerEl !== hostEl) {
            if (this._isElementTruncated(triggerEl)) {
                return true;
            }
            const triggerDirectChildren = triggerEl.children;
            for (let i = 0; i < triggerDirectChildren.length; i++) {
                if (this._isElementTruncated(triggerDirectChildren[i])) {
                    return true;
                }
            }
        }
        return false;
    }
    _isElementTruncated(el) {
        if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
            return this._isFormControlValueTruncated(el);
        }
        if (el.scrollWidth > el.clientWidth) {
            return true;
        }
        if (el.scrollHeight > el.clientHeight) {
            return true;
        }
        const styles = getComputedStyle(el);
        if (styles.whiteSpace === 'nowrap' || styles.textOverflow === 'ellipsis') {
            const range = this._document.createRange();
            range.selectNodeContents(el);
            const contentWidth = range.getBoundingClientRect().width;
            const elementWidth = el.getBoundingClientRect().width;
            const paddingLeft = parseFloat(styles.paddingLeft) || 0;
            const paddingRight = parseFloat(styles.paddingRight) || 0;
            const availableWidth = elementWidth - paddingLeft - paddingRight;
            if (contentWidth - availableWidth > 0.1) {
                return true;
            }
        }
        const lineClamp = styles.getPropertyValue('-webkit-line-clamp');
        if (lineClamp && lineClamp !== 'none') {
            const range = this._document.createRange();
            range.selectNodeContents(el);
            const rangeHeight = range.getBoundingClientRect().height;
            const elHeight = el.getBoundingClientRect().height;
            const paddingTop = parseFloat(styles.paddingTop) || 0;
            const paddingBottom = parseFloat(styles.paddingBottom) || 0;
            const contentHeight = elHeight - paddingTop - paddingBottom;
            if (rangeHeight > contentHeight + 1) {
                return true;
            }
        }
        return false;
    }
    _isFormControlValueTruncated(el) {
        if (!el.value) {
            return false;
        }
        const styles = getComputedStyle(el);
        const availableWidth = el.clientWidth - (parseFloat(styles.paddingLeft) || 0) - (parseFloat(styles.paddingRight) || 0);
        const canvas = this._document.createElement('canvas');
        const context = canvas.getContext('2d');
        if (!context) {
            return el.scrollWidth > el.clientWidth;
        }
        context.font = styles.font;
        const valueWidth = context.measureText(el.value).width;
        const letterSpacing = parseFloat(styles.letterSpacing);
        const spacingWidth = Number.isNaN(letterSpacing) ? 0 : Math.max(0, el.value.length - 1) * letterSpacing;
        return valueWidth + spacingWidth > availableWidth;
    }
    hide() {
        this._delay(false, this._hideDelay());
    }
    toggle() {
        if (this._isVisible()) {
            this.hide();
            return;
        }
        this.show();
    }
    _createOverlay() {
        const anchorElement = this.zTriggerElement() || this._elementRef;
        const positionStrategy = this._overlayPositionBuilder
            .flexibleConnectedTo(anchorElement)
            .withPositions(getTooltipFallbackPositions(this._position(), this._offset()))
            .withFlexibleDimensions(false)
            .withPush(true);
        return this._overlay.create({
            positionStrategy,
            scrollStrategy: this._overlay.scrollStrategies.reposition(),
        });
    }
    _disposeOverlay() {
        this._positionSubscription?.unsubscribe();
        this._positionSubscription = null;
        this._overlayRef?.dispose();
        this._overlayRef = null;
        this._componentRef = null;
    }
    _setupDelayMechanism() {
        this._delaySubject
            .pipe(switchMap(config => (config.delay <= 0 ? of(config) : timer(config.delay).pipe(map(() => config)))), takeUntilDestroyed(this._destroyRef))
            .subscribe(config => {
            if (config.show) {
                this._showTooltip();
                return;
            }
            this._hideTooltip();
        });
    }
    _setupTriggers() {
        this._cleanupListeners();
        const trigger = this._trigger();
        const triggerEl = this.zTriggerElement() || this._elementRef.nativeElement;
        this._listenerCleanups.push(this._renderer.listen(this._document.defaultView, 'scroll', () => this._delay(false, 0), {
            passive: true,
            capture: true,
        }), this._renderer.listen(this._document.defaultView, 'resize', () => this._delay(false, 0), {
            passive: true,
        }), this._renderer.listen(this._document.defaultView, 'blur', () => this._delay(false, 0)));
        if (trigger === 'hover') {
            this._listenerCleanups.push(this._renderer.listen(triggerEl, 'mouseenter', () => this.show()), this._renderer.listen(triggerEl, 'mouseleave', () => this.hide()), this._renderer.listen(triggerEl, 'focus', () => this.show()), this._renderer.listen(triggerEl, 'blur', () => this.hide()));
            return;
        }
        if (trigger === 'click') {
            this._listenerCleanups.push(this._renderer.listen(triggerEl, 'click', () => {
                if (this._isVisible()) {
                    this._delay(false, 0);
                    return;
                }
                this._delay(true, this._showDelay());
            }));
        }
    }
    _setupOutsideClick() {
        if (!this._overlayRef) {
            return;
        }
        this._overlayRef
            .outsidePointerEvents()
            .pipe(filter(() => this._trigger() === 'click'), filter(event => !this._elementRef.nativeElement.contains(event.target)), takeUntilDestroyed(this._destroyRef))
            .subscribe(() => this._delay(false, 0));
    }
    _delay(show, delay) {
        this._delaySubject.next({ show, delay });
    }
    _showTooltip() {
        const content = this.zContent();
        if (!content || this._disabled()) {
            return;
        }
        if (this._componentRef) {
            this._clearHideTimeout();
            this._componentRef.instance.state.set('open');
            this._isVisible.set(true);
            return;
        }
        if (!this._overlayRef) {
            this._overlayRef = this._createOverlay();
            this._setupOutsideClick();
        }
        const anchorElement = this.zTriggerElement() || this._elementRef;
        const positionStrategy = this._overlayPositionBuilder
            .flexibleConnectedTo(anchorElement)
            .withPositions(getTooltipFallbackPositions(this._position(), this._offset()))
            .withFlexibleDimensions(false)
            .withPush(true);
        this._overlayRef.updatePositionStrategy(positionStrategy);
        const portal = new ComponentPortal(ZTooltipContentComponent);
        this._componentRef = this._overlayRef.attach(portal);
        this._componentRef.instance.setProps({
            content,
            position: this._position(),
            type: this.zType(),
            size: this.zSize(),
            customClass: this._class(),
            arrow: this._arrow(),
            maxWidth: this.zMaxWidth(),
        });
        this._positionSubscription = positionStrategy.positionChanges.subscribe(change => {
            const actualPosition = getActualPosition(change);
            this._componentRef?.instance.position.set(actualPosition);
            this._calculateArrowOffset(actualPosition);
        });
        if (this._trigger() === 'hover') {
            this._setupTooltipHover();
        }
        this._isVisible.set(true);
        this.zShow.emit();
    }
    _setupTooltipHover() {
        const overlayElement = this._overlayRef?.overlayElement;
        if (!overlayElement) {
            return;
        }
        this._listenerCleanups.push(this._renderer.listen(overlayElement, 'mouseenter', () => {
            this._delay(true, 0);
        }), this._renderer.listen(overlayElement, 'mouseleave', () => {
            this._delay(false, this._hideDelay());
        }));
    }
    _hideTooltip() {
        if (!this._componentRef) {
            return;
        }
        this._componentRef.instance.state.set('closed');
        this._clearHideTimeout();
        this._hideTimeout = setTimeout(() => {
            if (this._destroyRef.destroyed) {
                return;
            }
            this._disposeOverlay();
            this._isVisible.set(false);
            this.zHide.emit();
        }, Z_TOOLTIP_ANIMATION_DURATION);
    }
    _clearHideTimeout() {
        if (!this._hideTimeout) {
            return;
        }
        clearTimeout(this._hideTimeout);
        this._hideTimeout = null;
    }
    _cleanupListeners() {
        this._listenerCleanups.forEach(cleanup => cleanup());
        this._listenerCleanups = [];
    }
    _calculateArrowOffset(position) {
        if (!this._overlayRef || !this._componentRef) {
            return;
        }
        const triggerRect = this._elementRef.nativeElement.getBoundingClientRect();
        const tooltipRect = this._overlayRef.overlayElement.getBoundingClientRect();
        let offset = 0;
        if (position === 'top' || position === 'bottom') {
            const triggerCenterX = triggerRect.left + triggerRect.width / 2;
            const tooltipCenterX = tooltipRect.left + tooltipRect.width / 2;
            offset = triggerCenterX - tooltipCenterX;
        }
        if (position === 'left' || position === 'right') {
            const triggerCenterY = triggerRect.top + triggerRect.height / 2;
            const tooltipCenterY = tooltipRect.top + tooltipRect.height / 2;
            offset = triggerCenterY - tooltipCenterY;
        }
        const maxOffset = position === 'top' || position === 'bottom' ? tooltipRect.width / 2 - 12 : tooltipRect.height / 2 - 12;
        offset = Math.max(-maxOffset, Math.min(maxOffset, offset));
        if (Math.abs(offset) > 1) {
            this._componentRef.instance.arrowOffset.set(offset);
            return;
        }
        this._componentRef.instance.arrowOffset.set(0);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.9", type: ZTooltipDirective, isStandalone: true, selector: "[z-tooltip], [zTooltip]", inputs: { zContent: { classPropertyName: "zContent", publicName: "zContent", isSignal: true, isRequired: false, transformFunction: null }, zPosition: { classPropertyName: "zPosition", publicName: "zPosition", isSignal: true, isRequired: false, transformFunction: null }, zTooltipPosition: { classPropertyName: "zTooltipPosition", publicName: "zTooltipPosition", isSignal: true, isRequired: false, transformFunction: null }, zTrigger: { classPropertyName: "zTrigger", publicName: "zTrigger", isSignal: true, isRequired: false, transformFunction: null }, zTooltipTrigger: { classPropertyName: "zTooltipTrigger", publicName: "zTooltipTrigger", isSignal: true, isRequired: false, transformFunction: null }, zType: { classPropertyName: "zType", publicName: "zTooltipType", isSignal: true, isRequired: false, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zTooltipSize", isSignal: true, isRequired: false, transformFunction: null }, zClass: { classPropertyName: "zClass", publicName: "zClass", isSignal: true, isRequired: false, transformFunction: null }, zTooltipClass: { classPropertyName: "zTooltipClass", publicName: "zTooltipClass", isSignal: true, isRequired: false, transformFunction: null }, zShowDelay: { classPropertyName: "zShowDelay", publicName: "zShowDelay", isSignal: true, isRequired: false, transformFunction: null }, zTooltipShowDelay: { classPropertyName: "zTooltipShowDelay", publicName: "zTooltipShowDelay", isSignal: true, isRequired: false, transformFunction: null }, zHideDelay: { classPropertyName: "zHideDelay", publicName: "zHideDelay", isSignal: true, isRequired: false, transformFunction: null }, zTooltipHideDelay: { classPropertyName: "zTooltipHideDelay", publicName: "zTooltipHideDelay", isSignal: true, isRequired: false, transformFunction: null }, zArrow: { classPropertyName: "zArrow", publicName: "zArrow", isSignal: true, isRequired: false, transformFunction: null }, zTooltipArrow: { classPropertyName: "zTooltipArrow", publicName: "zTooltipArrow", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null }, zTooltipDisabled: { classPropertyName: "zTooltipDisabled", publicName: "zTooltipDisabled", isSignal: true, isRequired: false, transformFunction: null }, zOffset: { classPropertyName: "zOffset", publicName: "zOffset", isSignal: true, isRequired: false, transformFunction: null }, zTooltipOffset: { classPropertyName: "zTooltipOffset", publicName: "zTooltipOffset", isSignal: true, isRequired: false, transformFunction: null }, zAutoDetect: { classPropertyName: "zAutoDetect", publicName: "zAutoDetect", isSignal: true, isRequired: false, transformFunction: null }, zTriggerElement: { classPropertyName: "zTriggerElement", publicName: "zTriggerElement", isSignal: true, isRequired: false, transformFunction: null }, zAlwaysShow: { classPropertyName: "zAlwaysShow", publicName: "zAlwaysShow", isSignal: true, isRequired: false, transformFunction: null }, zMaxWidth: { classPropertyName: "zMaxWidth", publicName: "zMaxWidth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zShow: "zShow", zHide: "zHide" }, exportAs: ["zTooltip"], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZTooltipDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[z-tooltip], [zTooltip]',
                    standalone: true,
                    exportAs: 'zTooltip',
                }]
        }], ctorParameters: () => [], propDecorators: { zContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "zContent", required: false }] }], zPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPosition", required: false }] }], zTooltipPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltipPosition", required: false }] }], zTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTrigger", required: false }] }], zTooltipTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltipTrigger", required: false }] }], zType: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltipType", required: false }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltipSize", required: false }] }], zClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zClass", required: false }] }], zTooltipClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltipClass", required: false }] }], zShowDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowDelay", required: false }] }], zTooltipShowDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltipShowDelay", required: false }] }], zHideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zHideDelay", required: false }] }], zTooltipHideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltipHideDelay", required: false }] }], zArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "zArrow", required: false }] }], zTooltipArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltipArrow", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zTooltipDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltipDisabled", required: false }] }], zOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOffset", required: false }] }], zTooltipOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTooltipOffset", required: false }] }], zAutoDetect: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutoDetect", required: false }] }], zTriggerElement: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTriggerElement", required: false }] }], zAlwaysShow: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAlwaysShow", required: false }] }], zMaxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMaxWidth", required: false }] }], zShow: [{ type: i0.Output, args: ["zShow"] }], zHide: [{ type: i0.Output, args: ["zHide"] }] } });

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

export { ZTooltipDirective, zTooltipVariants };
//# sourceMappingURL=shival99-z-ui-components-z-tooltip.mjs.map
