import type { ProviderRegistration, ConfigUISchema, SavedDevice, IDevice } from '../index.js';
import { BaseAddon } from '../addon/base-addon.js';
import { DeviceType } from './device-type.js';
import type { CreateDeviceSpec } from './device-management.js';
import type { DeviceConstructor } from './device-context.js';
export interface DiscoveryCandidate {
    readonly stableId: string;
    readonly type: DeviceType;
    readonly suggestedName: string;
    readonly prefilledConfig: Record<string, unknown>;
}
export interface DeviceSummary {
    readonly id: number;
    readonly stableId: string;
    readonly addonId: string;
    readonly type: string;
    readonly name: string;
    readonly parentDeviceId: number | null;
    readonly online: boolean;
    readonly features: readonly string[];
    readonly config: Record<string, unknown>;
}
export interface ProviderStatus {
    readonly connected: boolean;
    readonly deviceCount: number;
    readonly error?: string;
}
export interface FieldProbeResult {
    readonly status: 'ok' | 'error';
    readonly labels?: readonly string[];
    readonly error?: string;
    /**
     * Optional values the provider suggests applying to other form fields
     * after a successful probe. The form-builder merges these into the
     * working snapshot ONLY for fields the operator hasn't filled yet,
     * never overwriting user input. Typical use: a host-probe that
     * autodetects the camera model and proposes it as the device `name`.
     */
    readonly suggestedValues?: Readonly<Record<string, unknown>>;
}
/**
 * Convert an IDevice to the flat DeviceSummary shape expected by the
 * device-provider cap router. Shared across all providers.
 */
export declare function toDeviceSummary(device: IDevice, addonId: string): DeviceSummary;
/**
 * Base class for device-provider addons (rtsp, onvif, frigate).
 *
 * Provides default implementations for the common device-provider cap
 * methods (`start`, `stop`, `getStatus`, `getDevices`, `supportsDiscovery`,
 * `supportsManualCreation`, `toDeviceSummary`). Subclasses override the
 * methods that differ per provider.
 *
 * @example
 * ```ts
 * class RtspProvider extends BaseDeviceProvider {
 *   protected readonly addonId = 'provider-rtsp'
 *   protected readonly providerName = 'RTSP'
 *
 *   protected async onCreateDevice(input) { ... }
 *   protected async onGetCreationSchema(type) { ... }
 *   protected async onRestoreDevices(saved) { ... }
 * }
 * ```
 */
export declare abstract class BaseDeviceProvider<TConfig extends object = Record<string, unknown>> extends BaseAddon<TConfig> {
    /** Addon ID used in DeviceSummary. Must match package.json id. */
    protected abstract readonly addonId: string;
    /** Human-readable provider name for log messages. */
    protected abstract readonly providerName: string;
    protected onInitialize(): Promise<ProviderRegistration[]>;
    protected onShutdown(): Promise<void>;
    start(): Promise<void>;
    stop(): Promise<void>;
    getStatus(): Promise<ProviderStatus>;
    getDevices(): Promise<ReadonlyArray<{
        id: string;
        name: string;
        type: string;
    }>>;
    supportsDiscovery(): Promise<boolean>;
    discoverDevices(): Promise<readonly DiscoveryCandidate[]>;
    adoptDiscoveredDevice(_input: {
        candidate: DiscoveryCandidate;
    }): Promise<DeviceSummary>;
    supportsManualCreation(): Promise<boolean>;
    getChildCreationSchema(input: {
        type: DeviceType;
    }): Promise<ConfigUISchema | null>;
    /**
     * Default kernel-orchestrated `createDevice` implementation. The
     * subclass's `onCreateDevice` returns a declarative
     * `CreateDeviceSpec` (`{meta, config}`) — this method handles
     * stableId generation, class lookup, kernel.devices.create
     * dispatch, and DeviceSummary mapping. Subclasses should NOT
     * override this method; override `onCreateDevice` and
     * `deviceClasses` instead.
     */
    createDevice(input: {
        type: DeviceType;
        config: Record<string, unknown>;
    }): Promise<DeviceSummary>;
    /**
     * Generate a stableId for a newly-created device. Default uses the
     * `${addonId}-${Date.now()}` pattern as a unique-but-opaque
     * fallback; any provider that has access to durable hardware
     * identity (UID, MAC, serial) should override and derive from it
     * so re-adding the same physical device reuses its persisted row.
     *
     * `config` is the parsed CreateDeviceSpec.config the subclass
     * returned from `onCreateDevice` — the override has access to
     * every operator-supplied + autodetect-resolved field. Optional
     * for back-compat: existing overrides that take only `type`
     * keep working unchanged.
     */
    protected generateStableId(_type: DeviceType, _config?: Record<string, unknown>): string;
    testCreationField(_input: {
        type: DeviceType;
        key: string;
        value: unknown;
        formValues?: Record<string, unknown>;
    }): Promise<FieldProbeResult>;
    restoreDevices(savedDevices: readonly SavedDevice[]): Promise<void>;
    /**
     * Concrete device classes this provider can spawn, keyed by
     * `DeviceType`. Used by:
     *   - `createDevice` to look up the class for the type the operator
     *     selected in the Add-Device modal
     *   - the default `onRestoreDevices` to instantiate persisted rows
     *     based on their `type` field
     *
     * Required for the declarative create + restore flow. Providers
     * that need custom-arg constructors (accessory child devices) wire
     * those up via `BaseDevice.getAccessoryChildren()` instead — the
     * top-level type → class map only handles parent devices.
     */
    protected abstract readonly deviceClasses: Partial<Record<DeviceType, DeviceConstructor<IDevice>>>;
    /** Return the creation form schema for a given device type, or null if unsupported. */
    protected abstract onGetCreationSchema(type: DeviceType): Promise<ConfigUISchema | null>;
    /**
     * Build the create spec from operator-supplied form values. Returns
     * `{meta, config}` — kernel handles allocateId, persist, instantiate,
     * register, and accessory auto-spawn. Provider's only job is to:
     *   - validate / probe the input
     *   - emit the meta (`type`, `name`, optional `location`)
     *   - emit the `config` blob the device class will self-hydrate
     */
    protected abstract onCreateDevice(type: DeviceType, config: Record<string, unknown>): Promise<CreateDeviceSpec>;
    /**
     * Restore devices from persisted state. Two-pass:
     *
     * 1. **Top-level pass** — invokes `kernel.devices.create()` for every
     *    `parentDeviceId === null` row using the `deviceClasses` map.
     *    The kernel's register flow handles `getAccessoryChildren()` for
     *    each parent (siren / floodlight / PIR / etc).
     *
     * 2. **Hub-adopted children pass** — for rows with
     *    `parentDeviceId !== null` whose `type` IS in `deviceClasses`
     *    (e.g. Reolink hub-adopted cameras under an NVR), spawn them
     *    explicitly with the persisted `parentDeviceId`. These are
     *    NOT accessory children — they're first-class adopted devices
     *    that just happen to have a parent. Without this pass, every
     *    server restart would lose hub-adopted cameras (their type is
     *    in `deviceClasses` but parent's `getAccessoryChildren` doesn't
     *    spawn them — that callback is only for purpose-built
     *    accessory roles).
     *
     * Rows whose `type` is NOT in `deviceClasses` are skipped — those
     * are accessory children (siren/light/sensor) that the kernel's
     * accessory-spawn flow handles via the parent's
     * `getAccessoryChildren()`. Override only when the default doesn't
     * fit.
     */
    protected onRestoreDevices(savedDevices: readonly SavedDevice[]): Promise<void>;
    /** Convert an IDevice to the flat DeviceSummary for the cap router. */
    protected toSummary(device: IDevice): DeviceSummary;
}
//# sourceMappingURL=base-device-provider.d.ts.map