'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var coreRestPipeline = require('@azure/core-rest-pipeline');
var coreClient = require('@azure/core-client');

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
const disableKeepAlivePolicyName = "DisableKeepAlivePolicy";
function createDisableKeepAlivePolicy() {
    return {
        name: disableKeepAlivePolicyName,
        async sendRequest(request, next) {
            request.disableKeepAlive = true;
            return next(request);
        },
    };
}
/**
 * @internal
 */
function pipelineContainsDisableKeepAlivePolicy(pipeline) {
    return pipeline.getOrderedPolicies().some((policy) => policy.name === disableKeepAlivePolicyName);
}

// Copyright (c) Microsoft Corporation.
// We use a custom symbol to cache a reference to the original request without
// exposing it on the public interface.
const originalRequestSymbol = Symbol("Original PipelineRequest");
// Symbol.for() will return the same symbol if it's already been created
// This particular one is used in core-client to handle the case of when a request is
// cloned but we need to retrieve the OperationSpec and OperationArguments from the
// original request.
const originalClientRequestSymbol = Symbol.for("@azure/core-client original request");
function toPipelineRequest(webResource, options = {}) {
    const compatWebResource = webResource;
    const request = compatWebResource[originalRequestSymbol];
    const headers = coreRestPipeline.createHttpHeaders(webResource.headers.toJson({ preserveCase: true }));
    if (request) {
        request.headers = headers;
        return request;
    }
    else {
        const newRequest = coreRestPipeline.createPipelineRequest({
            url: webResource.url,
            method: webResource.method,
            headers,
            withCredentials: webResource.withCredentials,
            timeout: webResource.timeout,
            requestId: webResource.requestId,
            abortSignal: webResource.abortSignal,
            body: webResource.body,
            formData: webResource.formData,
            disableKeepAlive: !!webResource.keepAlive,
            onDownloadProgress: webResource.onDownloadProgress,
            onUploadProgress: webResource.onUploadProgress,
            proxySettings: webResource.proxySettings,
            streamResponseStatusCodes: webResource.streamResponseStatusCodes,
        });
        if (options.originalRequest) {
            newRequest[originalClientRequestSymbol] =
                options.originalRequest;
        }
        return newRequest;
    }
}
function toWebResourceLike(request, options) {
    var _a;
    const originalRequest = (_a = options === null || options === void 0 ? void 0 : options.originalRequest) !== null && _a !== void 0 ? _a : request;
    const webResource = {
        url: request.url,
        method: request.method,
        headers: toHttpHeadersLike(request.headers),
        withCredentials: request.withCredentials,
        timeout: request.timeout,
        requestId: request.headers.get("x-ms-client-request-id") || request.requestId,
        abortSignal: request.abortSignal,
        body: request.body,
        formData: request.formData,
        keepAlive: !!request.disableKeepAlive,
        onDownloadProgress: request.onDownloadProgress,
        onUploadProgress: request.onUploadProgress,
        proxySettings: request.proxySettings,
        streamResponseStatusCodes: request.streamResponseStatusCodes,
        clone() {
            throw new Error("Cannot clone a non-proxied WebResourceLike");
        },
        prepare() {
            throw new Error("WebResourceLike.prepare() is not supported by @azure/core-http-compat");
        },
        validateRequestProperties() {
            /** do nothing */
        },
    };
    if (options === null || options === void 0 ? void 0 : options.createProxy) {
        return new Proxy(webResource, {
            get(target, prop, receiver) {
                if (prop === originalRequestSymbol) {
                    return request;
                }
                else if (prop === "clone") {
                    return () => {
                        return toWebResourceLike(toPipelineRequest(webResource, { originalRequest }), {
                            createProxy: true,
                            originalRequest,
                        });
                    };
                }
                return Reflect.get(target, prop, receiver);
            },
            set(target, prop, value, receiver) {
                if (prop === "keepAlive") {
                    request.disableKeepAlive = !value;
                }
                const passThroughProps = [
                    "url",
                    "method",
                    "withCredentials",
                    "timeout",
                    "requestId",
                    "abortSignal",
                    "body",
                    "formData",
                    "onDownloadProgress",
                    "onUploadProgress",
                    "proxySettings",
                    "streamResponseStatusCodes",
                ];
                if (typeof prop === "string" && passThroughProps.includes(prop)) {
                    request[prop] = value;
                }
                return Reflect.set(target, prop, value, receiver);
            },
        });
    }
    else {
        return webResource;
    }
}
/**
 * Converts HttpHeaders from core-rest-pipeline to look like
 * HttpHeaders from core-http.
 * @param headers - HttpHeaders from core-rest-pipeline
 * @returns HttpHeaders as they looked in core-http
 */
function toHttpHeadersLike(headers) {
    return new HttpHeaders(headers.toJSON({ preserveCase: true }));
}
/**
 * A collection of HttpHeaders that can be sent with a HTTP request.
 */
function getHeaderKey(headerName) {
    return headerName.toLowerCase();
}
/**
 * A collection of HTTP header key/value pairs.
 */
class HttpHeaders {
    constructor(rawHeaders) {
        this._headersMap = {};
        if (rawHeaders) {
            for (const headerName in rawHeaders) {
                this.set(headerName, rawHeaders[headerName]);
            }
        }
    }
    /**
     * Set a header in this collection with the provided name and value. The name is
     * case-insensitive.
     * @param headerName - The name of the header to set. This value is case-insensitive.
     * @param headerValue - The value of the header to set.
     */
    set(headerName, headerValue) {
        this._headersMap[getHeaderKey(headerName)] = {
            name: headerName,
            value: headerValue.toString(),
        };
    }
    /**
     * Get the header value for the provided header name, or undefined if no header exists in this
     * collection with the provided name.
     * @param headerName - The name of the header.
     */
    get(headerName) {
        const header = this._headersMap[getHeaderKey(headerName)];
        return !header ? undefined : header.value;
    }
    /**
     * Get whether or not this header collection contains a header entry for the provided header name.
     */
    contains(headerName) {
        return !!this._headersMap[getHeaderKey(headerName)];
    }
    /**
     * Remove the header with the provided headerName. Return whether or not the header existed and
     * was removed.
     * @param headerName - The name of the header to remove.
     */
    remove(headerName) {
        const result = this.contains(headerName);
        delete this._headersMap[getHeaderKey(headerName)];
        return result;
    }
    /**
     * Get the headers that are contained this collection as an object.
     */
    rawHeaders() {
        return this.toJson({ preserveCase: true });
    }
    /**
     * Get the headers that are contained in this collection as an array.
     */
    headersArray() {
        const headers = [];
        for (const headerKey in this._headersMap) {
            headers.push(this._headersMap[headerKey]);
        }
        return headers;
    }
    /**
     * Get the header names that are contained in this collection.
     */
    headerNames() {
        const headerNames = [];
        const headers = this.headersArray();
        for (let i = 0; i < headers.length; ++i) {
            headerNames.push(headers[i].name);
        }
        return headerNames;
    }
    /**
     * Get the header values that are contained in this collection.
     */
    headerValues() {
        const headerValues = [];
        const headers = this.headersArray();
        for (let i = 0; i < headers.length; ++i) {
            headerValues.push(headers[i].value);
        }
        return headerValues;
    }
    /**
     * Get the JSON object representation of this HTTP header collection.
     */
    toJson(options = {}) {
        const result = {};
        if (options.preserveCase) {
            for (const headerKey in this._headersMap) {
                const header = this._headersMap[headerKey];
                result[header.name] = header.value;
            }
        }
        else {
            for (const headerKey in this._headersMap) {
                const header = this._headersMap[headerKey];
                result[getHeaderKey(header.name)] = header.value;
            }
        }
        return result;
    }
    /**
     * Get the string representation of this HTTP header collection.
     */
    toString() {
        return JSON.stringify(this.toJson({ preserveCase: true }));
    }
    /**
     * Create a deep clone/copy of this HttpHeaders collection.
     */
    clone() {
        const resultPreservingCasing = {};
        for (const headerKey in this._headersMap) {
            const header = this._headersMap[headerKey];
            resultPreservingCasing[header.name] = header.value;
        }
        return new HttpHeaders(resultPreservingCasing);
    }
}

// Copyright (c) Microsoft Corporation.
const originalResponse = Symbol("Original FullOperationResponse");
/**
 * A helper to convert response objects from the new pipeline back to the old one.
 * @param response - A response object from core-client.
 * @returns A response compatible with `HttpOperationResponse` from core-http.
 */
function toCompatResponse(response, options) {
    let request = toWebResourceLike(response.request);
    let headers = toHttpHeadersLike(response.headers);
    if (options === null || options === void 0 ? void 0 : options.createProxy) {
        return new Proxy(response, {
            get(target, prop, receiver) {
                if (prop === "headers") {
                    return headers;
                }
                else if (prop === "request") {
                    return request;
                }
                else if (prop === originalResponse) {
                    return response;
                }
                return Reflect.get(target, prop, receiver);
            },
            set(target, prop, value, receiver) {
                if (prop === "headers") {
                    headers = value;
                }
                else if (prop === "request") {
                    request = value;
                }
                return Reflect.set(target, prop, value, receiver);
            },
        });
    }
    else {
        return Object.assign(Object.assign({}, response), { request,
            headers });
    }
}
/**
 * A helper to convert back to a PipelineResponse
 * @param compatResponse - A response compatible with `HttpOperationResponse` from core-http.
 */
function toPipelineResponse(compatResponse) {
    const extendedCompatResponse = compatResponse;
    const response = extendedCompatResponse[originalResponse];
    const headers = coreRestPipeline.createHttpHeaders(compatResponse.headers.toJson({ preserveCase: true }));
    if (response) {
        response.headers = headers;
        return response;
    }
    else {
        return Object.assign(Object.assign({}, compatResponse), { headers, request: toPipelineRequest(compatResponse.request) });
    }
}

// Copyright (c) Microsoft Corporation.
/**
 * Client to provide compatability between core V1 & V2.
 */
class ExtendedServiceClient extends coreClient.ServiceClient {
    constructor(options) {
        var _a, _b;
        super(options);
        if (((_a = options.keepAliveOptions) === null || _a === void 0 ? void 0 : _a.enable) === false &&
            !pipelineContainsDisableKeepAlivePolicy(this.pipeline)) {
            this.pipeline.addPolicy(createDisableKeepAlivePolicy());
        }
        if (((_b = options.redirectOptions) === null || _b === void 0 ? void 0 : _b.handleRedirects) === false) {
            this.pipeline.removePolicy({
                name: coreRestPipeline.redirectPolicyName,
            });
        }
    }
    /**
     * Compatible send operation request function.
     *
     * @param operationArguments - Operation arguments
     * @param operationSpec - Operation Spec
     * @returns
     */
    async sendOperationRequest(operationArguments, operationSpec) {
        var _a;
        const userProvidedCallBack = (_a = operationArguments === null || operationArguments === void 0 ? void 0 : operationArguments.options) === null || _a === void 0 ? void 0 : _a.onResponse;
        let lastResponse;
        function onResponse(rawResponse, flatResponse, error) {
            lastResponse = rawResponse;
            if (userProvidedCallBack) {
                userProvidedCallBack(rawResponse, flatResponse, error);
            }
        }
        operationArguments.options = Object.assign(Object.assign({}, operationArguments.options), { onResponse });
        const result = await super.sendOperationRequest(operationArguments, operationSpec);
        if (lastResponse) {
            Object.defineProperty(result, "_response", {
                value: toCompatResponse(lastResponse),
            });
        }
        return result;
    }
}

// Copyright (c) Microsoft Corporation.
/**
 * An enum for compatibility with RequestPolicy
 */
exports.HttpPipelineLogLevel = void 0;
(function (HttpPipelineLogLevel) {
    HttpPipelineLogLevel[HttpPipelineLogLevel["ERROR"] = 1] = "ERROR";
    HttpPipelineLogLevel[HttpPipelineLogLevel["INFO"] = 3] = "INFO";
    HttpPipelineLogLevel[HttpPipelineLogLevel["OFF"] = 0] = "OFF";
    HttpPipelineLogLevel[HttpPipelineLogLevel["WARNING"] = 2] = "WARNING";
})(exports.HttpPipelineLogLevel || (exports.HttpPipelineLogLevel = {}));
const mockRequestPolicyOptions = {
    log(_logLevel, _message) {
        /* do nothing */
    },
    shouldLog(_logLevel) {
        return false;
    },
};
/**
 * The name of the RequestPolicyFactoryPolicy
 */
const requestPolicyFactoryPolicyName = "RequestPolicyFactoryPolicy";
/**
 * A policy that wraps policies written for core-http.
 * @param factories - An array of `RequestPolicyFactory` objects from a core-http pipeline
 */
function createRequestPolicyFactoryPolicy(factories) {
    const orderedFactories = factories.slice().reverse();
    return {
        name: requestPolicyFactoryPolicyName,
        async sendRequest(request, next) {
            let httpPipeline = {
                async sendRequest(httpRequest) {
                    const response = await next(toPipelineRequest(httpRequest));
                    return toCompatResponse(response, { createProxy: true });
                },
            };
            for (const factory of orderedFactories) {
                httpPipeline = factory.create(httpPipeline, mockRequestPolicyOptions);
            }
            const webResourceLike = toWebResourceLike(request, { createProxy: true });
            const response = await httpPipeline.sendRequest(webResourceLike);
            return toPipelineResponse(response);
        },
    };
}

// Copyright (c) Microsoft Corporation.
/**
 * Converts a RequestPolicy based HttpClient to a PipelineRequest based HttpClient.
 * @param requestPolicyClient - A HttpClient compatible with core-http
 * @returns A HttpClient compatible with core-rest-pipeline
 */
function convertHttpClient(requestPolicyClient) {
    return {
        sendRequest: async (request) => {
            const response = await requestPolicyClient.sendRequest(toWebResourceLike(request, { createProxy: true }));
            return toPipelineResponse(response);
        },
    };
}

exports.ExtendedServiceClient = ExtendedServiceClient;
exports.convertHttpClient = convertHttpClient;
exports.createRequestPolicyFactoryPolicy = createRequestPolicyFactoryPolicy;
exports.disableKeepAlivePolicyName = disableKeepAlivePolicyName;
exports.requestPolicyFactoryPolicyName = requestPolicyFactoryPolicyName;
exports.toHttpHeadersLike = toHttpHeadersLike;
//# sourceMappingURL=index.js.map
