/**
 * Screen Observer
 *
 * Periodic screen monitoring with perceptual hashing for change detection.
 * Maintains a rolling history of frames for diff comparison.
 */
import { EventEmitter } from 'events';
import * as crypto from 'crypto';
import { logger } from '../../utils/logger.js';
const DEFAULT_CONFIG = {
    intervalMs: 10000,
    maxHistory: 10,
    changeThreshold: 0.05,
};
// ============================================================================
// Screen Observer
// ============================================================================
export class ScreenObserver extends EventEmitter {
    config;
    timer = null;
    running = false;
    history = [];
    lastHash = '';
    captureImpl = null;
    constructor(config = {}) {
        super();
        this.config = { ...DEFAULT_CONFIG, ...config };
    }
    /**
     * Set the capture implementation (platform-specific)
     */
    setCaptureMethod(capture) {
        this.captureImpl = capture;
    }
    /**
     * Start observing
     */
    start(intervalMs) {
        if (this.running)
            return;
        const interval = intervalMs || this.config.intervalMs;
        this.running = true;
        this.timer = setInterval(() => {
            this.observe().catch(err => logger.debug('Screen observation failed', { error: String(err) }));
        }, interval);
        this.emit('started', { interval });
        logger.debug(`Screen observer started (interval: ${interval}ms)`);
    }
    /**
     * Stop observing
     */
    stop() {
        if (this.timer) {
            clearInterval(this.timer);
            this.timer = null;
        }
        this.running = false;
        this.emit('stopped');
    }
    /**
     * Run a single observation cycle
     */
    async observe() {
        try {
            let imageData = null;
            if (this.captureImpl) {
                imageData = await this.captureImpl();
            }
            // Compute hash
            const hash = imageData
                ? this.computeHash(imageData)
                : crypto.randomUUID(); // Fallback for testing
            const frame = {
                hash,
                timestamp: new Date(),
            };
            // Add to history
            this.history.push(frame);
            if (this.history.length > this.config.maxHistory) {
                this.history.shift();
            }
            // Compare with last frame
            const diff = this.compareHashes(this.lastHash, hash);
            this.lastHash = hash;
            if (diff.hasChanges) {
                this.emit('change', diff);
            }
            return diff;
        }
        catch (error) {
            logger.debug('Screen observation error', { error: String(error) });
            return null;
        }
    }
    /**
     * Compute perceptual hash of image data
     */
    computeHash(data) {
        return crypto.createHash('sha256').update(data).digest('hex').slice(0, 16);
    }
    /**
     * Compare two hashes and determine if there's a change
     */
    compareHashes(previous, current) {
        if (!previous) {
            return {
                hasChanges: false,
                changePercentage: 0,
                changedRegions: [],
                previousHash: '',
                currentHash: current,
                timestamp: new Date(),
            };
        }
        const hasChanges = previous !== current;
        return {
            hasChanges,
            changePercentage: hasChanges ? 1.0 : 0,
            changedRegions: hasChanges ? [{ x: 0, y: 0, width: 0, height: 0, description: 'full screen' }] : [],
            previousHash: previous,
            currentHash: current,
            timestamp: new Date(),
        };
    }
    /**
     * Get frame history
     */
    getHistory() {
        return [...this.history];
    }
    /**
     * Is observer running
     */
    isRunning() {
        return this.running;
    }
    /**
     * Get config
     */
    getConfig() {
        return { ...this.config };
    }
}
//# sourceMappingURL=screen-observer.js.map