/**
 * @license
 * Copyright 2022-2025 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Agent } from "#endpoint/Agent.js";
import { Endpoint } from "#endpoint/Endpoint.js";
import { Duration, MaybePromise, Timestamp } from "#general";
import { Behavior } from "./Behavior.js";
import { ClusterEvents } from "./cluster/ClusterEvents.js";
import { BehaviorBacking } from "./internal/BehaviorBacking.js";
/**
 * Attribute transition management.
 *
 * This utility supports updates of one or more attributes of a single behavior when the change occurs gradually over
 * time.
 *
 * The nuances of integrating Matter transition semantics with a device can be complicated.  Matter specifies the
 * frequency of updates for levels and "remaining time" attributes.  These semantics may not map well to your device.
 *
 * This class attempts to offer implementors significant flexibility.  To that end, we offer several integration
 * approaches:
 *
 * 1. If you instantiate with {@link Transitions.Configuration.manageTransitions} as false, no transition occurs and
 *    device state updates instantly.
 *
 * 2. If you enable transition management but provide no other options, matter.js will perform transitions for you,
 *    updating values using a timer.  You probably do not want to use this option if your device supports transitions
 *    natively.
 *
 * 3. If you implement transitions in hardware or a bridged device, you can still use matter.js to track ongoing
 *    transitions and report remaining time.  To do this, extend this class and implement {@link transitionImmediately}
 *    and {@link transitionGradually}.  matter.js will report changes as you update local state and report transition
 *    completion when all attributes reach their target value or when you invoke {@link finish}.
 *
 * 4. You can also allow matter.js to operate a transition timer but apply value updates directly to hardware by
 *    overriding {@link applyUpdates} (and use `determineUpdates()` if needed) or {@link step}.  This is useful if your
 *    device does not support transitions natively, but you want to ensure that matter.js does not report values that
 *    do not reflect hardware state.
 *
 * Whichever approach you take, matter.js attempts to implement the Matter protocol as accurately as possible with the
 * information available.
 */
export declare class Transitions<B extends Behavior> {
    #private;
    constructor(endpoint: Endpoint, config: Transitions.Configuration<B>);
    /**
     * Iterate over all active transitions.
     */
    [Symbol.iterator](): ArrayIterator<Transitions.PropertyState<B>>;
    /**
     * Get iteration state for a specific property.
     */
    stateOf(name: Transitions.PropertyOf<B>): Transitions.PropertyState<B> | undefined;
    /**
     * Calculate the distance between two values in a cyclic range. This is the default implementation only caring
     * about normal upwards and downwards transitions.
     */
    protected calculateCyclicDistance(currentValue: number, targetValue: number, changePerS: number, min: number, max: number): number;
    /**
     * Initiate transition of an attribute.
     */
    start(transition: Transitions.Transition<B>): MaybePromise;
    /**
     * Immediately change to a target value.
     *
     * The default implementation updates the local state value and calls `applyUpdates()`.
     */
    protected transitionImmediately(owner: B, name: Transitions.PropertyOf<B>, targetValue: number): MaybePromise;
    /**
     * Initiate gradual transition to a target value.
     *
     * The default implementation starts a timer to drive transitions over time.
     */
    protected transitionGradually(_attr: Transitions.PropertyState<B>): void;
    /**
     * Stop transition of one or all attributes.
     */
    stop(name?: Transitions.PropertyOf<B>): void;
    /**
     * Stop a transition of one or more attributes that has completed successfully.
     */
    finish(name?: Transitions.PropertyOf<B>): void;
    /**
     * Free resources.
     */
    close(): Promise<void>;
    /**
     * Set the static version of remaining time used when transition management is disabled.
     */
    set remainingTime(value: number);
    /**
     * Determine time remaining in transition in (possibly fractional) seconds.
     *
     * This is computed dynamically based on the longest running individual attribute transition.
     */
    get remainingTime(): number;
    /**
     * Update transitioning attributes for a behavior.
     *
     * You may override this method if you want matter.js to run a timer, but you want to handle value updates yourself.
     */
    protected step(behavior: B): Promise<void>;
    /** Determine the changes to be applied to the behavior and return as key-value object. */
    protected determineUpdates(behavior: B): Partial<Transitions.StateOf<B>>;
    /**
     * This method is called to apply the changes to the behavior.
     * The default implementation detects the changed attributes using the method `determineChanges()`and updates the
     * state of the behavior.  It also returns them as an key-value object, which can be useful when just requiring the
     * changes values in an extended class.
     */
    protected applyUpdates(behavior: B, changes: Partial<Transitions.StateOf<B>>): MaybePromise<Partial<Transitions.StateOf<B>>>;
}
export declare namespace Transitions {
    const DEFAULT_STEP_INTERVAL: Duration;
    const DEFAULT_EXTERNAL_TIME_UNIT: Duration;
    /**
     * A valid transitionable attribute name for the specified type.
     */
    type AttrOf<T extends Behavior.Type> = keyof {
        [K in keyof InstanceType<T>["state"]]: T[K] extends number | undefined | null ? true : never;
    };
    /**
     * Transition configuration.
     *
     * The {@link Transitions} accesses this configuration on-demand so values that change after initial construction
     * will affect ongoing behavior.
     */
    interface Configuration<B extends Behavior> {
        /**
         * The behavior type this configuration applies to.
         */
        readonly type: Behavior.Type & {
            new (agent: Agent, backing: BehaviorBacking): B;
        };
        /**
         * If this is false we do not manage transitions and "remaining time" behaves like a normal static value.
         *
         * Default is true.
         */
        readonly manageTransitions?: boolean;
        /**
         * Interval per external time unit.  Defaults to 100ms which is appropriate for CC & LVL "remaining time"
         * attribute that is defined as 10ths of a second.
         */
        readonly externalTimeUnit?: Duration;
        /**
         * The internal tick rate for transitions.
         *
         * This is the smallest time increment between value adjustments.
         *
         * Defaults to {@link DEFAULT_STEP_INTERVAL}.
         */
        readonly stepInterval?: Duration;
        /**
         * The end time for a transition if transition management is disabled.
         */
        readonly transitionEndTimeMs?: number;
        /**
         * An observable associated with the "remaining time" value.
         *
         * If present, the {@link Transitions} forces an emit under conditions defined in spec for the "RemainingTime"
         * attribute of Level Control & Color Control clusters.
         *
         * This should also support Valve Configuration & Control cluster's "RemainingDuration" attribute with
         * additional options to support small variations in logic.
         */
        readonly remainingTimeEvent?: ClusterEvents.ChangedObservable;
        /**
         * The state properties that support transition.
         */
        readonly properties: Partial<Record<PropertyOf<B>, PropertyConfiguration>>;
    }
    /**
     * Configures a state property to support transitions.  This is typically an attribute but we support transition of
     * any numeric property.
     */
    interface PropertyConfiguration {
        /**
         * A lower bound on the transition value.
         */
        readonly min?: number | undefined;
        /**
         * An upper bound on the transition value.
         */
        readonly max?: number | undefined;
        /**
         * Is the property transitioning ina cyclic manner? means it overflows to the min value when it reaches the max
         */
        cyclic?: boolean;
    }
    type StateOf<B extends Behavior> = {
        [N in string & keyof B["state"]]: B[N] extends number | null | undefined ? true : never;
    };
    type PropertyOf<B extends Behavior> = keyof StateOf<B>;
    /**
     * Configuration for transition of a specific attribute.
     */
    interface Transition<B extends Behavior> {
        /**
         * The attribute to transition.
         */
        readonly name: PropertyOf<B>;
        /**
         * The behavior instance requesting transition.
         */
        readonly owner: B;
        /**
         * The amount to change the attribute per second.
         */
        readonly changePerS?: number | null;
        /**
         * The target value for the transition.
         *
         * If the property is not transitioning "cyclic" the following rules apply:
         *
         * * If undefined, transitions to the min/max value.
         *
         * * If no min or max is defined and no target value is supplied the transition will not run.
         *
         * If the property is transitioning "cyclic" the following rules apply:
         *
         * * If undefined, the transition will be endless and needs to be stopped manually.
         *
         * * If a target value is defined, the transition logic calculates the distance to the target value and stops
         *   on the target value once this distance was processed. By default, the distance is calculated linearly, but
         *   this behavior can be overridden with the custom function below.
         */
        readonly targetValue?: number;
        /**
         * A function to calculate the distance between the current value and the target value.
         */
        calculateCyclicDistance?: (currentValue: number, targetValue: number) => number;
        /**
         * Invoked every time the transitioning value changes before committing the mutating transaction.
         */
        onStep?: (this: B, value: number) => MaybePromise<void>;
    }
    /**
     * Internal state related to actively transitioning attributes.
     */
    interface PropertyState<B extends Behavior> {
        /**
         * The property name.
         */
        name: PropertyOf<B>;
        /**
         * Configuration for any active transition.
         */
        configuration: Transition<B>;
        /**
         * The current value for the transition.
         *
         * We track separately from canonical value because we transition using floats but values are typically
         * integers.  This allows us to avoid rounding errors.
         */
        currentValue: number;
        /**
         * The change in value per millisecond.
         */
        changePerMs: number;
        /**
         * The distance left in the transition for cyclic properties.
         */
        distanceLeft?: number;
        /**
         * The time of the last step.
         */
        prevStepAt: Timestamp;
        /**
         * Set to true when the reporting of remaining time should be suppressed when finishing the transition.
         * This usually is used for transitions that are faster than 1s.
         */
        suppressReportingRemainingTimeOnFinish?: boolean;
    }
}
//# sourceMappingURL=Transitions.d.ts.map