// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { getPollingUrl, inferLroMode, isUnexpectedInitialResponse } from "./requestUtils";
import { isBodyPollingDone, processBodyPollingOperationResult } from "./bodyPolling";
import { logger } from "./logger";
import { processLocationPollingOperationResult } from "./locationPolling";
import { processPassthroughOperationResult } from "./passthrough";
/**
 * creates a stepping function that maps an LRO state to another.
 */
export function createGetLroStatusFromResponse(lroPrimitives, config, lroResourceLocationConfig) {
    switch (config.mode) {
        case "Location": {
            return processLocationPollingOperationResult(lroPrimitives, config.resourceLocation, lroResourceLocationConfig);
        }
        case "Body": {
            return processBodyPollingOperationResult;
        }
        default: {
            return processPassthroughOperationResult;
        }
    }
}
/**
 * Creates a polling operation.
 */
export function createPoll(lroPrimitives) {
    return async (path, pollerConfig, getLroStatusFromResponse) => {
        const response = await lroPrimitives.sendPollRequest(path);
        const retryAfter = response.rawResponse.headers["retry-after"];
        if (retryAfter !== undefined) {
            // Retry-After header value is either in HTTP date format, or in seconds
            const retryAfterInSeconds = parseInt(retryAfter);
            pollerConfig.intervalInMs = isNaN(retryAfterInSeconds)
                ? calculatePollingIntervalFromDate(new Date(retryAfter), pollerConfig.intervalInMs)
                : retryAfterInSeconds * 1000;
        }
        return getLroStatusFromResponse(response);
    };
}
function calculatePollingIntervalFromDate(retryAfterDate, defaultIntervalInMs) {
    const timeNow = Math.floor(new Date().getTime());
    const retryAfterTime = retryAfterDate.getTime();
    if (timeNow < retryAfterTime) {
        return retryAfterTime - timeNow;
    }
    return defaultIntervalInMs;
}
/**
 * Creates a callback to be used to initialize the polling operation state.
 * @param state - of the polling operation
 * @param operationSpec - of the LRO
 * @param callback - callback to be called when the operation is done
 * @returns callback that initializes the state of the polling operation
 */
export function createInitializeState(state, requestPath, requestMethod) {
    return (response) => {
        if (isUnexpectedInitialResponse(response.rawResponse))
            return true;
        state.initialRawResponse = response.rawResponse;
        state.isStarted = true;
        state.pollingURL = getPollingUrl(state.initialRawResponse, requestPath);
        state.config = inferLroMode(requestPath, requestMethod, state.initialRawResponse);
        /** short circuit polling if body polling is done in the initial request */
        if (state.config.mode === undefined ||
            (state.config.mode === "Body" && isBodyPollingDone(state.initialRawResponse))) {
            state.result = response.flatResponse;
            state.isCompleted = true;
        }
        logger.verbose(`LRO: initial state: ${JSON.stringify(state)}`);
        return Boolean(state.isCompleted);
    };
}
//# sourceMappingURL=stateMachine.js.map