import { lsl_resolve_all, lsl_resolve_byprop, lsl_resolve_bypred, lsl_create_continuous_resolver, lsl_create_continuous_resolver_byprop, lsl_create_continuous_resolver_bypred, lsl_destroy_continuous_resolver, lsl_resolver_results } from './lib/index.js';
import { StreamInfo } from './streamInfo.js';
import { FOREVER } from './util.js';
/**
 * Find all streams on the network.
 * @param waitTime Time to wait for streams in seconds (default: 1.0)
 * @returns Array of StreamInfo objects
 */
export function resolveStreams(waitTime = 1.0) {
    // Create buffer for stream info pointers
    const bufferSize = 1024;
    const buffer = new Array(bufferSize).fill(null);
    // Resolve streams
    const numFound = lsl_resolve_all(buffer, bufferSize, waitTime);
    // Convert to StreamInfo objects
    const results = [];
    for (let i = 0; i < numFound; i++) {
        const handle = buffer[i];
        if (handle) {
            results.push(new StreamInfo('', '', 0, 0, 0, '', handle));
        }
    }
    return results;
}
/**
 * Find streams by a specific property.
 * @param prop Property name to match (e.g., 'name', 'type')
 * @param value Property value to match
 * @param minimum Minimum number of streams to find
 * @param timeout Timeout in seconds
 * @returns Array of StreamInfo objects
 */
export function resolveByProp(prop, value, minimum = 1, timeout = FOREVER) {
    // Create buffer for stream info pointers
    const bufferSize = 1024;
    const buffer = new Array(bufferSize).fill(null);
    // Resolve streams by property
    const numFound = lsl_resolve_byprop(buffer, bufferSize, prop, value, minimum, timeout);
    // Convert to StreamInfo objects
    const results = [];
    for (let i = 0; i < numFound; i++) {
        const handle = buffer[i];
        if (handle) {
            results.push(new StreamInfo('', '', 0, 0, 0, '', handle));
        }
    }
    return results;
}
/**
 * Find streams by an XPath predicate.
 * @param predicate XPath predicate string (e.g., "name='MyStream' and type='EEG'")
 * @param minimum Minimum number of streams to find
 * @param timeout Timeout in seconds
 * @returns Array of StreamInfo objects
 */
export function resolveByPred(predicate, minimum = 1, timeout = FOREVER) {
    // Create buffer for stream info pointers
    const bufferSize = 1024;
    const buffer = new Array(bufferSize).fill(null);
    // Resolve streams by predicate
    const numFound = lsl_resolve_bypred(buffer, bufferSize, predicate, minimum, timeout);
    // Convert to StreamInfo objects
    const results = [];
    for (let i = 0; i < numFound; i++) {
        const handle = buffer[i];
        if (handle) {
            results.push(new StreamInfo('', '', 0, 0, 0, '', handle));
        }
    }
    return results;
}
// Legacy compatibility function
export function resolveStream(...args) {
    if (args.length === 0) {
        return resolveStreams();
    }
    else if (typeof args[0] === 'number') {
        return resolveStreams(args[0]);
    }
    else if (typeof args[0] === 'string') {
        if (args.length === 1) {
            return resolveByPred(args[0]);
        }
        else if (typeof args[1] === 'number') {
            return resolveByPred(args[0], args[1]);
        }
        else {
            if (args.length === 2) {
                return resolveByProp(args[0], args[1]);
            }
            else {
                return resolveByProp(args[0], args[1], args[2]);
            }
        }
    }
    throw new Error('Invalid arguments for resolveStream');
}
// FinalizationRegistry for automatic cleanup
const resolverRegistry = new FinalizationRegistry((obj) => {
    try {
        lsl_destroy_continuous_resolver(obj);
    }
    catch (e) {
        // Silently ignore cleanup errors
    }
});
/**
 * Continuously resolves streams in the background.
 * Useful for monitoring streams that may appear and disappear.
 */
export class ContinuousResolver {
    obj; // Pointer to the continuous resolver object
    constructor(prop, value, pred, forgetAfter = 5.0) {
        if (pred !== undefined) {
            if (prop !== undefined || value !== undefined) {
                throw new Error('You can only either pass the prop/value argument or the pred argument, but not both.');
            }
            this.obj = lsl_create_continuous_resolver_bypred(pred, forgetAfter);
        }
        else if (prop !== undefined && value !== undefined) {
            this.obj = lsl_create_continuous_resolver_byprop(prop, value, forgetAfter);
        }
        else if (prop !== undefined || value !== undefined) {
            throw new Error('If prop is specified, then value must be specified too, and vice versa.');
        }
        else {
            this.obj = lsl_create_continuous_resolver(forgetAfter);
        }
        if (!this.obj) {
            throw new Error('Could not create continuous resolver.');
        }
        // Register for automatic cleanup
        resolverRegistry.register(this, this.obj, this);
    }
    /**
     * Destroy the resolver and free resources.
     */
    destroy() {
        if (this.obj) {
            try {
                resolverRegistry.unregister(this);
                lsl_destroy_continuous_resolver(this.obj);
            }
            catch (e) {
                // Silently ignore errors during destruction
            }
            this.obj = null;
        }
    }
    /**
     * Get the current list of resolved streams.
     * @returns Array of StreamInfo objects
     */
    results() {
        // Create buffer for stream info pointers
        const bufferSize = 1024;
        const buffer = new Array(bufferSize).fill(null);
        // Get resolver results
        const numFound = lsl_resolver_results(this.obj, buffer, bufferSize);
        // Convert to StreamInfo objects
        const results = [];
        for (let i = 0; i < numFound; i++) {
            const handle = buffer[i];
            if (handle) {
                results.push(new StreamInfo('', '', 0, 0, 0, '', handle));
            }
        }
        return results;
    }
}
//# sourceMappingURL=resolver.js.map