import { __assign, __read, __rest, __spread, __values } from "tslib";
import { parseQueryParameters, parseQueryParametersList, } from "../util";
export var ensureAbsoluteUrl = function (baseUrl, url) {
    if (!baseUrl || url.match(/^http/)) {
        return url;
    }
    if (baseUrl[baseUrl.length - 1] !== "/") {
        baseUrl += "/";
    }
    return baseUrl + url.slice(url[0] === "/" ? 1 : 0);
};
export function buildParameterString(params) {
    if (!params) {
        return "";
    }
    var entries;
    if (Array.isArray(params)) {
        entries = params;
    }
    else {
        entries = [];
        for (var key in params) {
            var value = params[key];
            entries.push({ key: key, value: value });
        }
    }
    return entries
        .filter(function (entry) { return entry.value !== undefined; })
        .map(function (_a) {
        var key = _a.key, rawValue = _a.value;
        var value;
        if (typeof rawValue === "object") {
            value = JSON.stringify(rawValue);
        }
        else {
            value = rawValue;
        }
        return key + "=" + encodeURIComponent(value);
    })
        .join("&");
}
export var createUrl = function (url, _a) {
    var e_1, _b;
    var _c = _a === void 0 ? {} : _a, params = _c.params, addTimestamp = _c.addTimestamp, baseUrl = _c.baseUrl;
    var paramString = "";
    var queryLocation = url.indexOf("?");
    var currentParams = queryLocation > -1 ? parseQueryParameters(url) : undefined;
    if (params || addTimestamp || currentParams) {
        var collectedParams = __assign(__assign({}, currentParams), params);
        if (addTimestamp) {
            collectedParams.timestamp = Date.now();
        }
        paramString = buildParameterString(collectedParams);
    }
    var bareUrl = queryLocation < 0 ? url : url.substr(0, queryLocation);
    if (paramString) {
        paramString = "?" + paramString;
    }
    if (baseUrl !== undefined && baseUrl.indexOf("?") > -1) {
        var baseUrlParams = parseQueryParametersList(baseUrl);
        if (baseUrlParams.length > 0) {
            // the base url ends with query parameters, so we need to join the url with the value of the last query param and encode it
            var lastParam = baseUrlParams[baseUrlParams.length - 1];
            var fullUrl_1 = ensureAbsoluteUrl(lastParam.value.toString(), bareUrl) +
                paramString;
            lastParam.value = fullUrl_1;
            var params_1 = {};
            try {
                for (var baseUrlParams_1 = __values(baseUrlParams), baseUrlParams_1_1 = baseUrlParams_1.next(); !baseUrlParams_1_1.done; baseUrlParams_1_1 = baseUrlParams_1.next()) {
                    var _d = baseUrlParams_1_1.value, key = _d.key, value = _d.value;
                    params_1[key] = value;
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (baseUrlParams_1_1 && !baseUrlParams_1_1.done && (_b = baseUrlParams_1.return)) _b.call(baseUrlParams_1);
                }
                finally { if (e_1) throw e_1.error; }
            }
            var completeUrl = createUrl(baseUrl, {
                params: params_1,
            });
            return completeUrl;
        }
    }
    var fullUrl = ensureAbsoluteUrl(baseUrl, bareUrl);
    return fullUrl + paramString;
};
var baseFetchConfig = {
    credentials: "same-origin",
    method: "GET",
};
export var joinConfigs = function (configs) {
    var e_2, _a;
    var result = { headers: {}, params: {} };
    var allConfigs = __spread([baseFetchConfig], configs);
    try {
        for (var allConfigs_1 = __values(allConfigs), allConfigs_1_1 = allConfigs_1.next(); !allConfigs_1_1.done; allConfigs_1_1 = allConfigs_1.next()) {
            var _b = allConfigs_1_1.value;
            var configParams = _b.params, headers = _b.headers, overrides = __rest(_b, ["params", "headers"]);
            if (configParams) {
                result.params = Object.assign(result.params, configParams);
            }
            if (headers) {
                result.headers = Object.assign(result.headers, headers);
            }
            Object.assign(result, overrides);
        }
    }
    catch (e_2_1) { e_2 = { error: e_2_1 }; }
    finally {
        try {
            if (allConfigs_1_1 && !allConfigs_1_1.done && (_a = allConfigs_1.return)) _a.call(allConfigs_1);
        }
        finally { if (e_2) throw e_2.error; }
    }
    return result;
};
var formData = typeof FormData === "undefined" ? undefined : FormData;
export var buildRequestConfig = function (url, config) {
    var _a = joinConfigs([config]), addTimestamp = _a.addTimestamp, params = _a.params, json = _a.json, baseUrl = _a.baseUrl, requestInit = __rest(_a, ["addTimestamp", "params", "json", "baseUrl"]);
    if ((formData === undefined || !(requestInit.body instanceof formData)) &&
        requestInit.body &&
        typeof requestInit.body === "object") {
        requestInit.body = JSON.stringify(requestInit.body);
    }
    return [createUrl(url, { params: params, addTimestamp: addTimestamp, baseUrl: baseUrl }), requestInit];
};
export var handleFetchResult = function (response) {
    if (response.ok !== true) {
        return response
            .text()
            .then(function (text) {
            return Promise.reject(new Error("[" + response.status + "] " + response.statusText + ": " + text));
        });
    }
    return Promise.resolve(response);
};
/**
 * path segments
 *
 * @param {...string[]} pathSegments
 * @returns {string}
 */
export var joinPaths = function () {
    var pathSegments = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        pathSegments[_i] = arguments[_i];
    }
    var url = pathSegments[0];
    if (pathSegments.length < 2) {
        return url;
    }
    for (var index = 1; index < pathSegments.length; index++) {
        var segment = pathSegments[index];
        if (url[url.length - 1] !== "/") {
            url += "/";
        }
        if (segment[0] === "/") {
            segment = segment.slice(1);
        }
        else if (segment[0] === "." && segment[1] === "/") {
            segment = segment.slice(2);
        }
        url += segment;
    }
    return url;
};
/**
 * check if url ends with desired fileEnding
 * @param url
 * @param fileEnding
 */
export var isFileType = function (url, fileEnding) {
    if (!url || !fileEnding) {
        return false;
    }
    var lcFileEnding = fileEnding.toLowerCase();
    if (lcFileEnding.indexOf(".") === 0) {
        lcFileEnding = lcFileEnding.slice(1);
    }
    var lcUrl = url.toLowerCase();
    if (lcFileEnding.length > lcUrl.length) {
        return false;
    }
    var position = lcUrl.length - lcFileEnding.length;
    if (lcUrl[position - 1] !== ".") {
        return false;
    }
    var lastIndex = lcUrl.indexOf(lcFileEnding, position);
    return lastIndex !== -1 && lastIndex === position;
};
/**
 * checks if url is an absolute path
 * @param url
 * @param validPrefixes protocols like http, https etc. (default value: ["http:", "https:", "ftp:", "sftp:", "ftps:"])
 */
export var isAbsoluteUrl = function (url, validPrefixes) {
    if (validPrefixes === void 0) { validPrefixes = [
        "http://",
        "https://",
        "ftp://",
        "sftp://",
        "ftps://",
    ]; }
    if (!validPrefixes) {
        console.warn("ig.utilities/http/isAbsoluteUrl: no valid prefixes given");
        return false;
    }
    var lcUrl = url.toLowerCase();
    var result = validPrefixes.some(function (prefix) {
        return lcUrl.indexOf(prefix) === 0;
    });
    return result;
};
