"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const messaging_1 = require("@mablhq-internal/runtime/core/messaging/messaging");
const FindStrategy_1 = __importDefault(require("./FindStrategy"));
class OrderedFindStrategy extends FindStrategy_1.default {
    strategies;
    groupStrategyWaitTimeoutMaximumMs;
    shouldSkipRetries;
    constructor(strategies, groupStrategyWaitTimeoutMaximumMs, shouldSkipRetries) {
        super();
        this.strategies = strategies;
        this.groupStrategyWaitTimeoutMaximumMs = groupStrategyWaitTimeoutMaximumMs;
        this.shouldSkipRetries = shouldSkipRetries;
    }
    getName() {
        return 'OrderedFindStrategy';
    }
    async findElement(driver, mobileExecutionContext, descriptor, isShortCircuited) {
        const shouldStopFind = () => !mobileExecutionContext.isRunningStep() || isShortCircuited();
        return this.findElementUsingAllStrategies(driver, mobileExecutionContext, descriptor, shouldStopFind);
    }
    async findElementUsingAllStrategies(driver, mobileExecutionContext, descriptor, isShortCircuited) {
        for (const strategiesGroup of this.strategies) {
            const result = await this.findElementUsingStrategies(driver, mobileExecutionContext, descriptor, strategiesGroup, isShortCircuited);
            if (result) {
                return result;
            }
        }
        return undefined;
    }
    async findElementUsingStrategies(driver, mobileExecutionContext, descriptor, strategies, isShortCircuited) {
        const applicableStrategies = strategies.filter((strategy) => strategy.isApplicable(descriptor));
        if (applicableStrategies.length === 0) {
            return undefined;
        }
        const sumOfPerStrategyTimeouts = applicableStrategies.reduce((previousValue, currentValue) => previousValue + currentValue.getFindTimeout(), 0);
        const maxFindExecutionTimeMs = Math.min(sumOfPerStrategyTimeouts, this.groupStrategyWaitTimeoutMaximumMs);
        mobileExecutionContext.log.debug(`Running strategy group for up to ${maxFindExecutionTimeMs}ms`, {
            executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
        });
        if (this.shouldSkipRetries) {
            mobileExecutionContext.log.debug('Only running strategy group once since shouldSkipRetries is true.', {
                executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
            });
        }
        const startTime = performance.now();
        let elapsedTimeMs = 0;
        let findAttemptNumber = 1;
        do {
            for (const strategy of applicableStrategies) {
                if (isShortCircuited()) {
                    return undefined;
                }
                const strategyName = strategy.getName();
                mobileExecutionContext.log.debug(`Running strategy: ${strategyName} on find attempt: ${findAttemptNumber}`, {
                    executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
                });
                const result = await strategy.findElement(driver, mobileExecutionContext, descriptor, isShortCircuited);
                if (result) {
                    elapsedTimeMs = performance.now() - startTime;
                    mobileExecutionContext.log.debug(`Found result with strategy: ${strategyName} with elapsed time: ${elapsedTimeMs}ms`, {
                        executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
                    });
                    return result;
                }
                elapsedTimeMs = performance.now() - startTime;
                mobileExecutionContext.log.debug(`Did not find element with strategy: ${strategyName} with elapsed time: ${elapsedTimeMs}ms`, {
                    executionPhase: messaging_1.ExecutionPhase.DURING_ACTION,
                });
            }
            findAttemptNumber++;
            elapsedTimeMs = performance.now() - startTime;
        } while (elapsedTimeMs < maxFindExecutionTimeMs && !this.shouldSkipRetries);
        return undefined;
    }
}
exports.default = OrderedFindStrategy;
