"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransportHttp = void 0;
const lodash_1 = require("lodash");
const baggage_header_1 = require("../../constants/baggage-header");
const logger_1 = require("../../logger");
const detect_environment_1 = require("../../util/detect-environment");
let EDP = {};
if ((0, detect_environment_1.detectEnvironment)() === "WEB" /* WEB */) {
    // tslint:disable-next-line: no-var-requires
    EDP = require('edp-helper-lib').EDP;
}
const config_1 = require("../../config");
const container_session_1 = require("../../constants/container-session");
const error_messages_1 = require("../../constants/error-messages");
const http_client_impl_1 = require("../../http-client/http-client-impl");
const detect_container_1 = require("../../util/detect-container");
const merge_request_params_1 = require("../../util/merge-request-params");
const constants_1 = require("../../constants");
const trim = (str, char) => str.split(char).filter(Boolean).join(char);
const removeProxyPrefix = (url) => {
    const rdpPrefix = trim(container_session_1.RDP_ENDPOINT_ROOT, '/');
    const udfPrefix = trim(container_session_1.UDF_ENDPOINT_ROOT, '/');
    const urlTrimmed = trim(url, '/');
    const startsWithRdp = urlTrimmed.toLowerCase().startsWith(rdpPrefix);
    const startsWithUdf = urlTrimmed.toLowerCase().startsWith(udfPrefix);
    const urlStartCropPosition = rdpPrefix.length;
    if (startsWithRdp || startsWithUdf) {
        return urlTrimmed.slice(urlStartCropPosition);
    }
    return url;
};
class TransportHttp {
    constructor(params) {
        this.isInitialized = false;
        this.appKey = params.appKey;
        this.bus = params.bus;
        this.httpClient = params.httpClient || http_client_impl_1.HttpClientImpl.getInstance();
        this.log = logger_1.logger.getLogger('TransportHttp');
    }
    /**
     * Returns a host for Platform-session from the configuration file
     */
    static get rdpPlatformHost() {
        return config_1.config.get('sessions').platform['default-session']['base-url'];
    }
    /**
     * Initialize all types of connections
     * Sends an authorization request through the transport channel
     * @param authParams {ContainerSessionAuthorize} params for authorization request
     */
    async initialize() {
        if (!EDP.getAccessToken) {
            throw new Error(error_messages_1.ErrorMessages.EDP_HELPER_UNAVAILABLE);
        }
        if (this.bus) {
            EDP.bus = this.bus;
        }
        this.isInitialized = true;
    }
    async authorize(authParams) {
        if (!this.isInitialized) {
            throw new Error(error_messages_1.ErrorMessages.INITIALIZE_FIRST);
        }
        EDP.appId = authParams.appKey;
        EDP.scopes = [authParams.scope];
        await EDP.getAccessToken();
    }
    async cleanUp() {
        return Promise.resolve(void 0);
    }
    /**
     * Get the prefix of URL for RDP requests
     */
    get rdpUrlRoot() {
        return '';
    }
    async request(requestParams) {
        const { url } = requestParams;
        const urlWithNoPrefix = removeProxyPrefix(url);
        const token = await EDP.getAccessToken();
        const headers = {
            Authorization: `Bearer ${token}`,
            Accept: 'application/json',
        };
        this.addBaggageHeader(requestParams);
        const sessionRequestParams = Object.assign(Object.assign({}, requestParams), { url: urlWithNoPrefix });
        const environment = await this.getEnvironment();
        let urlPrefix = container_session_1.RW_REQUEST_PREFIX;
        const useRelativeBaseUrlContainers = [container_session_1.ExecutionContainer.SXS_WEB];
        if (useRelativeBaseUrlContainers.some(container => container === environment)) {
            urlPrefix = TransportHttp.rdpPlatformHost;
        }
        const requestConfig = (0, merge_request_params_1.mergeRequestParams)(urlPrefix, sessionRequestParams, headers);
        return this.httpClient.request(requestConfig);
    }
    getStreamTransport() {
        throw new Error(error_messages_1.ErrorMessages.STREAMING_NOT_READY_OR_UNAVAILABLE);
    }
    getStreamLoginParams() {
        throw new Error(error_messages_1.ErrorMessages.STREAMING_NOT_READY_OR_UNAVAILABLE);
    }
    async getEnvironment() {
        if (this.environment) {
            return this.environment;
        }
        this.environment = await (0, detect_container_1.detectContainer)();
        return this.environment;
    }
    addBaggageHeader(requestParams) {
        const { headers: initialHeaders } = requestParams;
        if (initialHeaders) {
            const headerEntries = Object.entries(initialHeaders);
            const mappedEntries = headerEntries.map(([key, value]) => {
                return [key.toLowerCase(), value];
            });
            const lowerCaseHeaders = (0, lodash_1.fromPairs)(mappedEntries);
            const baggage = lowerCaseHeaders[baggage_header_1.BAGGAGE_HEADER];
            const baggageFields = this.deserializeBaggage(baggage);
            if (!baggageFields.has(baggage_header_1.ORIGIN_SVC_FIELD_NAME) || !this.isValid(baggageFields)) {
                baggageFields.set(baggage_header_1.ORIGIN_SVC_FIELD_NAME, `${constants_1.ASSET_ID}${baggage_header_1.ORIGIN_SVC_SEPARATOR}${this.appKey}`);
            }
            const filteredHeaders = headerEntries.filter(([key]) => key.toLowerCase() !== baggage_header_1.BAGGAGE_HEADER);
            requestParams.headers = (0, lodash_1.fromPairs)(filteredHeaders);
            requestParams.headers[baggage_header_1.BAGGAGE_HEADER] = this.serializeBaggage(baggageFields);
        }
        else {
            requestParams.headers = {
                [baggage_header_1.BAGGAGE_HEADER]: this.serializeBaggage(new Map([[baggage_header_1.ORIGIN_SVC_FIELD_NAME, `${constants_1.ASSET_ID}${baggage_header_1.ORIGIN_SVC_SEPARATOR}${this.appKey}`]])),
            };
        }
    }
    deserializeBaggage(baggage) {
        const fields = new Map();
        if (!!baggage) {
            baggage.split(baggage_header_1.BAGGAGE_FIELD_SEPARATOR).forEach((field) => {
                if (field.includes(baggage_header_1.FIELD_NAME_VALUE_SEPARATOR)) {
                    const entry = field.split(baggage_header_1.FIELD_NAME_VALUE_SEPARATOR, 2);
                    fields.set(...entry);
                }
            });
        }
        return fields;
    }
    serializeBaggage(baggageFields) {
        const baggage = [];
        baggageFields.forEach((value, key) => {
            baggage.push(`${key}${baggage_header_1.FIELD_NAME_VALUE_SEPARATOR}${value || ''}`);
        });
        return baggage.join(baggage_header_1.BAGGAGE_FIELD_SEPARATOR);
    }
    isValid(baggageFields) {
        const baggageValue = baggageFields.get(baggage_header_1.ORIGIN_SVC_FIELD_NAME);
        if (!!(baggageValue && baggageValue.split(baggage_header_1.ORIGIN_SVC_SEPARATOR).length > 1)) {
            return true;
        }
        this.log.warn(`Value of the baggage header is invalid. Existing value: ${baggageValue}. Baggage header will be overwritten.`);
        return false;
    }
}
exports.TransportHttp = TransportHttp;
//# sourceMappingURL=data:application/json;base64, 