#ifndef THIRD_PARTY_GBMCWEB_HTTP_HTTP_CLIENT_H_
#define THIRD_PARTY_GBMCWEB_HTTP_HTTP_CLIENT_H_

/*
// Copyright (c) 2020 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include <openssl/err.h>
#include <openssl/ssl.h>  // NOLINT

#include <chrono>  // NOLINT
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>

#include "boost/asio/connect.hpp"  // NOLINT
#include "boost/asio/io_context.hpp"  // NOLINT
#include "boost/asio/ip/address.hpp"  // NOLINT
#include "boost/asio/ip/basic_endpoint.hpp"  // NOLINT
#include "boost/asio/ip/tcp.hpp"  // NOLINT
#include "boost/asio/ssl/context.hpp"  // NOLINT
#include "boost/asio/ssl/error.hpp"  // NOLINT
#include "boost/asio/steady_timer.hpp"  // NOLINT
#include "boost/beast/core/flat_buffer.hpp"  // NOLINT
#include "boost/beast/core/flat_static_buffer.hpp"  // NOLINT
#include "boost/beast/http/message.hpp"  // NOLINT
#include "boost/beast/http/parser.hpp"  // NOLINT
#include "boost/beast/http/read.hpp"  // NOLINT
#include "boost/beast/http/string_body.hpp"  // NOLINT
#include "boost/beast/http/write.hpp"  // NOLINT
#include "boost/beast/ssl/ssl_stream.hpp"  // NOLINT
#include "boost/beast/version.hpp"  // NOLINT
#include "boost/container/devector.hpp"  // NOLINT
#include "boost/system/error_code.hpp"  // NOLINT
#include "http_response.hpp"
#include "logging.hpp"
#include "async_resolve.hpp"
#include "ssl_key_handler.hpp"
#include "managed_store.hpp"

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp"  // NOLINT
#endif

namespace crow {

// With Redfish Aggregation it is assumed we will connect to another instance
// of BMCWeb which can handle 100 simultaneous connections.
constexpr size_t maxPoolSize = 20;
constexpr size_t maxRequestQueueSize = 500;
constexpr unsigned int httpReadBodyLimit = 131072;
constexpr unsigned int httpReadBufferSize = 4096;

enum class ConnState : std::uint8_t {
  initialized,
  resolveInProgress,
  resolveFailed,
  connectInProgress,
  connectFailed,
  connected,
  handshakeInProgress,
  handshakeFailed,
  sendInProgress,
  sendFailed,
  recvInProgress,
  recvFailed,
  idle,
  closed,
  suspended,
  terminated,
  abortConnection,
  sslInitFailed,
  retry
};

static inline boost::system::error_code defaultRetryHandler(
    unsigned int respCode) {
  // As a default, assume 200X is alright
  BMCWEB_LOG_DEBUG << "Using default check for response code validity";
  if ((respCode < 200) || (respCode >= 300)) {
    return boost::system::errc::make_error_code(
        boost::system::errc::result_out_of_range);
  }

  // Return 0 if the response code is valid
  return boost::system::errc::make_error_code(boost::system::errc::success);
};

// We need to allow retry information to be set before a message has been sent
// and a connection pool has been created
struct ConnectionPolicy {
  uint32_t maxRetryAttempts = 5;  // NOLINT

  // the max size of requests in bytes.  0 for unlimited
  boost::optional<uint64_t> requestByteLimit = httpReadBodyLimit;  // NOLINT

  size_t maxConnections = 1;  // NOLINT

  std::string retryPolicyAction = "TerminateAfterRetries";  // NOLINT

  std::chrono::seconds retryIntervalSecs = std::chrono::seconds(0);  // NOLINT
  std::function<boost::system::error_code(unsigned int respCode)>
      invalidResp =  // NOLINT
      defaultRetryHandler;
};

struct PendingRequest {
  boost::beast::http::request<boost::beast::http::string_body> req;
  std::function<void(bool, uint32_t, Response&)> callback;
  PendingRequest(
      boost::beast::http::request<boost::beast::http::string_body>&& reqIn,
      const std::function<void(bool, uint32_t, Response&)>& callbackIn)
      : req(std::move(reqIn)), callback(callbackIn) {}
};

class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo> {
 private:
  ConnState state = ConnState::initialized;      // NOLINT
  uint32_t retryCount = 0;                       // NOLINT
  std::string subId;                             // NOLINT
  std::shared_ptr<ConnectionPolicy> connPolicy;  // NOLINT
  std::string host;                              // NOLINT
  uint16_t port;                                 // NOLINT
  uint32_t connId;                               // NOLINT

  // Data buffers
  boost::beast::http::request<boost::beast::http::string_body> req;  // NOLINT
  std::optional<
      boost::beast::http::response_parser<boost::beast::http::string_body>>
      parser;                                                   // NOLINT
  boost::beast::flat_static_buffer<httpReadBufferSize> buffer;  // NOLINT
  Response res;                                                 // NOLINT

  // Ascync callables
  std::function<void(bool, uint32_t, Response&)> callback;  // NOLINT
  crow::async_resolve::Resolver resolver;                   // NOLINT
  boost::asio::ip::tcp::socket conn;                        // NOLINT
  std::optional<boost::beast::ssl_stream<boost::asio::ip::tcp::socket&>>
      sslConn;  // NOLINT

  boost::asio::steady_timer timer;  // NOLINT

  friend class ConnectionPool;

  void doResolve() {
    state = ConnState::resolveInProgress;
    BMCWEB_LOG_DEBUG << "Trying to resolve: " << host << ":"
                     << std::to_string(port)
                     << ", id: " << std::to_string(connId);

    resolver.asyncResolve(host, port,
                          std::bind_front(&ConnectionInfo::afterResolve, this,
                                          shared_from_this()));
  }

  void afterResolve(
      const std::shared_ptr<ConnectionInfo>& /*self*/,
      const boost::beast::error_code ec,
      const std::vector<boost::asio::ip::tcp::endpoint>& endpointList) {
    if (ec || (endpointList.empty())) {
      BMCWEB_LOG_ERROR << "Resolve failed: " << ec.message();
      state = ConnState::resolveFailed;
      waitAndRetry();
      return;
    }
    BMCWEB_LOG_DEBUG << "Resolved " << host << ":" << std::to_string(port)
                     << ", id: " << std::to_string(connId);
    state = ConnState::connectInProgress;

    BMCWEB_LOG_DEBUG << "Trying to connect to: " << host << ":"
                     << std::to_string(port)
                     << ", id: " << std::to_string(connId);

    timer.expires_after(std::chrono::seconds(30));
    timer.async_wait(std::bind_front(onTimeout, weak_from_this()));

    boost::asio::async_connect(conn, endpointList,
                               std::bind_front(&ConnectionInfo::afterConnect,
                                               this, shared_from_this()));
  }

  void afterConnect(const std::shared_ptr<ConnectionInfo>& /*self*/,
                    boost::beast::error_code ec,
                    const boost::asio::ip::tcp::endpoint& endpoint) {
    // The operation already timed out.  We don't want do continue down
    // this branch
    if (ec && ec == boost::asio::error::operation_aborted) {
      return;
    }

    timer.cancel();
    if (ec) {
      BMCWEB_LOG_ERROR << "Connect " << endpoint.address().to_string() << ":"
                       << std::to_string(endpoint.port())
                       << ", id: " << std::to_string(connId)
                       << " failed: " << ec.message();
      state = ConnState::connectFailed;
      waitAndRetry();
      return;
    }
    BMCWEB_LOG_DEBUG << "Connected to: " << endpoint.address().to_string()
                     << ":" << std::to_string(endpoint.port())
                     << ", id: " << std::to_string(connId);
    if (sslConn) {
      doSslHandshake();
      return;
    }
    state = ConnState::connected;
    sendMessage();
  }

  void doSslHandshake() {
    if (!sslConn) {
      return;
    }
    state = ConnState::handshakeInProgress;
    timer.expires_after(std::chrono::seconds(30));
    timer.async_wait(std::bind_front(onTimeout, weak_from_this()));
    sslConn->async_handshake(boost::asio::ssl::stream_base::client,
                             std::bind_front(&ConnectionInfo::afterSslHandshake,
                                             this, shared_from_this()));
  }

  void afterSslHandshake(const std::shared_ptr<ConnectionInfo>& /*self*/,
                         boost::beast::error_code ec) {
    // The operation already timed out.  We don't want do continue down
    // this branch
    if (ec && ec == boost::asio::error::operation_aborted) {
      return;
    }

    timer.cancel();
    if (ec) {
      BMCWEB_LOG_ERROR << "SSL Handshake failed -"
                       << " id: " << std::to_string(connId)
                       << " error: " << ec.message();
      state = ConnState::handshakeFailed;
      waitAndRetry();
      return;
    }
    BMCWEB_LOG_DEBUG << "SSL Handshake successful -"
                     << " id: " << std::to_string(connId);
    state = ConnState::connected;
    sendMessage();
  }

  void sendMessage() {
    state = ConnState::sendInProgress;

    // Set a timeout on the operation
    timer.expires_after(std::chrono::seconds(30));
    timer.async_wait(std::bind_front(onTimeout, weak_from_this()));

    // Send the HTTP request to the remote host
    if (sslConn) {
      boost::beast::http::async_write(
          *sslConn, req,
          std::bind_front(&ConnectionInfo::afterWrite, this,
                          shared_from_this()));
    } else {
      boost::beast::http::async_write(
          conn, req,
          std::bind_front(&ConnectionInfo::afterWrite, this,
                          shared_from_this()));
    }
  }

  void afterWrite(const std::shared_ptr<ConnectionInfo>& /*self*/,
                  const boost::beast::error_code& ec, size_t bytesTransferred) {
    // The operation already timed out.  We don't want do continue down
    // this branch
    if (ec && ec == boost::asio::error::operation_aborted) {
      return;
    }

    timer.cancel();
    if (ec) {
      BMCWEB_LOG_ERROR << "sendMessage() failed: " << ec.message();
      state = ConnState::sendFailed;
      waitAndRetry();
      return;
    }
    BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: " << bytesTransferred;

    recvMessage();
  }

  void recvMessage() {
    state = ConnState::recvInProgress;

    parser.emplace(std::piecewise_construct, std::make_tuple());

    parser->body_limit(connPolicy->requestByteLimit);

    timer.expires_after(std::chrono::seconds(30));
    timer.async_wait(std::bind_front(onTimeout, weak_from_this()));

    // Receive the HTTP response
    if (sslConn) {
      boost::beast::http::async_read(*sslConn, buffer, *parser,
                                     std::bind_front(&ConnectionInfo::afterRead,
                                                     this, shared_from_this()));
    } else {
      boost::beast::http::async_read(conn, buffer, *parser,
                                     std::bind_front(&ConnectionInfo::afterRead,
                                                     this, shared_from_this()));
    }
  }

  void afterRead(const std::shared_ptr<ConnectionInfo>& /*self*/,
                 const boost::beast::error_code& ec,
                 const std::size_t& bytesTransferred) {
    // The operation already timed out.  We don't want do continue down
    // this branch
    if (ec && ec == boost::asio::error::operation_aborted) {
      return;
    }

    timer.cancel();
    if (ec && ec != boost::asio::ssl::error::stream_truncated) {
      BMCWEB_LOG_ERROR << "recvMessage() failed: " << ec.message();
      state = ConnState::recvFailed;
      waitAndRetry();
      return;
    }
    BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: " << bytesTransferred;
    BMCWEB_LOG_DEBUG << "recvMessage() data: " << parser->get().body();

    unsigned int resp_code = parser->get().result_int();
    BMCWEB_LOG_DEBUG << "recvMessage() Header Response Code: " << resp_code;

    // Make sure the received response code is valid as defined by
    // the associated retry policy
    if (connPolicy->invalidResp(resp_code)) {
      // The listener failed to receive the Sent-Event
      BMCWEB_LOG_ERROR << "recvMessage() Listener Failed to "
                          "receive Sent-Event. Header Response Code: "
                       << resp_code;
      state = ConnState::recvFailed;
      waitAndRetry();
      return;
    }

    // Send is successful
    // Reset the counter just in case this was after retrying
    retryCount = 0;

    // Keep the connection alive if server supports it
    // Else close the connection
    BMCWEB_LOG_DEBUG << "recvMessage() keepalive : " << parser->keep_alive();

    // Copy the response into a Response object so that it can be
    // processed by the callback function.
    res.stringResponse = parser->release();
    callback(parser->keep_alive(), connId, res);
    res.clear();
  }

  static void onTimeout(const std::weak_ptr<ConnectionInfo>& weakSelf,
                        const boost::system::error_code& ec) {
    if (ec == boost::asio::error::operation_aborted) {
      BMCWEB_LOG_DEBUG << "async_wait failed since the operation is aborted";
      return;
    }
    if (ec) {
      BMCWEB_LOG_ERROR << "async_wait failed: " << ec.message();
      // If the timer fails, we need to close the socket anyway, same as
      // if it expired.
    }
    std::shared_ptr<ConnectionInfo> self = weakSelf.lock();
    if (self == nullptr) {
      return;
    }
    self->waitAndRetry();
  }

  void waitAndRetry() {
    if ((retryCount >= connPolicy->maxRetryAttempts) ||
        (state == ConnState::sslInitFailed)) {
      BMCWEB_LOG_ERROR << "Maximum number of retries reached.";
      BMCWEB_LOG_DEBUG << "Retry policy: " << connPolicy->retryPolicyAction;

      if (connPolicy->retryPolicyAction == "TerminateAfterRetries") {
        // TODO: delete subscription
        state = ConnState::terminated;
      }
      if (connPolicy->retryPolicyAction == "SuspendRetries") {
        state = ConnState::suspended;
      }

      // We want to return a 502 to indicate there was an error with
      // the external server
      res.result(boost::beast::http::status::bad_gateway);
      callback(false, connId, res);
      res.clear();

      // Reset the retrycount to zero so that client can try connecting
      // again if needed
      retryCount = 0;
      return;
    }

    retryCount++;

    BMCWEB_LOG_DEBUG << "Attempt retry after "
                     << std::to_string(connPolicy->retryIntervalSecs.count())
                     << " seconds. RetryCount = " << retryCount;
    timer.expires_after(connPolicy->retryIntervalSecs);
    timer.async_wait(std::bind_front(&ConnectionInfo::onTimerDone, this,
                                     shared_from_this()));
  }

  void onTimerDone(const std::shared_ptr<ConnectionInfo>& /*self*/,
                   const boost::system::error_code& ec) {
    if (ec == boost::asio::error::operation_aborted) {
      BMCWEB_LOG_DEBUG << "async_wait failed since the operation is aborted"
                       << ec.message();
    } else if (ec) {
      BMCWEB_LOG_ERROR << "async_wait failed: " << ec.message();
      // Ignore the error and continue the retry loop to attempt
      // sending the event as per the retry policy
    }

    // Let's close the connection and restart from resolve.
    doClose(true);
  }

  void shutdownConn(bool retry) {
    boost::beast::error_code ec;
    // NOLINTNEXTLINE(bugprone-unused-return-value)
    conn.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
    conn.close();

    // not_connected happens sometimes so don't bother reporting it.
    if (ec && ec != boost::beast::errc::not_connected) {
      BMCWEB_LOG_ERROR << host << ":" << std::to_string(port)
                       << ", id: " << std::to_string(connId)
                       << " shutdown failed: " << ec.message();
    } else {
      BMCWEB_LOG_DEBUG << host << ":" << std::to_string(port)
                       << ", id: " << std::to_string(connId)
                       << " closed gracefully";
    }

    if (retry) {
      // Now let's try to resend the data
      state = ConnState::retry;
      doResolve();
    } else {
      state = ConnState::closed;
    }
  }

  void doClose(bool retry = false) {
    if (!sslConn) {
      shutdownConn(retry);
      return;
    }

    sslConn->async_shutdown(std::bind_front(&ConnectionInfo::afterSslShutdown,
                                            this, shared_from_this(), retry));
  }

  void afterSslShutdown(const std::shared_ptr<ConnectionInfo>& /*self*/,
                        bool retry, const boost::system::error_code& ec) {
    if (ec) {
      BMCWEB_LOG_ERROR << host << ":" << std::to_string(port)
                       << ", id: " << std::to_string(connId)
                       << " shutdown failed: " << ec.message();
    } else {
      BMCWEB_LOG_DEBUG << host << ":" << std::to_string(port)
                       << ", id: " << std::to_string(connId)
                       << " closed gracefully";
    }
    shutdownConn(retry);
  }

  void setCipherSuiteTLSext() {
    if (!sslConn) {
      return;
    }

#ifdef GOOGLE3_GBMCWEB_BUILD
    if (SSL_set_tlsext_host_name(sslConn->native_handle(), host.c_str()) == 0)
#else
    // NOTE: The SSL_set_tlsext_host_name is defined in tlsv1.h header
    // file but its having old style casting (name is cast to void*).
    // Since bmcweb compiler treats all old-style-cast as error, its
    // causing the build failure. So replaced the same macro inline and
    // did corrected the code by doing static_cast to viod*. This has to
    // be fixed in openssl library in long run. Set SNI Hostname (many
    // hosts need this to handshake successfully)
    if (SSL_ctrl(sslConn->native_handle(), SSL_CTRL_SET_TLSEXT_HOSTNAME,
                 TLSEXT_NAMETYPE_host_name,
                 static_cast<void*>(&host.front())) == 0)
#endif
    {
      boost::beast::error_code ec{static_cast<int>(::ERR_get_error()),
                                  boost::asio::error::get_ssl_category()};

      BMCWEB_LOG_ERROR << "SSL_set_tlsext_host_name " << host << ":" << port
                       << ", id: " << std::to_string(connId)
                       << " failed: " << ec.message();
      // Set state as sslInit failed so that we close the connection
      // and take appropriate action as per retry configuration.
      state = ConnState::sslInitFailed;
      waitAndRetry();
      return;
    }
  }

 public:
  explicit ConnectionInfo(boost::asio::io_context& iocIn,
                          const std::string& idIn,
                          const std::shared_ptr<ConnectionPolicy>& connPolicyIn,
                          const std::string& destIPIn, uint16_t destPortIn,
                          bool useSSL, unsigned int connIdIn)
      : subId(idIn),
        connPolicy(connPolicyIn),
        host(destIPIn),
        port(destPortIn),
        connId(connIdIn),
        conn(iocIn),
        timer(iocIn) {
    if (useSSL) {
      std::optional<boost::asio::ssl::context> ssl_ctx =
          ensuressl::getSSLClientContext();

      if (!ssl_ctx) {
        BMCWEB_LOG_ERROR << "prepareSSLContext failed - " << host << ":" << port
                         << ", id: " << std::to_string(connId);
        // Don't retry if failure occurs while preparing SSL context
        // such as certificate is invalid or set cipher failure or set
        // host name failure etc... Setting conn state to sslInitFailed
        // and connection state will be transitioned to next state
        // depending on retry policy set by subscription.
        state = ConnState::sslInitFailed;
        waitAndRetry();
        return;
      }
      sslConn.emplace(conn, *ssl_ctx);
      setCipherSuiteTLSext();
    }
  }
};

class ConnectionPool : public std::enable_shared_from_this<ConnectionPool> {
 private:
  boost::asio::io_context& ioc;                              // NOLINT
  std::string id;                                            // NOLINT
  std::shared_ptr<ConnectionPolicy> connPolicy;              // NOLINT
  std::string destIP;                                        // NOLINT
  uint16_t destPort;                                         // NOLINT
  bool useSSL;                                               // NOLINT
  std::vector<std::shared_ptr<ConnectionInfo>> connections;  // NOLINT
  boost::container::devector<PendingRequest> requestQueue;   // NOLINT

  friend class HttpClient;

  // Configure a connections's request, callback, and retry info in
  // preparation to begin sending the request
  void setConnProps(ConnectionInfo& conn) {
    if (requestQueue.empty()) {
      BMCWEB_LOG_ERROR << "setConnProps() should not have been called when "
                          "requestQueue is empty";
      return;
    }

    auto next_req = requestQueue.front();
    conn.req = std::move(next_req.req);
    conn.callback = std::move(next_req.callback);

    BMCWEB_LOG_DEBUG << "Setting properties for connection " << conn.host << ":"
                     << std::to_string(conn.port)
                     << ", id: " << std::to_string(conn.connId);

    // We can remove the request from the queue at this point
    requestQueue.pop_front();
  }

  // Gets called as part of callback after request is sent
  // Reuses the connection if there are any requests waiting to be sent
  // Otherwise closes the connection if it is not a keep-alive
  void sendNext(bool keepAlive, uint32_t connId) {
    auto conn = connections[connId];

    // Allow the connection's handler to be deleted
    // This is needed because of Redfish Aggregation passing an
    // AsyncResponse shared_ptr to this callback
    conn->callback = nullptr;

    // Reuse the connection to send the next request in the queue
    if (!requestQueue.empty()) {
      BMCWEB_LOG_DEBUG << std::to_string(requestQueue.size())
                       << " requests remaining in queue for " << destIP << ":"
                       << std::to_string(destPort) << ", reusing connnection "
                       << std::to_string(connId);

      setConnProps(*conn);

      if (keepAlive) {
        conn->sendMessage();
      } else {
        // Server is not keep-alive enabled so we need to close the
        // connection and then start over from resolve
        conn->doClose();
        conn->doResolve();
      }
      return;
    }

    // No more messages to send so close the connection if necessary
    if (keepAlive) {
      conn->state = ConnState::idle;
    } else {
      // Abort the connection since server is not keep-alive enabled
      conn->state = ConnState::abortConnection;
      conn->doClose();
    }
  }

  void sendData(std::string& data, const std::string& destUri,
                const boost::beast::http::fields& httpHeader,
                const boost::beast::http::verb verb,
                const std::function<void(Response&)>& resHandler) {
    // Construct the request to be sent
    boost::beast::http::request<boost::beast::http::string_body> this_req(
        verb, destUri, 11, "", httpHeader);
    this_req.set(boost::beast::http::field::host, destIP);
    this_req.keep_alive(true);
    this_req.body() = std::move(data);
    this_req.prepare_payload();
    auto cb = std::bind_front(&ConnectionPool::afterSendData, weak_from_this(),
                              resHandler);
    // Reuse an existing connection if one is available
    for (unsigned int i = 0; i < connections.size(); i++) {
      auto conn = connections[i];
      if ((conn->state == ConnState::idle) ||
          (conn->state == ConnState::initialized) ||
          (conn->state == ConnState::closed)) {
        conn->req = std::move(this_req);
        conn->callback = std::move(cb);
        std::string common_msg = std::to_string(i) + " from pool " + destIP +
                                 ":" + std::to_string(destPort);

        if (conn->state == ConnState::idle) {
          BMCWEB_LOG_DEBUG << "Grabbing idle connection " << common_msg;
          conn->sendMessage();
        } else {
          BMCWEB_LOG_DEBUG << "Reusing existing connection " << common_msg;
          conn->doResolve();
        }
        return;
      }
    }

    // All connections in use so create a new connection or add request to
    // the queue
    if (connections.size() < connPolicy->maxConnections) {
      BMCWEB_LOG_DEBUG << "Adding new connection to pool " << destIP << ":"
                       << std::to_string(destPort);
      auto conn = addConnection();
      conn->req = std::move(this_req);
      conn->callback = std::move(cb);
      conn->doResolve();
    } else if (requestQueue.size() < maxRequestQueueSize) {
      BMCWEB_LOG_ERROR << "Max pool size reached. Adding data to queue.";
      requestQueue.emplace_back(std::move(this_req), std::move(cb));
    } else {
      // If we can't buffer the request then we should let the callback
      // handle a 429 Too Many Requests dummy response
      BMCWEB_LOG_ERROR << destIP << ":" << std::to_string(destPort)
                       << " request queue full.  Dropping request.";
      Response dummy_res;
      dummy_res.result(boost::beast::http::status::too_many_requests);
      resHandler(dummy_res);
    }
  }

  // Callback to be called once the request has been sent
  static void afterSendData(const std::weak_ptr<ConnectionPool>& weakSelf,
                            const std::function<void(Response&)>& resHandler,
                            bool keepAlive, uint32_t connId, Response& res) {
    // Allow provided callback to perform additional processing of the
    // request
    resHandler(res);

    // If requests remain in the queue then we want to reuse this
    // connection to send the next request
    std::shared_ptr<ConnectionPool> self = weakSelf.lock();
    if (!self) {
      BMCWEB_LOG_CRITICAL << self << " Failed to capture connection";
      return;
    }

    self->sendNext(keepAlive, connId);
  }

  std::shared_ptr<ConnectionInfo>& addConnection() {
    unsigned int new_id = static_cast<unsigned int>(connections.size());

    auto& ret = connections.emplace_back(std::make_shared<ConnectionInfo>(
        ioc, id, connPolicy, destIP, destPort, useSSL, new_id));

    BMCWEB_LOG_DEBUG << "Added connection "
                     << std::to_string(connections.size() - 1) << " to pool "
                     << destIP << ":" << std::to_string(destPort);

    return ret;
  }

 public:
  explicit ConnectionPool(boost::asio::io_context& iocIn,
                          const std::string& idIn,
                          const std::shared_ptr<ConnectionPolicy>& connPolicyIn,
                          const std::string& destIPIn, uint16_t destPortIn,
                          bool useSSLIn)
      : ioc(iocIn),
        id(idIn),
        connPolicy(connPolicyIn),
        destIP(destIPIn),
        destPort(destPortIn),
        useSSL(useSSLIn) {
    BMCWEB_LOG_DEBUG << "Initializing connection pool for " << destIP << ":"
                     << std::to_string(destPort);

    // Initialize the pool with a single connection
    addConnection();
  }
};

class HttpClient {
 private:
  std::unordered_map<std::string, std::shared_ptr<ConnectionPool>>
      connectionPools;            // NOLINT
  boost::asio::io_context& ioc =  // NOLINT
      managedStore::GetManagedObjectStore()->GetIoContext();
  std::shared_ptr<ConnectionPolicy> connPolicy;  // NOLINT

  // Used as a dummy callback by sendData() in order to call
  // sendDataWithCallback()
  static void genericResHandler(const Response& res) {
    BMCWEB_LOG_DEBUG << "Response handled with return code: "
                     << std::to_string(res.resultInt());
  }

 public:
  HttpClient() = delete;
  explicit HttpClient(const std::shared_ptr<ConnectionPolicy>& connPolicyIn)
      : connPolicy(connPolicyIn) {}
  HttpClient(const HttpClient&) = delete;
  HttpClient& operator=(const HttpClient&) = delete;
  HttpClient(HttpClient&&) = delete;
  HttpClient& operator=(HttpClient&&) = delete;
  ~HttpClient() = default;

  // Send a request to destIP:destPort where additional processing of the
  // result is not required
  void sendData(std::string& data, const std::string& destIP, uint16_t destPort,
                const std::string& destUri, bool useSSL,
                const boost::beast::http::fields& httpHeader,
                const boost::beast::http::verb verb) {
    const std::function<void(Response&)> cb = genericResHandler;
    sendDataWithCallback(data, destIP, destPort, destUri, useSSL, httpHeader,
                         verb, cb);
  }

  // Send request to destIP:destPort and use the provided callback to
  // handle the response
  void sendDataWithCallback(std::string& data, const std::string& destIP,
                            uint16_t destPort, const std::string& destUri,
                            bool useSSL,
                            const boost::beast::http::fields& httpHeader,
                            const boost::beast::http::verb verb,
                            const std::function<void(Response&)>& resHandler) {
    std::string client_key = useSSL ? "https" : "http";
    client_key += destIP;
    client_key += ":";
    client_key += std::to_string(destPort);
    auto pool = connectionPools.try_emplace(client_key);
    if (pool.first->second == nullptr) {
      pool.first->second = std::make_shared<ConnectionPool>(
          ioc, client_key, connPolicy, destIP, destPort, useSSL);
    }
    // Send the data using either the existing connection pool or the newly
    // created connection pool
    pool.first->second->sendData(data, destUri, httpHeader, verb, resHandler);
  }
};
}  // namespace crow

#endif  // THIRD_PARTY_GBMCWEB_HTTP_HTTP_CLIENT_H_
