import * as i0 from '@angular/core';
import { InjectionToken, signal, Injectable, model, computed, Injector, Input, Component, inject, ApplicationRef, EnvironmentInjector, DestroyRef, createComponent } from '@angular/core';
import { NgComponentOutlet, DOCUMENT } from '@angular/common';
import { DynamicDialogRef } from 'primeng/dynamicdialog';
import * as i1 from 'primeng/drawer';
import { DrawerModule } from 'primeng/drawer';
import { Button } from '@masterteam/components/button';

const DynamicDrawerConfig = new InjectionToken('DynamicDrawerConfig');
/**
 * Controller to dynamically update drawer properties from inside the child component.
 * Inject this in your drawer content component to modify drawer behavior.
 */
class DrawerController {
    _styleClass = signal('', ...(ngDevMode ? [{ debugName: "_styleClass" }] : []));
    _header = signal('', ...(ngDevMode ? [{ debugName: "_header" }] : []));
    _fullScreen = signal(undefined, ...(ngDevMode ? [{ debugName: "_fullScreen" }] : []));
    /** Get the current additional styleClass */
    get styleClass() {
        return this._styleClass;
    }
    /** Get the current header */
    get header() {
        return this._header;
    }
    /** Get the current fullScreen state */
    get fullScreen() {
        return this._fullScreen;
    }
    /** Add or replace the dynamic styleClass */
    setStyleClass(styleClass) {
        this._styleClass.set(styleClass);
    }
    /** Append a class to the existing styleClass */
    addClass(className) {
        const current = this._styleClass();
        if (!current.includes(className)) {
            this._styleClass.set((current + ' ' + className).trim());
        }
    }
    /** Remove a class from the styleClass */
    removeClass(className) {
        const current = this._styleClass();
        this._styleClass.set(current
            .split(' ')
            .filter((c) => c !== className)
            .join(' '));
    }
    /** Toggle a class on/off */
    toggleClass(className) {
        if (this._styleClass().includes(className)) {
            this.removeClass(className);
        }
        else {
            this.addClass(className);
        }
    }
    /** Update the drawer header */
    setHeader(header) {
        this._header.set(header);
    }
    /** Toggle fullScreen mode */
    setFullScreen(fullScreen) {
        this._fullScreen.set(fullScreen);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DrawerController, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DrawerController });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DrawerController, decorators: [{
            type: Injectable
        }] });
class DynamicDrawerHost {
    visible = model(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
    cmp = signal(null, ...(ngDevMode ? [{ debugName: "cmp" }] : []));
    cfg = signal({}, ...(ngDevMode ? [{ debugName: "cfg" }] : []));
    cmpInputs = signal({}, ...(ngDevMode ? [{ debugName: "cmpInputs" }] : []));
    childInjector;
    ref;
    drawerController = new DrawerController();
    /** Computed styleClass combining config + dynamic controller class */
    computedStyleClass = computed(() => {
        const configClass = this.cfg()?.styleClass ?? '';
        const dynamicClass = this.drawerController.styleClass();
        return `${configClass} ${dynamicClass} mt-drawer`.trim();
    }, ...(ngDevMode ? [{ debugName: "computedStyleClass" }] : []));
    /** Computed header - controller overrides config if set */
    computedHeader = computed(() => {
        const dynamicHeader = this.drawerController.header();
        return dynamicHeader || this.cfg()?.header || '';
    }, ...(ngDevMode ? [{ debugName: "computedHeader" }] : []));
    /** Computed fullScreen - controller overrides config if set */
    computedFullScreen = computed(() => {
        const dynamicFullScreen = this.drawerController.fullScreen();
        return dynamicFullScreen !== undefined
            ? dynamicFullScreen
            : this.cfg()?.fullScreen;
    }, ...(ngDevMode ? [{ debugName: "computedFullScreen" }] : []));
    connect(opts) {
        this.cmp.set(opts.component);
        this.cfg.set(opts.config ?? {});
        this.cmpInputs.set(opts.config?.inputValues ?? {});
        this.ref = opts.ref;
        this.childInjector = Injector.create({
            parent: opts.parent,
            providers: [
                { provide: DynamicDrawerConfig, useValue: opts.config ?? {} },
                { provide: DynamicDialogRef, useValue: opts.ref },
                { provide: DrawerController, useValue: this.drawerController },
            ],
        });
        opts.ref.onClose.subscribe(() => {
            this.visible.set(false);
        });
        this.visible.set(true);
    }
    handleHide(data = null) {
        this.visible.set(false);
        this.ref?.close(data);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DynamicDrawerHost, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.3", type: DynamicDrawerHost, isStandalone: true, selector: "mt-dynamic-drawer-host", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, connect: { classPropertyName: "connect", publicName: "connect", isSignal: false, isRequired: true, transformFunction: null } }, outputs: { visible: "visibleChange" }, ngImport: i0, template: `
    <p-drawer
      [(visible)]="visible"
      [closable]="cfg()?.closable"
      [position]="cfg()?.position"
      [fullScreen]="computedFullScreen()"
      [modal]="cfg()?.modal"
      [closeOnEscape]="cfg()?.closeOnEscape"
      [dismissible]="cfg()?.dismissible"
      [transitionOptions]="cfg()?.transitionOptions"
      [styleClass]="computedStyleClass()"
    >
      <ng-template #header>
        <div
          class="flex items-center justify-between px-5 w-full py-3 border-b border-surface"
        >
          <h3 class="text-xl font-semibold">{{ computedHeader() }}</h3>
          <mt-button
            (onClick)="handleHide()"
            variant="outlined"
            styleClass="!bg-white"
            icon="general.x-close"
            severity="secondary"
          >
          </mt-button>
        </div>
      </ng-template>

      <ng-container
        *ngComponentOutlet="cmp(); injector: childInjector; inputs: cmpInputs()"
      >
      </ng-container>
    </p-drawer>
  `, isInline: true, dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i1.Drawer, selector: "p-drawer", inputs: ["appendTo", "motionOptions", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DynamicDrawerHost, decorators: [{
            type: Component,
            args: [{
                    selector: 'mt-dynamic-drawer-host',
                    standalone: true,
                    imports: [NgComponentOutlet, DrawerModule, Button],
                    template: `
    <p-drawer
      [(visible)]="visible"
      [closable]="cfg()?.closable"
      [position]="cfg()?.position"
      [fullScreen]="computedFullScreen()"
      [modal]="cfg()?.modal"
      [closeOnEscape]="cfg()?.closeOnEscape"
      [dismissible]="cfg()?.dismissible"
      [transitionOptions]="cfg()?.transitionOptions"
      [styleClass]="computedStyleClass()"
    >
      <ng-template #header>
        <div
          class="flex items-center justify-between px-5 w-full py-3 border-b border-surface"
        >
          <h3 class="text-xl font-semibold">{{ computedHeader() }}</h3>
          <mt-button
            (onClick)="handleHide()"
            variant="outlined"
            styleClass="!bg-white"
            icon="general.x-close"
            severity="secondary"
          >
          </mt-button>
        </div>
      </ng-template>

      <ng-container
        *ngComponentOutlet="cmp(); injector: childInjector; inputs: cmpInputs()"
      >
      </ng-container>
    </p-drawer>
  `,
                }]
        }], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }, { type: i0.Output, args: ["visibleChange"] }], connect: [{
                type: Input,
                args: [{ required: true }]
            }] } });

// dynamic-drawer.service.ts
class DrawerService {
    appRef = inject(ApplicationRef);
    env = inject(EnvironmentInjector);
    rootInjector = inject(Injector);
    destroyRef = inject(DestroyRef);
    doc = inject(DOCUMENT);
    hostRef;
    defauiltConfig = {
        position: 'right',
        modal: true,
        closable: false,
        transitionOptions: '200ms cubic-bezier(0, 0, 1, 1)',
        inputValues: {},
    };
    open(component, config = {}) {
        config = { ...this.defauiltConfig, ...config };
        const targetEl = this.resolveAppendTarget(config.appendTo);
        this.hostRef = createComponent(DynamicDrawerHost, {
            environmentInjector: this.env,
        });
        this.appRef.attachView(this.hostRef.hostView);
        // 📌 append to target (NOT body when provided)
        targetEl.appendChild(this.hostRef.location.nativeElement);
        // 🧹 auto-clean if app destroyed (SSR / HMR safety)
        this.destroyRef.onDestroy(() => {
            this.appRef.detachView(this.hostRef.hostView);
            this.hostRef.destroy();
            this.hostRef = undefined;
        });
        const ref = new DynamicDialogRef();
        this.hostRef.instance.connect({
            component,
            config,
            parent: this.rootInjector,
            ref,
        });
        return ref;
    }
    resolveAppendTarget(appendTo) {
        if (!appendTo)
            return this.doc.body;
        if (typeof appendTo === 'string') {
            const selector = appendTo.startsWith('#') || appendTo.startsWith('.')
                ? appendTo
                : `#${appendTo}`;
            const el = this.doc.querySelector(selector);
            if (!el) {
                return this.doc.body;
            }
            return el;
        }
        return appendTo; // HTMLElement passed directly
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DrawerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DrawerService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: DrawerService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

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

export { DrawerController, DrawerService, DynamicDrawerConfig, DynamicDrawerHost };
//# sourceMappingURL=masterteam-components-dynamic-drawer.mjs.map
