import { __assign, __read } from "tslib";
import { noop, isString } from '@slardar/sdk-template';
import { now, getFullUrl } from '../../utils';
import { checkIsIgnored, isSensitiveHeader, applySendOnce } from './util';
export var httpGetterWithFetchObserver = function (report, tearDownGroup, _a, fetchConfig) {
    var _b = __read(_a, 2), fetchObserver = _b[0], getResourceObserver = _b[1];
    var setTraceHeader = fetchConfig.setTraceHeader, ignoreUrls = fetchConfig.ignoreUrls, hookCbAtReq = fetchConfig.hookCbAtReq;
    // eslint-disable-next-line compat/compat
    var Headers = window.Headers;
    // eslint-disable-next-line compat/compat
    var Request = window.Request;
    if (!Request || !Headers)
        return;
    tearDownGroup.push(fetchObserver[0](function (_a) {
        var _b = __read(_a, 2), req = _b[0], options = _b[1];
        var url = getFullUrl(req instanceof Request ? req.url : req);
        if (!isHttpURL(url) || checkIsIgnored(ignoreUrls, url)) {
            return noop;
        }
        setTraceHeader &&
            setTraceHeader(url, function (key, value) { return addHeader(key, value, req, options, Request, Headers); });
        var reportWithContext = hookCbAtReq(report);
        var _start = now();
        var timing = undefined;
        var resourceTearDown = getResourceObserver()[0](function (entry) {
            url === entry.name && !timing && (timing = entry);
        });
        return function (res) {
            var payload = getEventParams(req, options, res, Request, Headers, fetchConfig, _start);
            var reportFetchData = applySendOnce(function (data) {
                timing && (data.response.timing = timing);
                reportWithContext && reportWithContext({ ev_type: 'http', payload: data });
                resourceTearDown();
            });
            setTimeout(function () {
                reportFetchData(payload);
            }, 1000);
        };
    }));
};
var isHttpURL = function (url) {
    if (!isString(url)) {
        return false;
    }
    var _a = __read(url.split(':'), 2), protocol = _a[0], path = _a[1];
    return !path || protocol === 'http' || protocol === 'https';
};
var isRequest = function (req, Request) {
    return req instanceof Request;
};
var addHeader = function (key, value, req, options, Request, Headers) {
    var _a;
    if (isRequest(req, Request)) {
        req.headers.set(key, value);
    }
    else if (options.headers instanceof Headers) {
        options.headers.set(key, value);
    }
    else {
        options.headers = __assign(__assign({}, options.headers), (_a = {}, _a[key] = value, _a));
    }
};
var getFetchMethod = function (req, options, Request) {
    var method = (options && options.method) || 'get';
    if (isRequest(req, Request)) {
        method = req.method || method;
    }
    return method.toLowerCase();
};
var mergeHeaders = function (Headers) {
    var headers = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        headers[_i - 1] = arguments[_i];
    }
    try {
        return headers.reduce(function (sum, cur) {
            // eslint-disable-next-line compat/compat
            new Headers(cur || {}).forEach(function (val, key) { return !isSensitiveHeader(key, val) && (sum[key] = val); });
            return sum;
        }, {});
    }
    catch (_a) {
        return {};
    }
};
var getFetchBody = function (req, options, Request) {
    if (isRequest(req, Request)) {
        return req.body;
    }
    else {
        return options === null || options === void 0 ? void 0 : options.body;
    }
};
var getEventParams = function (req, options, res, Request, Headers, props, _start) {
    var _a, _b;
    var params = {
        api: 'fetch',
        request: {
            method: getFetchMethod(req, options, Request),
            timestamp: _start,
            url: getFullUrl(req instanceof Request ? req.url : req),
            headers: mergeHeaders(Headers, req.headers, options.headers),
        },
        response: {
            status: (res && res.status) || 0,
            is_custom_error: false,
            timestamp: now(),
        },
        duration: now() - _start,
    };
    var collectBodyOnError = props.collectBodyOnError, extraExtractor = props.extraExtractor;
    if (res) {
        try {
            params.response.headers = mergeHeaders(Headers, res.headers);
            try {
                extraExtractor &&
                    res
                        .clone()
                        .json()
                        .then(function (o) {
                        var extra = extraExtractor(o, params);
                        if (extra) {
                            params.extra = extra;
                            params.response.is_custom_error = true;
                        }
                    })
                        .catch(noop);
            }
            catch (_o) {
                // do nothing
            }
            if (collectBodyOnError && res.status >= 400) {
                params.request.body = (_a = getFetchBody(req, options, Request)) === null || _a === void 0 ? void 0 : _a.toString();
            }
        }
        catch (_c) {
            // do nothing
        }
    }
    else {
        collectBodyOnError && (params.request.body = (_b = getFetchBody(req, options, Request)) === null || _b === void 0 ? void 0 : _b.toString());
    }
    return params;
};
//# sourceMappingURL=fetch.js.map