"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.sendRequest = sendRequest;
var _public = require("@kbn/es-ui-shared-plugin/public");
var _constants = require("../../../../common/constants");
var _utils = require("../../../lib/utils");
var _es = require("../../../lib/es/es");
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

const {
  collapseLiteralStrings
} = _public.XJson;
const getContentType = response => {
  var _ref;
  return (_ref = response === null || response === void 0 ? void 0 : response.headers.get('Content-Type')) !== null && _ref !== void 0 ? _ref : '';
};
const extractStatusCodeAndText = (response, path) => {
  var _response$headers$get, _response$headers$get2;
  const isKibanaApiRequest = path.startsWith(_constants.KIBANA_API_PREFIX);
  // Kibana API requests don't go through the proxy, so we can use the response status code and text.
  if (isKibanaApiRequest) {
    var _response$status, _response$statusText;
    return {
      statusCode: (_response$status = response === null || response === void 0 ? void 0 : response.status) !== null && _response$status !== void 0 ? _response$status : 500,
      statusText: (_response$statusText = response === null || response === void 0 ? void 0 : response.statusText) !== null && _response$statusText !== void 0 ? _response$statusText : 'error'
    };
  }

  // For ES requests, we need to extract the status code and text from the response
  // headers, due to the way the proxy set up to avoid mirroring the status code which could be 401
  // and trigger a login prompt. See for more details: https://github.com/elastic/kibana/issues/140536
  const statusCode = parseInt((_response$headers$get = response === null || response === void 0 ? void 0 : response.headers.get('x-console-proxy-status-code')) !== null && _response$headers$get !== void 0 ? _response$headers$get : '500', 10);
  const statusText = (_response$headers$get2 = response === null || response === void 0 ? void 0 : response.headers.get('x-console-proxy-status-text')) !== null && _response$headers$get2 !== void 0 ? _response$headers$get2 : 'error';
  return {
    statusCode,
    statusText
  };
};
let CURRENT_REQ_ID = 0;
function sendRequest(args) {
  const requests = args.requests.slice();
  return new Promise((resolve, reject) => {
    const reqId = ++CURRENT_REQ_ID;
    const results = [];
    if (reqId !== CURRENT_REQ_ID) {
      return;
    }
    if (requests.length === 0) {
      return;
    }
    const isMultiRequest = requests.length > 1;
    const sendNextRequest = async () => {
      if (reqId !== CURRENT_REQ_ID) {
        resolve(results);
        return;
      }
      if (requests.length === 0) {
        resolve(results);
        return;
      }
      const req = requests.shift();
      const path = req.url;
      const method = req.method;
      let data = collapseLiteralStrings(req.data.join('\n'));
      if (data) {
        data += '\n';
      } // append a new line for bulk requests.

      const startTime = Date.now();
      try {
        const {
          response,
          body
        } = await (0, _es.send)({
          http: args.http,
          method,
          path,
          data,
          asResponse: true
        });
        const {
          statusCode,
          statusText
        } = extractStatusCodeAndText(response, path);
        if (reqId !== CURRENT_REQ_ID) {
          // Skip if previous request is not resolved yet. This can happen when issuing multiple requests at the same time and with slow networks
          return;
        }
        if (response) {
          let value;
          // check if object is ArrayBuffer
          if (body instanceof ArrayBuffer) {
            value = body;
          } else {
            value = typeof body === 'string' ? body : JSON.stringify(body, null, 2);
          }
          const warnings = response.headers.get('warning');
          if (warnings) {
            const warningMessages = (0, _utils.extractWarningMessages)(warnings);
            value = warningMessages.join('\n') + '\n' + value;
          }
          if (isMultiRequest) {
            value = `# ${req.method} ${req.url} ${statusCode} ${statusText}\n${value}`;
          }
          results.push({
            response: {
              timeMs: Date.now() - startTime,
              statusCode,
              statusText,
              contentType: getContentType(response),
              value
            },
            request: {
              data,
              method,
              path
            }
          });

          // single request terminate via sendNextRequest as well
          await sendNextRequest();
        }
      } catch (error) {
        let value;
        const {
          response,
          body
        } = error;
        const {
          statusCode,
          statusText
        } = extractStatusCodeAndText(response, path);
        if (body) {
          value = JSON.stringify(body, null, 2);
        } else {
          value = 'Request failed to get to the server (status code: ' + statusCode + ')';
        }
        if (isMultiRequest) {
          value = `# ${req.method} ${req.url} ${statusCode} ${statusText}\n${value}`;
        }
        const result = {
          response: {
            value,
            contentType: getContentType(response),
            timeMs: Date.now() - startTime,
            statusCode,
            statusText
          },
          request: {
            data,
            method,
            path
          }
        };

        // Reject on unknown errors
        if (!response) {
          reject(result);
        }

        // Add error to the list of results
        results.push(result);
        await sendNextRequest();
      }
    };
    sendNextRequest();
  });
}