/**
 * A utility type that recursively makes all properties of an object, including nested objects, optional.
 *
 * This should only be used on JSON objects. If used on classes, class methods will also be marked as optional.
 *
 * @remarks Credit for this type goes to: https://github.com/joonhocho/tsdef.
 *
 * @typeParam T - The type to make recursively partial.
 *
 * @example
 *
 * ```ts
 * type Original = {
 *
 *   id: string;
 *   nested: { value: number };
 * };
 *
 * // All properties, including nested ones, are optional.
 * type PartialObj = DeepPartial<Original>;
 *
 * const obj: PartialObj = { nested: {} };
 * ```
 *
 * @category Utilities
 */
export type DeepPartial<T> = {
    [P in keyof T]?: T[P] extends (infer I)[] ? DeepPartial<I>[] : DeepPartial<T[P]>;
};
/**
 * A utility type that recursively makes all properties of an object, including nested objects, readonly.
 *
 * This should only be used on JSON objects. If used on classes, class methods will also be marked as readonly.
 *
 * @remarks Credit for this type goes to: https://github.com/joonhocho/tsdef.
 *
 * @typeParam T - The type to make recursively readonly.
 *
 * @example
 *
 * ```ts
 * type Original = {
 *   id: string;
 *   nested: { value: number };
 * };
 *
 * // All properties, including nested ones, are readonly.
 * type ReadonlyObj = DeepReadonly<Original>;
 *
 * const obj: ReadonlyObj = { id: "a", nested: { value: 1 } };
 * // obj.id = "b"; // Error: cannot assign to readonly property.
 * ```
 *
 * @category Utilities
 */
export type DeepReadonly<T> = {
    readonly [P in keyof T]: T[P] extends (infer I)[] ? DeepReadonly<I>[] : DeepReadonly<T[P]>;
};
/**
 * Utility type that allows a value to be either the given type or `null`.
 *
 * This type is used to explicitly indicate that a variable, property, or return value may be either a specific type or `null`.
 *
 * @typeParam T - The type to make nullable.
 *
 * @example
 *
 * ```ts
 * let id: Nullable<string> = null;
 *
 * // Later...
 * id = "device-001";
 * ```
 *
 * @category Utilities
 */
export type Nullable<T> = T | null;
/**
 * Makes all properties in `T` optional except for those specified by `K`, which remain required.
 *
 * @typeParam T - The base interface or type.
 * @typeParam K - The keys of `T` that should remain required.
 *
 * @example
 *
 * ```ts
 * interface Device {
 *
 *   id: string;
 *   name: string;
 *   mac: string;
 * }
 *
 * type DeviceUpdate = PartialWithId<Device, "id">;
 *
 * // Valid: Only 'id' is required, others are optional.
 * const update: DeviceUpdate = { id: "123" };
 *
 * // Valid: Extra properties can be provided.
 * const another: DeviceUpdate = { id: "456", name: "SomeDevice" };
 *
 * // Error: 'id' is missing.
 * const invalid: DeviceUpdate = { name: "SomeOtherDevice" }; // TypeScript error
 * ```
 *
 * @category Utilities
 */
export type PartialWithId<T, K extends keyof T> = Partial<T> & Pick<T, K>;
/**
 * Logging interface for Homebridge plugins.
 *
 * This interface defines the standard logging methods (`debug`, `info`, `warn`, `error`) that plugins should use to output log messages at different severity levels. It
 * is intended to be compatible with Homebridge's builtin logger and can be implemented by any custom logger used within Homebridge plugins.
 *
 * @example
 *
 * ```ts
 * function example(log: HomebridgePluginLogging) {
 *
 *   log.debug("Debug message: %s", "details");
 *   log.info("Informational message.");
 *   log.warn("Warning message!");
 *   log.error("Error message: %s", "problem");
 * }
 * ```
 *
 * @category Utilities
 */
export interface HomebridgePluginLogging {
    /**
     * Logs a debug-level message.
     *
     * @param message    - The message string, with optional format specifiers.
     * @param parameters - Optional parameters for message formatting.
     */
    debug: (message: string, ...parameters: unknown[]) => void;
    /**
     * Logs an error-level message.
     *
     * @param message    - The message string, with optional format specifiers.
     * @param parameters - Optional parameters for message formatting.
     */
    error: (message: string, ...parameters: unknown[]) => void;
    /**
     * Logs an info-level message.
     *
     * @param message    - The message string, with optional format specifiers.
     * @param parameters - Optional parameters for message formatting.
     */
    info: (message: string, ...parameters: unknown[]) => void;
    /**
     * Logs a warning-level message.
     *
     * @param message    - The message string, with optional format specifiers.
     * @param parameters - Optional parameters for message formatting.
     */
    warn: (message: string, ...parameters: unknown[]) => void;
}
/**
 * A utility method that formats a bitrate value into a human-readable form as kbps or Mbps.
 *
 * @param value           - The bitrate value to convert.
 *
 * @returns Returns the value as a human-readable string.
 * @example
 *
 * ```ts
 * formatBps(500);        // "500 bps".
 * formatBps(2000);       // "2.0 kbps".
 * formatBps(15000);      // "15.0 kbps".
 * formatBps(1000000);    // "1.0 Mbps".
 * formatBps(2560000);    // "2.6 Mbps".
 * ```
 */
export declare function formatBps(value: number): string;
/**
 * A utility method that retries an operation at a specific interval for up to an absolute total number of retries.
 *
 * @param operation       - The operation callback to try until successful.
 * @param retryInterval   - Interval to retry, in milliseconds.
 * @param totalRetries    - Optionally, specify the total number of retries.
 *
 * @returns Returns `true` when the operation is successful, `false` otherwise or if the total number of retries has been exceeded.
 *
 * @remarks `operation` must be an asynchronous function that returns `true` when successful, and `false` otherwise.
 *
 * @example
 * ```ts
 * // Example: Retry an async operation up to 5 times, waiting 1 second between each try.
 * let attempt = 0;
 * const result = await retry(async () => {
 *
 *   attempt++;
 *
 *   // Simulate a 50% chance of success
 *   return Math.random() > 0.5 || attempt === 5;
 * }, 1000, 5);
 *
 * console.log(result); // true if operation succeeded within 5 tries, otherwise false.
 * ```
 *
 * @category Utilities
 */
export declare function retry(operation: () => Promise<boolean>, retryInterval: number, totalRetries?: number): Promise<boolean>;
/**
 * Run a promise with a guaranteed timeout to complete.
 *
 * @typeParam T           - The type of value the promise resolves with.
 * @param promise         - The promise you want to run.
 * @param timeout         - The amount of time, in milliseconds, to wait for the promise to resolve.
 *
 * @returns Returns the result of resolving the promise it's been passed if it completes before timeout, or null if the timeout expires. The internal timer is cleaned
 * up regardless of which outcome wins the race. Note that the underlying promise is not cancelled...it continues to run, but its result is ignored.
 *
 * @example
 * ```ts
 * // Resolves in 100ms, timeout is 500ms, so it resolves to 42.
 * const result = await runWithTimeout(Promise.resolve(42), 500);
 * console.log(result); // 42
 *
 * // Resolves in 1000ms, timeout is 500ms, so it resolves to null.
 * const slowPromise = new Promise<number>(resolve => setTimeout(() => resolve(42), 1000));
 * const result2 = await runWithTimeout(slowPromise, 500);
 * console.log(result2); // null
 * ```
 *
 * @category Utilities
 */
export declare function runWithTimeout<T>(promise: Promise<T>, timeout: number): Promise<Nullable<T>>;
/**
 * Emulate a sleep function.
 *
 * @param sleepTimer      - The amount of time to sleep, in milliseconds.
 *
 * @returns Returns a promise that resolves after the specified time elapses.
 *
 * @example
 * To sleep for 3 seconds before continuing execute:
 *
 * ```ts
 * await sleep(3000)
 * ```
 *
 * @category Utilities
 */
export declare function sleep(sleepTimer: number): Promise<void>;
/**
 * Start case a string, capitalizing the first letter of each word unconditionally.
 *
 * @param input - The string to start case.
 *
 * @returns Returns the start cased string.
 *
 * @example
 *
 * ```ts
 * toStartCase("this is a test");
 * ```
 *
 * Returns: `This Is A Test`.
 *
 * @category Utilities
 */
export declare function toStartCase(input: string): string;
/**
 * Sanitize an accessory name according to HomeKit naming conventions.
 *
 * @param name - The name to validate.
 *
 * @returns Returns the HomeKit-sanitized version of the name, replacing invalid characters with a space and squashing multiple spaces.
 *
 * @remarks This sanitizes names using [HomeKit's naming rulesets](https://developer.apple.com/design/human-interface-guidelines/homekit#Help-people-choose-useful-names)
 * and HAP specification documentation:
 *
 * - Starts and ends with a letter or number. Exception: may end with a period.
 * - May have the following special characters: -"',.#&.
 * - Must not include emojis.
 *
 * @example
 * ```ts
 * sanitizeName("Test|Switch")
 * ```
 *
 * Returns: `Test Switch`, replacing the pipe (an invalid character in HomeKit's naming ruleset) with a space.
 *
 * @category Utilities
 */
export declare function sanitizeName(name: string): string;
/**
 * Validate an accessory name according to HomeKit naming conventions.
 *
 * @param name - The name to validate.
 *
 * @returns Returns `true` if the name passes HomeKit's naming rules, `false` otherwise.
 *
 * @remarks This validates names using [HomeKit's naming rulesets](https://developer.apple.com/design/human-interface-guidelines/homekit#Help-people-choose-useful-names)
 * and HAP specification documentation:
 *
 * - Starts and ends with a letter or number. Exception: may end with a period.
 * - May not have multiple spaces adjacent to each other, nor begin nor end with a space.
 * - May have the following special characters: -"',.#&.
 * - Must not include emojis.
 *
 * @example
 * ```ts
 * validateName("Test|Switch")
 * ```
 *
 * Returns: `false`.
 *
 * @category Utilities
 */
export declare function validateName(name: string): boolean;
