import * as _angular_core from '@angular/core';
import { Signal, Provider, ViewContainerRef, TemplateRef, AfterContentInit, OnDestroy, OnInit, ElementRef } from '@angular/core';
import { RxStrategyNames } from '@rx-angular/cdk/render-strategies';
import { Observable } from 'rxjs';

interface RxVirtualViewConfig {
    enabled: boolean | Signal<boolean>;
    keepLastKnownSize: boolean;
    useContentVisibility: boolean;
    useContainment: boolean;
    placeholderStrategy: RxStrategyNames<string>;
    contentStrategy: RxStrategyNames<string>;
    cacheEnabled: boolean;
    startWithPlaceholderAsap: boolean;
    /**
     * The scroll margin to observe.
     *
     * Docs: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#scrollmargin
     */
    scrollMargin: string;
    /**
     * Whether to enable the visibility after hydration. (DEFAULT: true)
     *
     * If `false`, the elements that were hydrated, won't go back to render placeholder anymore on hydration.
     * You can disable this to avoid destroying components that were just hydrated.
     */
    enableAfterHydration: boolean;
    cache: {
        /**
         * The maximum number of contents that can be stored in the cache.
         * Defaults to 20.
         */
        contentCacheSize: number;
        /**
         * The maximum number of placeholders that can be stored in the cache.
         * Defaults to 20.
         */
        placeholderCacheSize: number;
    };
}
/**
 * Provides a configuration object for the `VirtualView` service.
 *
 * Can be used to customize the behavior of the `VirtualView` service.
 *
 * Default configuration:
 * - contentCacheSize: 20
 * - placeholderCacheSize: 20
 *
 * Example usage:
 *
 * ```ts
 * import { provideVirtualViewConfig } from '@rx-angular/template/virtual-view';
 *
 * const appConfig: ApplicationConfig = {
 *   providers: [
 *     provideVirtualViewConfig({
 *       contentCacheSize: 50,
 *       placeholderCacheSize: 50,
 *     }),
 *   ],
 * };
 * ```
 *
 * @developerPreview
 *
 * @param config - The configuration object.
 * @returns An object that can be provided to the `VirtualView` service.
 */
declare function provideVirtualViewConfig(config: VVConfig | (() => VVConfig)): Provider;
type VVConfig = Partial<RxVirtualViewConfig & {
    cache?: Partial<RxVirtualViewConfig['cache']>;
}>;

/**
 * @internal
 */
interface _RxVirtualViewContent {
    viewContainerRef: ViewContainerRef;
    templateRef: TemplateRef<unknown>;
}
/**
 * @internal
 */
interface _RxVirtualViewPlaceholder {
    templateRef: TemplateRef<unknown>;
}
/**
 * @internal
 */
declare abstract class _RxVirtualViewObserver {
    abstract observeElementVisibility(virtualView: HTMLElement): Observable<boolean>;
    abstract observeElementSize(element: Element, options?: ResizeObserverOptions): Observable<ResizeObserverEntry>;
}
/**
 * @internal
 */
declare abstract class _RxVirtualView {
    abstract registerContent(content: _RxVirtualViewContent): void;
    abstract registerPlaceholder(placeholder: _RxVirtualViewPlaceholder): void;
}

/**
 * The RxVirtualView directive is a directive that allows you to create virtual views.
 *
 * It can be used on an element/component to create a virtual view.
 *
 * It works by using 3 directives:
 * - `rxVirtualViewContent`: The content to render when the virtual view is visible.
 * - `rxVirtualViewPlaceholder`: The placeholder to render when the virtual view is not visible.
 * - `rxVirtualViewObserver`: The directive that observes the virtual view and emits a boolean value indicating whether the virtual view is visible.
 *
 * The `rxVirtualViewObserver` directive is mandatory for the `rxVirtualView` directive to work.
 * And it needs to be a sibling of the `rxVirtualView` directive.
 *
 * @example
 * ```html
 * <div rxVirtualViewObserver>
 *   <div rxVirtualView>
 *     <div *rxVirtualViewContent>Virtual View 1</div>
 *     <div *rxVirtualViewPlaceholder>Loading...</div>
 *   </div>
 * </div>
 * ```
 *
 * @developerPreview
 */
declare class RxVirtualView implements AfterContentInit, _RxVirtualView, OnDestroy {
    #private;
    /**
     * Useful when we want to cache the templates and placeholders to optimize view rendering.
     *
     * Enabled by default.
     */
    readonly cacheEnabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * Whether to start with the placeholder asap or not.
     *
     * If `true`, the placeholder will be rendered immediately, without waiting for the content to be visible.
     * This is useful when you want to render the placeholder immediately, but you don't want to wait for the content to be visible.
     *
     * This is to counter concurrent rendering, and to avoid flickering.
     */
    readonly startWithPlaceholderAsap: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * This will keep the last known size of the host element while the content is visible.
     */
    readonly keepLastKnownSize: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * Whether to use content visibility or not.
     *
     * It will add the `content-visibility` CSS class to the host element, together with
     * `contain-intrinsic-width` and `contain-intrinsic-height` CSS properties.
     */
    readonly useContentVisibility: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * Whether to use containment or not.
     *
     * It will add `contain` css property with:
     * - `size layout paint`: if `useContentVisibility` is `true` && placeholder is visible
     * - `content`: if `useContentVisibility` is `false` || content is visible
     */
    readonly useContainment: _angular_core.InputSignalWithTransform<boolean, unknown>;
    /**
     * The strategy to use for rendering the placeholder.
     */
    readonly placeholderStrategy: _angular_core.InputSignal<string>;
    /**
     * The strategy to use for rendering the content.
     */
    readonly contentStrategy: _angular_core.InputSignal<string>;
    /**
     * A function extracting width & height from a ResizeObserverEntry
     */
    readonly extractSize: _angular_core.InputSignal<(entry: ResizeObserverEntry) => {
        width: number;
        height: number;
    }>;
    /**
     * ResizeObserverOptions
     */
    readonly resizeObserverOptions: _angular_core.InputSignal<ResizeObserverOptions>;
    /**
     * Emits when the visibility state of the virtual view changes.
     *
     * This output fires whenever the virtual view transitions between showing content and showing placeholder.
     * The emitted value is an object containing the current visibility state of both the content and placeholder.
     *
     * @example
     * ```html
     * <div rxVirtualViewObserver>
     *   <div rxVirtualView (visibilityChanged)="onVisibilityChanged($event)">
     *     <div *rxVirtualViewContent>Virtual View Content</div>
     *     <div *rxVirtualViewPlaceholder>Loading...</div>
     *   </div>
     * </div>
     * ```
     *
     * ```typescript
     * onVisibilityChanged(event: { content: boolean; placeholder: boolean }) {
     *   console.log('Content visible:', event.content);
     *   console.log('Placeholder visible:', event.placeholder);
     * }
     * ```
     */
    readonly visibilityChanged: _angular_core.OutputEmitterRef<{
        content: boolean;
        placeholder: boolean;
    }>;
    /**
     * Returns the current visibility state of the content and placeholder.
     *
     * This getter provides synchronous access to the visibility state, which can be useful
     * when you need to check the current state imperatively or from the template.
     *
     * @returns An object containing:
     * - `content`: `true` if the content is currently visible, `false` otherwise
     * - `placeholder`: `true` if the placeholder is currently visible, `false` otherwise
     *
     * @example
     * ```html
     * <!-- Access visibility state in template using exportAs -->
     * <div rxVirtualViewObserver>
     *   <div rxVirtualView #virtualView="rxVirtualView">
     *     <div *rxVirtualViewContent>Virtual View Content</div>
     *     <div *rxVirtualViewPlaceholder>Loading...</div>
     *   </div>
     *
     *   <!-- Display visibility state -->
     *   <div>
     *     Content visible: {{ virtualView.visibility.content }}
     *     Placeholder visible: {{ virtualView.visibility.placeholder }}
     *   </div>
     * </div>
     * ```
     */
    get visibility(): {
        content: boolean;
        placeholder: boolean;
    };
    readonly size: _angular_core.WritableSignal<{
        width: number;
        height: number;
    }>;
    readonly width: _angular_core.Signal<string>;
    readonly height: _angular_core.Signal<string>;
    readonly containment: _angular_core.Signal<"size layout paint" | "content">;
    readonly intrinsicWidth: _angular_core.Signal<string>;
    readonly intrinsicHeight: _angular_core.Signal<string>;
    readonly minHeight: _angular_core.Signal<string>;
    readonly minWidth: _angular_core.Signal<string>;
    constructor();
    ngAfterContentInit(): void;
    ngOnDestroy(): void;
    registerContent(content: _RxVirtualViewContent): void;
    registerPlaceholder(placeholder: _RxVirtualViewPlaceholder): void;
    /**
     * Shows the content using the configured rendering strategy (by default: normal).
     * @private
     */
    private showContent$;
    /**
     * Shows the placeholder using the configured rendering strategy (by default: low).
     * @private
     */
    private showPlaceholder$;
    /**
     * Renders a placeholder within the view container, and hides the content.
     *
     * If we already have a content and cache enabled, we store the content in
     * the cache, so we can reuse it later.
     *
     * When we want to render the placeholder, we try to get it from the cache,
     * and if it is not available, we create a new one.
     *
     * Then insert the placeholder into the view container and trigger a CD.
     */
    private renderPlaceholder;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<RxVirtualView, never>;
    static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RxVirtualView, "[rxVirtualView]", ["rxVirtualView"], { "cacheEnabled": { "alias": "cacheEnabled"; "required": false; "isSignal": true; }; "startWithPlaceholderAsap": { "alias": "startWithPlaceholderAsap"; "required": false; "isSignal": true; }; "keepLastKnownSize": { "alias": "keepLastKnownSize"; "required": false; "isSignal": true; }; "useContentVisibility": { "alias": "useContentVisibility"; "required": false; "isSignal": true; }; "useContainment": { "alias": "useContainment"; "required": false; "isSignal": true; }; "placeholderStrategy": { "alias": "placeholderStrategy"; "required": false; "isSignal": true; }; "contentStrategy": { "alias": "contentStrategy"; "required": false; "isSignal": true; }; "extractSize": { "alias": "extractSize"; "required": false; "isSignal": true; }; "resizeObserverOptions": { "alias": "resizeObserverOptions"; "required": false; "isSignal": true; }; }, { "visibilityChanged": "visibilityChanged"; }, never, never, true, never>;
}

/**
 * The RxVirtualViewTemplate directive is a directive that allows you to create a content template for the virtual view.
 *
 * It can be used on an element/component to create a content template for the virtual view.
 *
 * It needs to be a sibling of the `rxVirtualView` directive.
 *
 * @example
 * ```html
 * <div rxVirtualViewObserver>
 *   <div rxVirtualView>
 *     <div *rxVirtualViewContent>Virtual View 1</div>
 *     <div *rxVirtualViewPlaceholder>Loading...</div>
 *   </div>
 * </div>
 * ```
 *
 * @developerPreview
 */
declare class RxVirtualViewContent implements _RxVirtualViewContent {
    #private;
    templateRef: TemplateRef<unknown>;
    viewContainerRef: ViewContainerRef;
    constructor(templateRef: TemplateRef<unknown>);
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<RxVirtualViewContent, never>;
    static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RxVirtualViewContent, "[rxVirtualViewContent]", never, {}, {}, never, never, true, never>;
}

/**
 * The RxVirtualViewObserver directive observes the virtual view and emits a boolean value indicating whether the virtual view is visible.
 * This is the container for the RxVirtualView directives.
 *
 * This is a mandatory directive for the RxVirtualView directives to work.
 *
 * @example
 * ```html
 * <div rxVirtualViewObserver>
 *   <div rxVirtualView>
 *     <div *rxVirtualViewContent>Virtual View 1</div>
 *     <div *rxVirtualViewPlaceholder>Loading...</div>
 *   </div>
 * </div>
 * ```
 *
 * @developerPreview
 */
declare class RxVirtualViewObserver extends _RxVirtualViewObserver implements OnInit, OnDestroy {
    #private;
    /**
     * The root element to observe.
     *
     * If not provided, the root element is the element that the directive is attached to.
     */
    root: _angular_core.InputSignal<HTMLElement | ElementRef<any>>;
    /**
     * The root margin to observe.
     *
     * This is useful when you want to observe the virtual view in a specific area of the root element.
     */
    rootMargin: _angular_core.InputSignal<string>;
    /**
     * The scroll margin to observe.
     *
     * This is useful when you want to observe the virtual view in a specific area of the scroll container.
     */
    scrollMargin: _angular_core.InputSignal<string>;
    /**
     * The threshold to observe.
     *
     * If you want to observe the virtual view when it is partially visible, you can set the threshold to a number between 0 and 1.
     *
     * For example, if you set the threshold to 0.5, the virtual view will be observed when it is half visible.
     */
    threshold: _angular_core.InputSignal<number | number[]>;
    ngOnInit(): void;
    ngOnDestroy(): void;
    /**
     * Hide all the virtual views.
     *
     * This is useful when you want to hide all the virtual views when the user cannot see them.
     *
     * For example, when the user opens a modal, you can hide all the virtual views to improve performance.
     *
     * **IMPORTANT:**
     *
     * Don't forget to call `showAllVisible()` when you want to show the virtual views again.
     */
    hideAll(): void;
    /**
     * Show all the virtual views that are currently visible.
     *
     * This needs to be called if `hideAll()` was called before.
     */
    showAllVisible(): void;
    observeElementVisibility(virtualView: HTMLElement): Observable<boolean>;
    observeElementSize(element: Element, options?: ResizeObserverOptions): Observable<ResizeObserverEntry>;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<RxVirtualViewObserver, never>;
    static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RxVirtualViewObserver, "[rxVirtualViewObserver]", never, { "root": { "alias": "root"; "required": false; "isSignal": true; }; "rootMargin": { "alias": "rootMargin"; "required": false; "isSignal": true; }; "scrollMargin": { "alias": "scrollMargin"; "required": false; "isSignal": true; }; "threshold": { "alias": "threshold"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}

/**
 * The RxVirtualViewPlaceholder directive is a directive that allows you to create a placeholder for the virtual view.
 *
 * It can be used on an element/component to create a placeholder for the virtual view.
 *
 * It needs to be a sibling of the `rxVirtualView` directive.
 *
 * @example
 * ```html
 * <div rxVirtualViewObserver>
 *   <div rxVirtualView>
 *     <div *rxVirtualViewContent>Virtual View 1</div>
 *     <div *rxVirtualViewPlaceholder>Loading...</div>
 *   </div>
 * </div>
 * ```
 *
 * @developerPreview
 */
declare class RxVirtualViewPlaceholder implements _RxVirtualViewPlaceholder {
    #private;
    templateRef: TemplateRef<unknown>;
    constructor(templateRef: TemplateRef<unknown>);
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<RxVirtualViewPlaceholder, never>;
    static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RxVirtualViewPlaceholder, "[rxVirtualViewPlaceholder]", never, {}, {}, never, never, true, never>;
}

export { RxVirtualView, RxVirtualViewContent, RxVirtualViewObserver, RxVirtualViewPlaceholder, provideVirtualViewConfig };
export type { RxVirtualViewConfig };
