"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var OutboxPollingCoordinator_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutboxPollingCoordinator = void 0;
const common_1 = require("@nestjs/common");
const integration_settings_service_1 = require("./integration-settings.service");
const outbox_notifier_1 = require("./outbox.notifier");
const outbox_processor_1 = require("./outbox.processor");
/**
 * Hybrid polling coordinator
 * Manages the adaptive polling strategy: immediate reactions + periodic checks
 * Uses in-memory notifications for immediate wakeup + configurable polling intervals
 */
let OutboxPollingCoordinator = OutboxPollingCoordinator_1 = class OutboxPollingCoordinator {
    constructor(processor, notifier, integrationSettingsService) {
        this.processor = processor;
        this.notifier = notifier;
        this.integrationSettingsService = integrationSettingsService;
        this.logger = new common_1.Logger(OutboxPollingCoordinator_1.name);
        this.processingLoopRunning = false;
        this.processingLoopPromise = null;
        this.immediateWakeupTriggered = false;
        this.shouldStopLoop = false;
    }
    /**
     * Start the hybrid processing loop
     * Reacts to notifications immediately, polls periodically
     */
    async startProcessingLoop() {
        if (this.processingLoopRunning) {
            this.logger.warn('Processing loop already running');
            return;
        }
        this.processingLoopRunning = true;
        this.shouldStopLoop = false;
        this.logger.log('Starting outbox hybrid processing loop');
        this.processingLoopPromise = this.runProcessingLoop();
    }
    /**
     * Stop the processing loop gracefully
     */
    async stopProcessingLoop() {
        if (!this.processingLoopRunning) {
            return;
        }
        this.logger.log('Stopping outbox processing loop');
        this.shouldStopLoop = true;
        if (this.processingLoopPromise) {
            await this.processingLoopPromise;
        }
        this.processingLoopRunning = false;
    }
    /**
     * Trigger immediate processing from notifier
     */
    triggerImmediateProcessing() {
        this.immediateWakeupTriggered = true;
    }
    /**
     * Check if loop is currently running
     */
    isRunning() {
        return this.processingLoopRunning;
    }
    /**
     * Main processing loop - runs continuously
     */
    async runProcessingLoop() {
        // Subscribe to notifications
        const immediateWakeupListener = () => {
            this.triggerImmediateProcessing();
        };
        this.notifier.subscribe(immediateWakeupListener);
        try {
            while (!this.shouldStopLoop) {
                const settings = await this.integrationSettingsService.getRuntimeSettings();
                const isEnabled = settings.outboxEnabled;
                const processorEnabled = settings.outboxProcessorEnabled;
                if (!isEnabled || !processorEnabled) {
                    // If disabled, wait before checking again
                    await this.delay(settings.idlePollingIntervalMs);
                    continue;
                }
                // Check if we should process immediately (woken by notification)
                const shouldProcessImmediately = this.immediateWakeupTriggered;
                this.immediateWakeupTriggered = false;
                // Process batch
                const processedCount = await this.processor.processBatch();
                // Determine next polling interval
                let nextDelayMs;
                if (shouldProcessImmediately && processedCount > 0) {
                    // We processed items from immediate wakeup - use active polling interval
                    nextDelayMs = settings.pollingIntervalMs;
                    this.logger.debug(`Processed ${processedCount} events from immediate wakeup, next poll in ${nextDelayMs}ms`);
                }
                else if (processedCount > 0) {
                    // Processed items from periodic polling - use active interval
                    nextDelayMs = settings.pollingIntervalMs;
                    this.logger.debug(`Processed ${processedCount} events, next poll in ${nextDelayMs}ms`);
                }
                else {
                    // No items processed - use idle interval
                    nextDelayMs = settings.idlePollingIntervalMs;
                }
                // Wait for next poll, but be ready for immediate wakeup
                await this.delay(nextDelayMs);
            }
        }
        finally {
            // Cleanup: unsubscribe from notifications
            this.notifier.unsubscribe(immediateWakeupListener);
            this.logger.log('Processing loop stopped');
        }
    }
    /**
     * Utility: delay with cancellation support
     */
    delay(ms) {
        return new Promise((resolve) => {
            const timeout = setTimeout(resolve, ms);
            // Store timeout for potential cancellation (not used yet, but available)
            this._currentTimeout = timeout;
        });
    }
};
exports.OutboxPollingCoordinator = OutboxPollingCoordinator;
exports.OutboxPollingCoordinator = OutboxPollingCoordinator = OutboxPollingCoordinator_1 = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [outbox_processor_1.OutboxProcessor,
        outbox_notifier_1.OutboxNotifier,
        integration_settings_service_1.IntegrationSettingsService])
], OutboxPollingCoordinator);
//# sourceMappingURL=outbox-polling.coordinator.js.map