/**
 * Matter Port Allocator
 *
 * Handles allocation of Matter protocol ports for the main bridge and external accessories.
 */
import { Logger } from '../logger.js';
const log = Logger.withPrefix('Matter/PortAllocator');
/**
 * Allocates Matter ports from the user-defined `config.matterPorts` option.
 * Separate from HAP port allocation to avoid conflicts.
 */
export class MatterPortAllocator {
    matterPorts;
    allocatedPorts = new Map();
    configuredPorts = new Set();
    constructor(matterPorts, configuredMatterPorts) {
        this.matterPorts = matterPorts;
        if (configuredMatterPorts) {
            this.configuredPorts = new Set(configuredMatterPorts);
        }
    }
    /**
     * Returns the next available Matter port in the Matter port config.
     * If Matter ports are not configured, falls back to range 5530-5541.
     * If the port range has been exhausted it will return undefined.
     *
     * @param uuid - Unique identifier for the Matter accessory (can be accessory UUID or other unique string)
     */
    async requestPort(uuid) {
        // Check to see if this accessory has already requested a Matter port
        const existingPortAllocation = this.allocatedPorts.get(uuid);
        if (existingPortAllocation !== undefined) {
            return existingPortAllocation;
        }
        // Get the next unused Matter port
        const port = this.getNextFreePort();
        this.allocatedPorts.set(uuid, port);
        return port;
    }
    /**
     * Get the next free Matter port from the configured range
     */
    getNextFreePort() {
        // Fallback to default range 5530-5541, avoiding already allocated ports
        const rangeStart = this.matterPorts?.start || 5530;
        const rangeEnd = this.matterPorts?.end || 5541;
        if (rangeStart > rangeEnd) {
            log.error(`Invalid Matter port range: start (${rangeStart}) is greater than end (${rangeEnd}).`);
            return undefined;
        }
        const allocatedPortValues = new Set([
            ...this.configuredPorts,
            ...[...this.allocatedPorts.values()].filter((p) => p !== undefined),
        ]);
        // Find first unallocated port in preferred range
        for (let port = rangeStart; port <= rangeEnd; port += 1) {
            if (!allocatedPortValues.has(port)) {
                return port;
            }
        }
        // Preferred range exhausted - find any available port above the range
        log.warn(`Matter port range ${rangeStart}-${rangeEnd} exhausted, allocating from extended range.`);
        for (let port = rangeEnd + 1; port <= 65535; port += 1) {
            if (!allocatedPortValues.has(port)) {
                return port;
            }
        }
        log.error('No available ports remaining for Matter allocation.');
        return undefined;
    }
    /**
     * Get statistics about port allocation
     */
    getStats() {
        return {
            allocatedCount: this.allocatedPorts.size,
            configuredPortsCount: this.configuredPorts.size,
        };
    }
}
//# sourceMappingURL=MatterPortAllocator.js.map