/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Lifecycle } from "./Lifecycle.js";
import { Lifetime } from "./Lifetime.js";
import { Observable } from "./Observable.js";
import { MaybePromise } from "./Promises.js";
/**
 * Create an instance of a class implementing the {@link Constructable} pattern.
 */
export declare function asyncNew<const A extends any[], const C extends new (...args: A) => Constructable<any>>(constructor: C, ...args: A): Promise<InstanceType<C>>;
/**
 * A pattern for asynchronous object initialization and cleanup of a target object, called the "subject".
 *
 * Construction happens in the initializer parameter of {@link Construction} or via {@link Construction.construct} on
 * the subject.  You invoke in your constructor and place in a property called "construction".
 *
 * Destruction is optional and happens in the destructor parameter of {@link Construction#close} or via
 * {@link Construction.destruct} on the subject.  Typically you invoke in a "close" method of the subject.
 *
 * If construction or destruction is not asynchronous (does not return a Promise) then they complete synchronously,
 * including throwing exceptions.
 *
 * To ensure an instance is initialized prior to use you may await construction, so e.g. `await new
 * MyConstructable().construction`. {@link asyncNew} is shorthand for this.  The creation code path can instead await
 * {@link Construction.ready} to ensure handling of the root cause.
 *
 * Public APIs should provide a static async create() that performs an asyncNew().  The class will then adhere to
 * Matter.js conventions and library users can ignore the complexities associated with async creation.
 */
export interface Constructable<T = object> {
    readonly construction: Construction<T>;
}
export declare namespace Constructable {
    /**
     * An {@link Constructable} that supports deferred construction.
     *
     * This supports use cases where initialization initiates separately from construction and/or reinitialization is
     * possible.
     */
    interface Deferred<T, A extends unknown[]> extends Constructable<T> {
        /**
         * Perform deferred construction.
         */
        [Construction.construct](...args: A): MaybePromise<void>;
    }
    /**
     * An object that supports destruction.
     */
    interface Destructable {
        /**
         * Perform destruction. This is used invoked by {@link Constructable#close} after transitioning to
         * {@link Lifecycle.Status.Destroying} but before transitioning to {@link Lifecycle.Status.Destroyed}.
         *
         * This is separate from {@link Symbol.dispose}/{@link Symbol.asyncDispose} so those can invoke
         * {@link Constructable#close}.
         */
        [Construction.destruct](): MaybePromise<void>;
    }
}
/**
 * The promise implementing by an {@link Constructable#construction}.
 */
export interface Construction<T> extends Promise<T>, Lifetime.Owner {
    /**
     * If construction ends with an error, the error is saved here.
     */
    readonly error?: Error;
    /**
     * Status of the constructed object.
     */
    readonly status: Lifecycle.Status;
    /**
     * Notifications of state change.  Normally you just await construction but this offers more granular events and
     * repeating events.
     */
    readonly change: Observable<[status: Lifecycle.Status, subject: T]>;
    /**
     * True iff the primary error has been or will be reported.
     */
    readonly isErrorHandled: boolean;
    /**
     * Resolves when construction completes; rejects if construction crashes.
     *
     * Behaves identically to {@link Construction} but always throws the primary cause rather than
     * {@link CrashedDependencyError}.
     *
     * Handling errors on this promise will prevent other handlers from seeing the primary cause.
     */
    readonly ready: Promise<T>;
    /**
     * Resolves when destruction completes; rejects if the component crashes.
     *
     * Handling errors on this promise will prevent other handlers from seeing the primary cause.
     */
    readonly closed: Promise<T>;
    /**
     * If you omit the initializer parameter to {@link Construction} execution is deferred until you invoke this
     * method to initiate construction via the {@link Constructable.Deferred} interface.
     *
     * Unlike the initializer, errors are always reported via the PromiseLike interface even if the constructable throws
     * an error synchronously.
     */
    start<const T, const A extends unknown[], const This extends Construction<Constructable.Deferred<T, A>>>(this: This, ...args: A): void;
    /**
     * Invoke destruction logic then move to destroyed status.
     *
     * Typically you invoke this in the subject's "close" method.
     *
     * Use of this function is optional.  It provides these benefits:
     *
     *   - Ensures the subject is fully initialized before closing.
     *
     *   - Guards against closing multiple times; tertiary closes will wait for destruction.
     *
     *   - Handles and logs errors, ensuring close() always completes successfully.
     *
     *   - Makes destruction observable via {@link change} and {@link closed}.
     */
    close(destructor?: () => MaybePromise): MaybePromise;
    /**
     * Throws an error if construction is ongoing or incomplete.
     */
    assert(description?: string): void;
    /**
     * Asserts construction is complete and that an object is defined.
     */
    assert<T>(description: string, dependency: T | undefined): T;
    /**
     * Manually force a specific {@link status}.
     *
     * This offers flexibility in component lifecycle management including resetting component to inactive state and
     * broadcasting lifecycle changes.  On reset listeners are also reset and must be reinstalled.
     *
     * This method fails if initialization is ongoing; await completion first.
     */
    setStatus(status: Lifecycle.Status): void;
    /**
     * Move subject to "crashed" state, optionally setting the cause.
     *
     * This happens automatically if there is an error during construction.  It is also useful for post-construction
     * errors to convey crashed state to components such as the environmental runtime service.
     */
    crash(cause?: any): void;
    /**
     * Invoke a method after construction completes successfully.
     *
     * Errors thrown by this callback are logged but otherwise ignored.
     */
    onSuccess(actor: () => MaybePromise<void>): void;
    /**
     * Invoke a method after construction completes unsuccessfully.
     *
     * If you register an onError handler then the default error handler will not log the error.
     *
     * Errors thrown by this callback are logged but otherwise ignored.
     */
    onError(actor: (error: Error) => MaybePromise<void>): void;
    /**
     * Invoke a method after construction completes successfully or onsuccessfully.
     *
     * Errors thrown by this callback are logged but otherwise ignored.
     */
    onCompletion(actor: () => void): void;
    toString(): string;
}
/**
 * Create an {@link Constructable} and optionally begin async construction.
 */
export declare function Construction<const T extends Constructable>(subject: T, initializer?: () => MaybePromise): Construction<T>;
export declare namespace Construction {
    /**
     * Ensure a pool of {@link Constructable}s are initialized.  Returns a promise if any constructables are still
     * initializing or there is an error.
     *
     * @param subjects the constructables to monitor; may mutate whilst construction is ongoing
     * @param onError error handler; if returns error it is thrown; if omitted throws CrashedDependenciesError
     */
    function all<T extends Constructable>(subjects: Iterable<T>, onError?: (errored: Iterable<T>) => void | Error): MaybePromise;
    const construct: unique symbol;
    const destruct: unique symbol;
}
//# sourceMappingURL=Construction.d.ts.map