/**
 * A complete implementation of the UniFi Protect API, including access to the events, livestream data (not just RTSP), and websocket endpoints.
 *
 * The UniFi Protect API is largely undocumented and has been reverse engineered mostly through the Protect native web interface as well as trial and error. This
 * implementation provides a high-performance, event-driven interface into the Protect API, allowing you to access all of Protect's rich capabilities.
 *
 * @module ProtectApi
 */
import { type RequestOptions, type Response } from "@adobe/fetch";
import type { Nullable, ProtectCameraConfig, ProtectCameraConfigInterface, ProtectCameraConfigPayload, ProtectChimeConfig, ProtectChimeConfigPayload, ProtectLightConfig, ProtectLightConfigPayload, ProtectNvrBootstrap, ProtectNvrConfig, ProtectNvrConfigPayload, ProtectSensorConfig, ProtectSensorConfigPayload, ProtectViewerConfig, ProtectViewerConfigPayload } from "./protect-types.js";
import { EventEmitter } from "node:events";
import { ProtectLivestream } from "./protect-api-livestream.js";
import type { ProtectLogging } from "./protect-logging.js";
/**
 * Define our known Protect device types.
 */
export type ProtectKnownDeviceTypes = ProtectCameraConfig | ProtectChimeConfig | ProtectLightConfig | ProtectNvrConfig | ProtectSensorConfig | ProtectViewerConfig;
/**
 * Define our known Protect device payload types.
 */
export type ProtectKnownDevicePayloads = ProtectCameraConfigPayload | ProtectChimeConfigPayload | ProtectLightConfigPayload | ProtectNvrConfigPayload | ProtectSensorConfigPayload | ProtectViewerConfigPayload;
/**
 * Options to tailor the behavior of {@link ProtectApi.retrieve}.
 *
 * @property {boolean} [logErrors=true] - Log errors. Defaults to `true`.
 * @property {number} [timeout=3500] - Amount of time, in milliseconds, to wait for the Protect controller to respond before timing out. Defaults to `3500`.
 */
export interface RetrieveOptions {
    logErrors?: boolean;
    timeout?: number;
}
/**
 * This class provides an event-driven API to access the UniFi Protect API. Here's how to quickly get up and running with this library once you've instantiated the class:
 *
 * 1. {@link login | Login} to the UniFi Protect controller and acquire security credentials for further calls to the API.
 *
 * 2. Retrieve the current configuration and state of the Protect controller by calling the {@link bootstrap} endpoint. This contains everything you would want to know
 *    about this particular UniFi Protect controller, including enumerating all the devices it knows about.
 *
 * 3. Listen for `message` events emitted by {@link ProtectApi} containing all Protect controller events, in realtime. They are delivered as
 *    {@link ProtectApiEvents.ProtectEventPacket | ProtectEventPacket} packets, containing the event-specific details.
 *
 * Those are the basics that gets us up and running.
 */
export declare class ProtectApi extends EventEmitter {
    private _bootstrap;
    private _eventsWs;
    private apiErrorCount;
    private apiLastSuccess;
    private fetch;
    private headers;
    private _isAdminUser;
    private log;
    private nvrAddress;
    private password;
    private username;
    /**
     * Create an instance of the UniFi Protect API.
     *
     * @param log - Logging functions to use.
     *
     * @defaultValue `none` - Logging will be done to stdout and stderr.
     *
     * @category Constructor
     */
    constructor(log?: ProtectLogging);
    /**
     * Execute a login attempt to the UniFi Protect API.
     *
     * @param nvrAddress - Address of the UniFi Protect controller, expressed as an FQDN or IP address.
     * @param username   - Username to use when logging into the controller.
     * @param password   - Password to use when logging into the controller.
     *
     * @returns Returns a promise that will resolve to `true` if successful and `false` otherwise.
     *
     * @remarks A `login` event will be emitted each time this method is called, with the result of the attempt as an argument. If there are any existing logins from prior
     *          calls to login, they will be terminated.
     *
     * @example
     * Login to the Protect controller. You can selectively choose to either `await` the promise that is returned by `login`, or subscribe to the `login` event.
     *
     * ```ts
     * import { ProtectApi } from "unifi-protect";
     *
     * // Create a new Protect API instance.
     * const ufp = new ProtectApi();
     *
     * // Set a listener to wait for the login event to occur.
     * ufp.once("login", (successfulLogin: boolean) => {
     *
     *   // Indicate if we are successful.
     *   if(successfulLogin) {
     *
     *     console.log("Logged in successfully.");
     *     process.exit(0);
     *   }
     * });
     *
     * // Login to the Protect controller.
     * if(!(await ufp.login("protect-controller.local", "username", "password"))) {
     *
     *   console.log("Invalid login credentials.");
     *   process.exit(0);
     * };
     * ```
     *
     * @category Authentication
     */
    login(nvrAddress: string, username: string, password: string): Promise<boolean>;
    private loginController;
    private bootstrapController;
    private launchEventsWs;
    /**
     * Retrieve the bootstrap JSON from a UniFi Protect controller.
     *
     * @returns Returns a promise that will resolve to `true` if successful and `false` otherwise.
     *
     * @remarks A `bootstrap` event will be emitted each time this method is successfully called, with the {@link ProtectNvrBootstrap} JSON as an argument.
     *
     * @example
     * Retrieve the bootstrap JSON. You can selectively choose to either `await` the promise that is returned by `getBootstrap`, or subscribe to the `bootstrap` event.
     *
     * ```ts
     * import { ProtectApi, ProtectNvrBootstrap } from "unifi-protect";
     * import util from "node:util";
     *
     * // Create a new Protect API instance.
     * const ufp = new ProtectApi();
     *
     * // Set a listener to wait for the bootstrap event to occur.
     * ufp.once("bootstrap", (bootstrapJSON: ProtectNvrBootstrap) => {
     *
     *   // Once we've bootstrapped the Protect controller, output the bootstrap JSON and we're done.
     *   process.stdout.write(util.inspect(bootstrapJSON, { colors: true, depth: null, sorted: true }) + "\n", () => process.exit(0));
     * });
     *
     * // Login to the Protect controller.
     * if(!(await ufp.login("protect-controller.local", "username", "password"))) {
     *
     *   console.log("Invalid login credentials.");
     *   process.exit(0);
     * };
     *
     * // Bootstrap the controller. It will emit a message once it's received the bootstrap JSON, or you can alternatively wait for the promise to resolve.
     * if(!(await ufp.getBootstrap())) {
     *
     *   console.log("Unable to bootstrap the Protect controller.");
     *   process.exit(0);
     * }
     * ```
     *
     * Alternatively, you can access the bootstrap JSON directly through the {@link bootstrap} accessor:
     *
     * ```ts
     * import { ProtectApi } from "unifi-protect";
     * import util from "node:util";
     *
     * // Create a new Protect API instance.
     * const ufp = new ProtectApi();
     *
     * // Login to the Protect controller.
     * if(!(await ufp.login("protect-controller.local", "username", "password"))) {
     *
     *   console.log("Invalid login credentials.");
     *   process.exit(0);
     * };
     *
     * // Bootstrap the controller.
     * if(!(await ufp.getBootstrap())) {
     *
     *   console.log("Unable to bootstrap the Protect controller.");
     *   process.exit(0);
     * }
     *
     * // Once we've bootstrapped the Protect controller, access the bootstrap JSON through the bootstrap accessor and we're done.
     * process.stdout.write(util.inspect(ufp.bootstrap, { colors: true, depth: null, sorted: true }) + "\n", () => process.exit(0));
     * ```
     *
     * @category API Access
     */
    getBootstrap(): Promise<boolean>;
    private checkAdminUserStatus;
    /**
     * Retrieve a snapshot image from a Protect camera.
     *
     * @param device           - Protect device.
     * @param options          - Parameters to pass on for the snapshot request.
     *
     * @returns Returns a promise that will resolve to a Buffer containing the JPEG image snapshot if successful, and `null` otherwise.
     *
     * @remarks The `options` object for snapshot parameters accepts the following properties, all of which are optional:
     *
     * | Property          | Description                                                                                                |
     * |-------------------|------------------------------------------------------------------------------------------------------------|
     * | height            | The image height to request. Defaults selected by the Protect controller, based on the camera resolution.  |
     * | width             | The image width to request. Defaults selected by the Protect controller, based on the camera resolution.   |
     * | usePackageCamera  | Retriver a snapshot fron the package camera rather than the primary camera lens. Defaults to `false`.      |
     *
     * @category API Access
     */
    getSnapshot(device: ProtectCameraConfig, options?: Partial<{
        width: number;
        height: number;
        usePackageCamera: boolean;
    }>): Promise<Nullable<Buffer>>;
    /**
     * Update a Protect device's configuration on the UniFi Protect controller.
     *
     * @typeParam DeviceType - Generic for any known Protect device type.
     *
     * @param device  - Protect device.
     * @param payload - Device configuration payload to upload, usually a subset of the device-specific configuration JSON.
     *
     * @returns Returns a promise that will resolve to the updated device-specific configuration JSON if successful, and `null` otherwise.
     *
     * @remarks Use this method to change the configuration of a given Protect device or controller. It requires the credentials used to login to the Protect API
     *   to have administrative privileges for most settings.
     *
     * @category API Access
     */
    updateDevice<DeviceType extends ProtectKnownDeviceTypes>(device: DeviceType, payload: ProtectKnownDevicePayloads): Promise<Nullable<DeviceType>>;
    private updateCameraChannels;
    /**
     * Utility method that enables all RTSP channels on a given Protect camera.
     *
     * @param device - Protect camera to modify.
     *
     * @returns Returns a promise that will resolve to the updated {@link ProtectCameraConfig} if successful, and `null` otherwise.
     *
     * @category Utilities
     */
    enableRtsp(device: ProtectCameraConfigInterface): Promise<Nullable<ProtectCameraConfig>>;
    /**
     * Utility method that generates a nicely formatted device information string.
     *
     * @param device     - Protect device.
     * @param name       - Optional name for the device. Defaults to the device type (e.g. `G4 Pro`).
     * @param deviceInfo - Optionally specify whether or not to include the IP address and MAC address in the returned string. Defaults to `false`.
     *
     * @returns Returns the Protect device name in the following format: <code>*Protect device name* [*Protect device type*] (address: *IP address*
     *          mac: *MAC address*)</code>.
     *
     * @remarks The example above assumed the `deviceInfo` parameter is set to `true`.
     *
     * @category Utilities
     */
    getDeviceName(device: ProtectKnownDeviceTypes, name?: string, deviceInfo?: boolean): string;
    /**
     * Utility method that generates a combined, nicely formatted device and NVR string.
     *
     * @param device - Protect device.
     *
     * @returns Returns the Protect device name in the following format:
     *   <code>*Protect controller name* [*Protect controller type*] *Protect device name* [*Protect device type*]</code>.
     *
     * @category Utilities
     */
    getFullName(device: ProtectKnownDeviceTypes): string;
    /**
     * Terminate any open connection to the UniFi Protect API.
     *
     * @category Utilities
     */
    reset(): void;
    /**
     * Clear the login credentials and terminate any open connection to the UniFi Protect API.
     *
     * @category Authentication
     */
    logout(): void;
    private canModifyCamera;
    /**
     * Return a websocket API endpoint for the requested endpoint type.
     *
     * @param endpoint - Requested endpoint type. Valid types are `livestream` and `talkback`.
     * @param params   - Parameters to pass on for the endpoint request.
     *
     * @returns Returns a promise that will resolve to a URL to the requested endpoint if successful, and `null` otherwise.
     *
     * @remarks Valid API endpoints are `livestream` and `talkback`.
     *
     * - The `livestream` endpoint will return a URL to a websocket that provides an encoded livestream from a given camera. **Do not access this endpoint directly, use
     *   {@link createLivestream} instead.** Accessing the livestream endpoint directly is not directly useful without additional manipulation, which, unless you have
     *   a need for, you should avoid dealing with and use the {@link ProtectLivestream} API instead that provides you direct access to the livestream as an H.264 fMP4.
     * - The `talkback` endpoint creates a talkback connection to a Protect camera that contains a speaker (e.g. Protect doorbells).
     *   The returned websocket accepts an AAC-encoded ADTS stream. The only valid parameter is `camera`, containing the ID of the Protect camera you want to connect to.
     *
     * @category API Access
     */
    getWsEndpoint(endpoint: "livestream" | "talkback", params?: URLSearchParams): Promise<Nullable<string>>;
    private _getWsEndpoint;
    /**
     * Execute an HTTP fetch request to the Protect controller.
     *
     * @param url             - URL to execute **without** any additional parameters you want to pass (e.g. https://unvr.local/proxy/protect/cameras/someid/snapshot).
     * @param options         - Parameters to pass on for the endpoint request.
     * @param retrieveOptions - Options that modify whether errors are logged and timeout intervals to wait for a response from the Protect controller.
     *
     * @returns Returns a promise that will resolve to a Response object successful, and `null` otherwise.
     *
     * @remarks This method should be used when direct access to the Protect controller is needed, or when this library doesn't have a needed method to access
     *   controller capabilities. `options` must be a
     *   [Fetch API compatible](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request#options) request options object.
     *
     * @category API Access
     */
    retrieve(url: string, options?: RequestOptions, retrieveOptions?: RetrieveOptions): Promise<Nullable<Response>>;
    private _retrieve;
    private logRetry;
    /**
     * Return a new instance of the Protect livestream API.
     *
     * @returns Returns a new livestream API object.
     *
     * @remarks This method should be used to create a new livestream API object. It allows you to create access livestreams of individual cameras and interact
     *   directly with the H.264 fMP4 streams for a given camera.
     *
     * @category API Access
     */
    createLivestream(): ProtectLivestream;
    /**
     * Return an API endpoint for the requested endpoint type.
     *
     * @param endpoint - Requested endpoint type.
     *
     * @returns Returns a URL to the requested endpoint if successful, and an empty string otherwise.
     *
     * @remarks Valid API endpoints are `bootstrap`, `camera`, `chime`, `light`, `login`, `nvr`, `self`, `sensor`, `websocket` and `viewer`.
     *
     * @category API Access
     */
    getApiEndpoint(endpoint: string): string;
    /**
     * Access the Protect controller bootstrap JSON.
     *
     * @returns Returns the bootstrap JSON if the Protect controller has been bootstrapped, `null` otherwise.
     *
     * @remarks A call to {@link getBootstrap} is required before calling this getter. Otherwise, it will return `null`. Put another way, you need to execute a bootstrap
     * request to the Protect controller before accessing the bootstrap JSON.
     *
     * @category API Access
     */
    get bootstrap(): Nullable<ProtectNvrBootstrap>;
    /**
     * Utility method that returns whether the credentials that were used to login to the Protect controller have administrative privileges or not.
     *
     * @returns Returns `true` if the logged in user has administrative privileges, `false` otherwise.
     *
     * @category Utilities
     */
    get isAdminUser(): boolean;
    /**
     * Utility method that returns whether our connection to the Protect controller is currently throttled or not.
     *
     * @returns Returns `true` if the API has returned too many errors and is now throttled for a period of time, `false` otherwise.
     *
     * @category Utilities
     */
    get isThrottled(): boolean;
    /**
     * Utility method that returns a nicely formatted version of the Protect controller name.
     *
     * @returns Returns the Protect controller name in the following format:
     *   <code>*Protect controller name* [*Protect controller type*]</code>.
     *
     * @category Utilities
     */
    get name(): string;
}
