/**
 * @license
 * Copyright 2022-2024 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import type { Agent } from "#endpoint/Agent.js";
import { AsyncObservable, EventEmitter, MaybePromise, Observable } from "#general";
import { ClusterComposer, ClusterType, ElementModifier, TypeFromBitSchema } from "#types";
import { Behavior } from "../Behavior.js";
import type { BehaviorBacking } from "../internal/BehaviorBacking.js";
import type { RootSupervisor } from "../supervision/RootSupervisor.js";
import { Schema } from "../supervision/Schema.js";
import { NetworkBehavior } from "../system/network/NetworkBehavior.js";
import { ExtensionInterfaceOf, type ClusterOf } from "./ClusterBehaviorUtil.js";
import type { ClusterEvents } from "./ClusterEvents.js";
import { ClusterInterface } from "./ClusterInterface.js";
import type { ClusterState } from "./ClusterState.js";
/**
 * A {@link Behavior} with specialization for a specific cluster.
 *
 * To implement cluster functionality you should use a subclass provided by {@link ClusterBehavior.for} with the
 * {@link ClusterType} you are implementing.  Most commonly you would use one of the predefined implementations
 * matter.js includes.
 *
 * Subclasses can be modified using the static builder methods or extended like a normal class.
 *
 * Behaviors should store all mutable state in their {@link Behavior.state} property.  Other fields will be transient
 * and may not be retained across invocations.
 *
 * ClusterBehaviors may be instantiated with unsupported mandatory commands and attributes.  This is currently results
 * in a runtime error but it will not cause a type error during development.
 */
export declare class ClusterBehavior extends Behavior {
    /**
     * The ID of ClusterBehavior implementations is the uncapitalized cluster name.
     */
    static id: Uncapitalize<string>;
    /**
     * The cluster implemented by this behavior.
     */
    get cluster(): ClusterType.Of<{
        readonly id: 0;
        readonly revision: 0;
        readonly name: "Unknown";
        readonly attributes: {};
        readonly commands: {};
        readonly events: {};
    }>;
    /**
     * Supported features as a flag object.
     */
    get features(): {};
    /**
     * Every cluster behavior has an associated ClusterType defined statically.
     */
    static readonly cluster: ClusterType.Of<{
        readonly id: 0;
        readonly revision: 0;
        readonly name: "Unknown";
        readonly attributes: {};
        readonly commands: {};
        readonly events: {};
    }>;
    /**
     * Method definitions.
     */
    static readonly Interface: {
        components: never[];
    };
    /**
     * All ClusterBehavior initialization currently runs as part of {@link Endpoint} initialization.
     */
    static readonly early = true;
    /**
     * Keep networking alive until I'm destroyed.
     */
    static readonly dependencies: (typeof NetworkBehavior)[];
    constructor(agent: Agent, backing: BehaviorBacking);
    /**
     * Create a new behavior for a specific {@link ClusterType}.
     *
     * If you invoke directly on {@link ClusterBehavior} you will receive a new implementation that reports all commands
     * as unimplemented.
     *
     * If you invoke on an existing subclass, you will receive a new implementation with the cluster in the subclass
     * replaced.  You should generally only do this with a {@link ClusterType} with the same ID.
     */
    static for<This extends ClusterBehavior.Type, const ClusterT extends ClusterType>(this: This, cluster: ClusterT, schema?: Schema): ClusterBehavior.Type<ClusterT, This>;
    /**
     * Create a new behavior with different cluster features.
     */
    static with<This extends ClusterBehavior.Type, const FeaturesT extends ClusterComposer.FeatureSelection<This["cluster"]>>(this: This, ...features: FeaturesT): ClusterBehavior.Type<ClusterComposer.WithFeatures<This["cluster"], FeaturesT>, This, ClusterInterface.InterfaceOf<This>>;
    /**
     * Create a new behavior with modified cluster elements.
     */
    static alter<This extends ClusterBehavior.Type, const AlterationsT extends ElementModifier.Alterations<This["cluster"]>>(this: This, alterations: AlterationsT): ClusterBehavior.Type<ElementModifier.WithAlterations<ClusterType, AlterationsT>, This, ClusterInterface.InterfaceOf<This>>;
    /**
     * Create a new behavior with additional cluster features marked "mandatory".
     *
     * This informs matter.js that an application supports these elements.
     */
    static enable<This extends ClusterBehavior.Type, const FlagsT extends ElementModifier.ElementFlags<This["cluster"]>>(this: This, flags: FlagsT): ClusterBehavior.Type<ElementModifier.WithAlterations<ClusterType, ElementModifier.ElementFlagAlterations<FlagsT>>, This, ClusterInterface.InterfaceOf<This>>;
    /**
     * Create a ClusterBehavior like this one with different interface methods.
     *
     * The Interface "property" is type-only.  We define a method however to keep the API consistent.  At runtime the
     * method is a no-op.
     */
    static withInterface<const I extends ClusterInterface>(): ClusterBehavior.Type<typeof ClusterType.Unknown, typeof ClusterBehavior, I>;
    static supports(other: Behavior.Type): boolean;
    requireAttributeEnabled<This extends Behavior, K extends keyof This["state"]>(this: This, attributeName: K): Exclude<This["state"][K], undefined>;
    assertAttributeEnabled<This extends Behavior, K extends keyof This["state"]>(this: This, attributeName: K): void;
}
export declare namespace ClusterBehavior {
    /**
     * A ClusterBehavior specialized for a specific Cluster.
     */
    interface Type<C extends ClusterType = ClusterType, B extends Behavior.Type = Behavior.Type, I extends ClusterInterface = ClusterInterface.InterfaceOf<B>> {
        new (agent: Agent, backing: BehaviorBacking): Instance<C, B, I>;
        readonly name: string;
        /**
         * The behavior ID for ClusterBehaviors is the name of the cluster.
         */
        readonly id: Uncapitalize<C["name"]>;
        /**
         * Base cluster state include all attribute values but may be extended by subclasses.
         */
        readonly cluster: C;
        readonly Events: ClusterEvents.Type<C, B>;
        readonly State: new () => ClusterState.Type<C, B>;
        readonly Internal: B["Internal"];
        readonly Interface: I;
        readonly schema?: Schema;
        readonly early: boolean;
        readonly defaults: ClusterState.Type<C, B>;
        readonly supervisor: RootSupervisor;
        readonly dependencies?: Iterable<Behavior.Type>;
        supports: typeof ClusterBehavior.supports;
        readonly ExtensionInterface: ExtensionInterfaceOf<B>;
        for<This extends ClusterBehavior.Type, const ClusterT extends ClusterType>(this: This, cluster: ClusterT, schema?: Schema): ClusterBehavior.Type<ClusterT, This>;
        with<This extends ClusterBehavior.Type, const FeaturesT extends ClusterComposer.FeatureSelection<This["cluster"]>>(this: This, ...features: FeaturesT): ClusterBehavior.Type<ClusterComposer.WithFeatures<This["cluster"], FeaturesT>, This>;
        alter<This extends ClusterBehavior.Type, const AlterationsT extends ElementModifier.Alterations<This["cluster"]>>(this: This, alterations: AlterationsT): ClusterBehavior.Type<ElementModifier.WithAlterations<This["cluster"], AlterationsT>, This>;
        set<This extends Behavior.Type>(this: This, defaults: Behavior.InputStateOf<This>): This;
        enable<This extends ClusterBehavior.Type, const FlagsT extends ElementModifier.ElementFlags<This["cluster"]>>(this: This, flags: FlagsT): ClusterBehavior.Type<ElementModifier.WithAlterations<This["cluster"], ElementModifier.ElementFlagAlterations<FlagsT>>, This>;
    }
    /**
     * A fully-typed ClusterBehavior.  This type is derived by combining properties of the base type with properties
     * contributed by the cluster.
     */
    type Instance<C extends ClusterType, B extends Behavior.Type, I extends ClusterInterface> = ClusterBehavior & Omit<InstanceType<B>, "cluster" | "state" | "events" | "initialize" | typeof Symbol.asyncDispose | keyof ClusterInterface.MethodsOf<ClusterInterface.InterfaceOf<B>, ClusterOf<B>> | keyof ExtensionInterfaceOf<B>> & ClusterInterface.MethodsOf<I, C> & ExtensionInterfaceOf<B> & {
        /**
         * The implemented cluster.
         */
        cluster: C;
        /**
         * State values for the behavior.
         */
        state: ClusterState<C, B>;
        /**
         * Observables for cluster events and attribute changes.
         */
        events: ClusterEvents<C, B>;
        /**
         * Supported features as a flag object.
         */
        features: TypeFromBitSchema<C["features"]>;
        [Symbol.asyncDispose](): MaybePromise<void>;
    };
    /**
     * All cluster behaviors support interaction events in addition to cluster-specific attribute mutation events.
     */
    class Events extends EventEmitter {
        /**
         * Emitted when state associated with this behavior is first mutated by a specific interaction.
         */
        interactionBegin: Observable<[], void>;
        /**
         * Emitted when a mutating interaction completes.
         */
        interactionEnd: AsyncObservable<[], void>;
    }
    /**
     * This is an unfortunate kludge required to work around https://github.com/microsoft/TypeScript/issues/27965.  It
     * allows you to designate extension methods available on behavior instances.
     *
     * Methods designated in this way make it so you can override methods using the syntax:
     *
     *     override foo() {}
     *
     * rather than:
     *
     *     override foo: () => {}
     *
     * See {@link ClusterInterface} for more details.
     */
    const ExtensionInterface: {};
}
//# sourceMappingURL=ClusterBehavior.d.ts.map