/**
 * Observer Coordinator
 *
 * Wires ScreenObserver + FileWatcher + TriggerRegistry together.
 * Aggregates events and deduplicates.
 */
import { EventEmitter } from 'events';
import { TriggerRegistry } from './trigger-registry.js';
import { logger } from '../../utils/logger.js';
const DEFAULT_CONFIG = {
    enableScreenObserver: false,
    enableFileWatcher: true,
    screenIntervalMs: 10000,
    deduplicationWindowMs: 1000,
};
export class ObserverCoordinator extends EventEmitter {
    config;
    screenObserver;
    triggerManager;
    triggerRegistry;
    recentEvents = new Map(); // eventKey -> timestamp
    running = false;
    constructor(screenObserver, triggerManager, config = {}) {
        super();
        this.config = { ...DEFAULT_CONFIG, ...config };
        this.screenObserver = screenObserver;
        this.triggerManager = triggerManager;
        this.triggerRegistry = new TriggerRegistry(triggerManager);
    }
    /**
     * Start all observers
     */
    async start() {
        if (this.running)
            return;
        // Load persisted triggers
        await this.triggerRegistry.load();
        // Wire screen observer
        if (this.config.enableScreenObserver) {
            this.screenObserver.on('change', (diff) => {
                this.handleScreenChange(diff);
            });
            this.screenObserver.start(this.config.screenIntervalMs);
        }
        // Wire trigger actions
        this.triggerManager.on('trigger:fired', ({ trigger, event }) => {
            this.emit('action', { trigger, event });
        });
        this.running = true;
        this.emit('started');
        logger.info('Observer coordinator started');
    }
    /**
     * Stop all observers
     */
    async stop() {
        this.screenObserver.stop();
        await this.triggerRegistry.save();
        this.running = false;
        this.emit('stopped');
    }
    /**
     * Handle screen change event
     */
    handleScreenChange(diff) {
        const eventKey = `screen_change:${diff.currentHash}`;
        if (this.isDuplicate(eventKey))
            return;
        const event = {
            triggerId: '',
            type: 'screen_change',
            data: {
                changePercentage: diff.changePercentage,
                regions: diff.changedRegions,
            },
            timestamp: diff.timestamp,
        };
        this.triggerManager.evaluate(event);
        this.emit('event', event);
    }
    /**
     * Handle file change event (called externally)
     */
    handleFileChange(filePath, changeType) {
        const eventKey = `file_change:${filePath}:${changeType}`;
        if (this.isDuplicate(eventKey))
            return;
        const event = {
            triggerId: '',
            type: 'file_change',
            data: { path: filePath, changeType },
            timestamp: new Date(),
        };
        this.triggerManager.evaluate(event);
        this.emit('event', event);
    }
    /**
     * Handle webhook event
     */
    handleWebhook(data) {
        const event = {
            triggerId: '',
            type: 'webhook',
            data,
            timestamp: new Date(),
        };
        this.triggerManager.evaluate(event);
        this.emit('event', event);
    }
    /**
     * Check for duplicate events within deduplication window
     */
    isDuplicate(key) {
        const lastSeen = this.recentEvents.get(key);
        const now = Date.now();
        if (lastSeen && (now - lastSeen) < this.config.deduplicationWindowMs) {
            return true;
        }
        this.recentEvents.set(key, now);
        // Clean old entries
        if (this.recentEvents.size > 1000) {
            const cutoff = now - this.config.deduplicationWindowMs * 2;
            for (const [k, t] of this.recentEvents) {
                if (t < cutoff)
                    this.recentEvents.delete(k);
            }
        }
        return false;
    }
    /**
     * Get registry for CRUD operations
     */
    getRegistry() {
        return this.triggerRegistry;
    }
    isRunning() {
        return this.running;
    }
}
//# sourceMappingURL=observer-coordinator.js.map