#include "query.hpp"

#include <algorithm>
#include <array>
#include <cctype>
#include <charconv>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iterator>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <system_error>  // NOLINT
#include <unordered_set>
#include <utility>
#include <vector>

#include "absl/synchronization/mutex.h"
#include "boost/beast/http/verb.hpp"  // NOLINT
#include "boost/system/error_code.hpp"  // NOLINT
#include "boost/url/params_view.hpp"  // NOLINT
#include "boost/url/url_view.hpp"  // NOLINT
#include "bmcweb_config.h"
#include "app.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "async_resp.hpp"
#include "str_utility.hpp"
#include "error_messages.hpp"
#include "redfish_aggregator.hpp"  // NOLINT
#include <nlohmann/json.hpp>

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

namespace redfish {

namespace query_param {

// Validates the property in the $select parameter. Every character is among
// [a-zA-Z0-9#@_.] (taken from Redfish spec, section 9.6 Properties)
bool isSelectedPropertyAllowed(std::string_view property) {
  // These a magic number, but with it it's less likely that this code
  // introduces CVE; e.g., too large properties crash the service.
  constexpr int maxPropertyLength = 60;
  if (property.empty() || property.size() > maxPropertyLength) {
    return false;
  }
  for (char ch : property) {
    if (std::isalnum(static_cast<unsigned char>(ch)) == 0 && ch != '#' &&
        ch != '@' && ch != '.') {
      return false;
    }
  }
  return true;
}

bool SelectTrie::insertNode(std::string_view nestedProperty) {
  if (nestedProperty.empty()) {
    return false;
  }
  SelectTrieNode* currNode = &root;
  size_t index = nestedProperty.find_first_of('/');
  while (!nestedProperty.empty()) {
    std::string_view property = nestedProperty.substr(0, index);
    if (!isSelectedPropertyAllowed(property)) {
      return false;
    }
    currNode = currNode->emplace(property);
    if (index == std::string::npos) {
      break;
    }
    nestedProperty.remove_prefix(index + 1);
    index = nestedProperty.find_first_of('/');
  }
  currNode->setToSelected();
  return true;
}

// Delegates query parameters according to the given |queryCapabilities|
// This function doesn't check query parameter conflicts since the parse
// function will take care of it.
// Returns a delegated query object which can be used by individual resource
// handlers so that handlers don't need to query again.
Query delegate(const QueryCapabilities& queryCapabilities, Query& query,
               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  Query delegated;
  // delegate only
  if (query.isOnly && queryCapabilities.canDelegateOnly) {
    delegated.isOnly = true;
    query.isOnly = false;
  }
  // delegate expand as much as we can
  if (query.expandType != ExpandType::None) {
    delegated.expandType = query.expandType;
    if (query.expandLevel <= queryCapabilities.canDelegateExpandLevel) {
      query.expandType = ExpandType::None;
      delegated.expandLevel = query.expandLevel;
      query.expandLevel = 0;
    } else {
      // We actually dont need to subtract query.expandType here because
      // When we expand navigation references, we actually start from
      // the root of the entire response instead of the delegated level
      delegated.expandLevel = queryCapabilities.canDelegateExpandLevel;
    }
    asyncResp->delegatedExpandLevel = delegated.expandLevel;
  }

  // delegate top
  if (query.top && queryCapabilities.canDelegateTop) {
    delegated.top = query.top;
    query.top = std::nullopt;
  }

  // delegate skip
  if (query.skip && queryCapabilities.canDelegateSkip) {
    delegated.skip = query.skip;
    query.skip = 0;
  }

  // delegate select
  if (!query.selectTrie.root.empty() && queryCapabilities.canDelegateSelect) {
    delegated.selectTrie = std::move(query.selectTrie);
    query.selectTrie.root.clear();
  }

  // delegate filter
  if (!query.filter.empty() && queryCapabilities.canDelegateFilter) {
    delegated.filter = query.filter;
    query.filter = "";
  }
  return delegated;
}

bool getExpandType(std::string_view value, Query& query) {
  if (value.empty()) {
    return false;
  }
  switch (value[0]) {
    case '*':
      query.expandType = ExpandType::Both;
      break;
    case '.':
      query.expandType = ExpandType::NotLinks;
      break;
    case '~':
      query.expandType = ExpandType::Links;
      break;
    default:
      return false;

      break;
  }
  value.remove_prefix(1);
  if (value.empty()) {
    query.expandLevel = 1;
    return true;
  }
  constexpr std::string_view levels = "($levels=";
  if (!value.starts_with(levels)) {
    return false;
  }
  value.remove_prefix(levels.size());

  auto it = std::from_chars(value.data(), value.data() + value.size(),
                            query.expandLevel);
  if (it.ec != std::errc()) {
    return false;
  }
  value.remove_prefix(static_cast<size_t>(it.ptr - value.data()));
  return value == ")";
}

enum class QueryError : std::uint8_t {
  Ok,
  OutOfRange,
  ValueFormat,
};

QueryError getNumericParam(std::string_view value, size_t& param) {
  std::from_chars_result r =
      std::from_chars(value.data(), value.data() + value.size(), param);

  // If the number wasn't representable in the type, it's out of range
  if (r.ec == std::errc::result_out_of_range) {
    return QueryError::OutOfRange;
  }
  // All other errors are value format
  if (r.ec != std::errc()) {
    return QueryError::ValueFormat;
  }
  return QueryError::Ok;
}

QueryError getSkipParam(std::string_view value, Query& query) {
  return getNumericParam(value, query.skip.emplace());
}

QueryError getTopParam(std::string_view value, Query& query) {
  QueryError ret = getNumericParam(value, query.top.emplace());
  if (ret != QueryError::Ok) {
    return ret;
  }

  // Range check for sanity.
  if (query.top > Query::maxTop) {
    return QueryError::OutOfRange;
  }

  return QueryError::Ok;
}

// Parses and validates the $select parameter.
// As per OData URL Conventions and Redfish Spec, the $select values shall be
// comma separated Resource Path
// Ref:
// 1. https://datatracker.ietf.org/doc/html/rfc3986#section-3.3
// 2.
// https://docs.oasis-open.org/odata/odata/v4.01/os/abnf/odata-abnf-construction-rules.txt
bool getSelectParam(std::string_view value, Query& query) {
  std::vector<std::string> properties;
  bmcweb::split(properties, value, ',');
  if (properties.empty()) {
    return false;
  }
  // These a magic number, but with it it's less likely that this code
  // introduces CVE; e.g., too large properties crash the service.
  constexpr int maxNumProperties = 10;
  if (properties.size() > maxNumProperties) {
    return false;
  }
  for (const auto& property : properties) {
    if (!query.selectTrie.insertNode(property)) {
      return false;
    }
  }
  return true;
}

bool getFilterParam(std::string_view value, Query& query) {
  if (value.empty()) {
    return false;
  }

  query.filter = std::string(value);
  return true;
}

std::optional<Query> parseParameters(boost::urls::params_view urlParams,
                                     crow::Response& res) {
  Query ret;
  for (const boost::urls::params_view::value_type& it : urlParams) {
    if (it.key == "only") {
      if (!it.value.empty()) {
        messages::queryParameterValueFormatError(res, it.value, it.key);
        return std::nullopt;
      }
      ret.isOnly = true;
    } else if (it.key == "$expand" && bmcwebInsecureEnableQueryParams) {
      if (!getExpandType(it.value, ret)) {
        messages::queryParameterValueFormatError(res, it.value, it.key);
        return std::nullopt;
      }
    } else if (it.key == "$top") {
      QueryError topRet = getTopParam(it.value, ret);
      if (topRet == QueryError::ValueFormat) {
        messages::queryParameterValueFormatError(res, it.value, it.key);
        return std::nullopt;
      }
      if (topRet == QueryError::OutOfRange) {
        messages::queryParameterOutOfRange(
            res, it.value, "$top", "0-" + std::to_string(Query::maxTop));
        return std::nullopt;
      }
    } else if (it.key == "$skip") {
      QueryError topRet = getSkipParam(it.value, ret);
      if (topRet == QueryError::ValueFormat) {
        messages::queryParameterValueFormatError(res, it.value, it.key);
        return std::nullopt;
      }
      if (topRet == QueryError::OutOfRange) {
        messages::queryParameterOutOfRange(
            res, it.value, it.key,
            "0-" + std::to_string(std::numeric_limits<size_t>::max()));
        return std::nullopt;
      }
    } else if (it.key == "$select") {
      if (!getSelectParam(it.value, ret)) {
        messages::queryParameterValueFormatError(res, it.value, it.key);
        return std::nullopt;
      }
    } else if (it.key == "$filter") {
      if (!getFilterParam(it.value, ret)) {
        messages::queryParameterValueFormatError(res, it.value, it.key);
        return std::nullopt;
      }
    } else {
      // Intentionally ignore other errors Redfish spec, 7.3.1
      if (it.key.starts_with("$")) {
        // Services shall return... The HTTP 501 Not Implemented
        // status code for any unsupported query parameters that
        // start with $ .
        messages::queryParameterValueFormatError(res, it.value, it.key);
        res.result(boost::beast::http::status::not_implemented);
        return std::nullopt;
      }
      // "Shall ignore unknown or unsupported query parameters that do
      // not begin with $ ."
    }
  }

  if (ret.expandType != ExpandType::None && !ret.selectTrie.root.empty()) {
    messages::queryCombinationInvalid(res);
    return std::nullopt;
  }

  return ret;
}

bool processOnly(
    crow::App& app, crow::Response& res,
    std::function<void(crow::Response&)>& completionHandler,
    const std::shared_ptr<boost::asio::io_context::strand>& strand) {
  BMCWEB_LOG_DEBUG << "Processing only query param";
  auto itMembers = res.jsonValue.find("Members");
  if (itMembers == res.jsonValue.end()) {
    messages::queryNotSupportedOnResource(res);
    completionHandler(res);
    return false;
  }
  auto itMemBegin = itMembers->begin();
  if (itMemBegin == itMembers->end() || itMembers->size() != 1) {
    BMCWEB_LOG_DEBUG << "Members contains " << itMembers->size()
                     << " element, returning full collection.";
    completionHandler(res);
    return false;
  }

  auto itUrl = itMemBegin->find("@odata.id");
  if (itUrl == itMemBegin->end()) {
    BMCWEB_LOG_DEBUG << "No found odata.id";
    messages::internalError(res);
    completionHandler(res);
    return false;
  }
  const std::string* url = itUrl->get_ptr<const std::string*>();
  if (url == nullptr) {
    BMCWEB_LOG_DEBUG << "@odata.id wasn't a string????";
    messages::internalError(res);
    completionHandler(res);
    return false;
  }
  // TODO(Ed) copy request headers?
  // newReq.session = req.session;
  std::error_code ec;
  crow::Request newReq({boost::beast::http::verb::get, *url, 11}, ec);
  if (ec) {
    messages::internalError(res);
    completionHandler(res);
    return false;
  }

  auto asyncResp = std::make_shared<bmcweb::AsyncResp>(strand);
  BMCWEB_LOG_DEBUG << "setting completion handler on " << &asyncResp->res;
  asyncResp->res.setCompleteRequestHandler(std::move(completionHandler));
  asyncResp->res.setIsAliveHelper(res.releaseIsAliveHelper());
  app.handle(newReq, asyncResp);
  return true;
}

// Walks a json object looking for Redfish NavigationReference entries that
// might need resolved.  It recursively walks the jsonResponse object, looking
// for links at every level, and returns a list (out) of locations within the
// tree that need to be expanded.  The current json pointer location p is passed
// in to reference the current node that's being expanded, so it can be combined
// with the keys from the jsonResponse object
void findNavigationReferencesRecursive(ExpandType eType,
                                       nlohmann::json& jsonResponse,
                                       const nlohmann::json::json_pointer& p,
                                       int depth, bool inLinks,
                                       std::vector<ExpandNode>& out) {
  // If no expand is needed, return early
  if (eType == ExpandType::None) {
    return;
  }

  nlohmann::json::array_t* array =
      jsonResponse.get_ptr<nlohmann::json::array_t*>();
  if (array != nullptr) {
    size_t index = 0;
    // For arrays, walk every element in the array
    for (auto& element : *array) {
      nlohmann::json::json_pointer newPtr = p / index;
      BMCWEB_LOG_DEBUG << "Traversing response at " << newPtr.to_string();
      findNavigationReferencesRecursive(eType, element, newPtr, depth, inLinks,
                                        out);
      index++;
    }
  }
  nlohmann::json::object_t* obj =
      jsonResponse.get_ptr<nlohmann::json::object_t*>();
  if (obj == nullptr) {
    return;
  }
  // Navigation References only ever have a single element
  if (obj->size() == 1) {
    if (obj->begin()->first == "@odata.id") {
      const std::string* uri =
          obj->begin()->second.get_ptr<const std::string*>();
      if (uri != nullptr) {
        BMCWEB_LOG_DEBUG << "Found " << *uri << " at " << p.to_string();
        out.push_back({p, *uri});
        return;
      }
    }
  }

  int newDepth = depth;
  auto odataId = obj->find("@odata.id");
  if (odataId != obj->end()) {
    // The Redfish spec requires all resources to include the resource
    // identifier.  If the object has multiple elements and one of them is
    // "@odata.id" then that means we have entered a new level / expanded
    // resource.  We need to stop traversing if we're already at the desired
    // depth
    if ((obj->size() > 1) && (depth == 0)) {
      return;
    }
    newDepth--;
  }

  // Loop the object and look for links
  for (auto& element : *obj) {
    bool localInLinks = inLinks;
    if (!localInLinks) {
      // Check if this is a links node
      localInLinks = element.first == "Links";
    }
    // Only traverse the parts of the tree the user asked for
    // Per section 7.3 of the redfish specification
    if (localInLinks && eType == ExpandType::NotLinks) {
      continue;
    }
    if (!localInLinks && eType == ExpandType::Links) {
      continue;
    }
    nlohmann::json::json_pointer newPtr = p / element.first;
    BMCWEB_LOG_DEBUG << "Traversing response at " << newPtr;

    findNavigationReferencesRecursive(eType, element.second, newPtr, newDepth,
                                      localInLinks, out);
  }
}

// TODO: When aggregation is enabled and we receive a partially expanded
// response we may need need additional handling when the original URI was
// up tree from a top level collection.
// Isn't a concern until https://gerrit.openbmc.org/c/openbmc/bmcweb/+/60556
// lands.  May want to avoid forwarding query params when request is uptree from
// a top level collection.
std::vector<ExpandNode> findNavigationReferences(ExpandType eType, int depth,
                                                 nlohmann::json& jsonResponse) {
  std::vector<ExpandNode> ret;
  const nlohmann::json::json_pointer root = nlohmann::json::json_pointer("");
  findNavigationReferencesRecursive(eType, jsonResponse, root, depth, false,
                                    ret);
  return ret;
}

// Formats a query parameter string for the sub-query.
// Returns std::nullopt on failures.
// This function shall handle $select when it is added.
// There is no need to handle parameters that's not campatible with $expand,
// e.g., $only, since this function will only be called in side $expand handlers
std::optional<std::string> formatQueryForExpand(const Query& query) {
  // query.expandLevel<=1: no need to do subqueries
  if (query.expandLevel <= 1) {
    return "";
  }
  std::string str = "?$expand=";
  bool queryTypeExpected = false;
  switch (query.expandType) {
    case ExpandType::None:
      return "";
    case ExpandType::Links:
      queryTypeExpected = true;
      str += '~';
      break;
    case ExpandType::NotLinks:
      queryTypeExpected = true;
      str += '.';
      break;
    case ExpandType::Both:
      queryTypeExpected = true;
      str += '*';
      break;
  }
  if (!queryTypeExpected) {
    return std::nullopt;
  }
  str += "($levels=";
  str += std::to_string(query.expandLevel - 1);
  str += ')';
  return str;
}

// Propogates the worst error code to the final response.
// The order of error code is (from high to low)
// 500 Internal Server Error
// 511 Network Authentication Required
// 510 Not Extended
// 508 Loop Detected
// 507 Insufficient Storage
// 506 Variant Also Negotiates
// 505 HTTP Version Not Supported
// 504 Gateway Timeout
// 503 Service Unavailable
// 502 Bad Gateway
// 501 Not Implemented
// 401 Unauthorized
// 451 - 409 Error codes (not listed explictly)
// 408 Request Timeout
// 407 Proxy Authentication Required
// 406 Not Acceptable
// 405 Method Not Allowed
// 404 Not Found
// 403 Forbidden
// 402 Payment Required
// 400 Bad Request
unsigned propogateErrorCode(unsigned finalCode, unsigned subResponseCode) {
  // We keep a explicit list for error codes that this project often uses
  // Higer priority codes are in lower indexes
  constexpr std::array<unsigned, 13> orderedCodes = {
      500, 507, 503, 502, 501, 401, 412, 409, 406, 405, 404, 403, 400};
  size_t finalCodeIndex = std::numeric_limits<size_t>::max();
  size_t subResponseCodeIndex = std::numeric_limits<size_t>::max();
  for (size_t i = 0; i < orderedCodes.size(); ++i) {
    if (orderedCodes[i] == finalCode) {
      finalCodeIndex = i;
    }
    if (orderedCodes[i] == subResponseCode) {
      subResponseCodeIndex = i;
    }
  }
  if (finalCodeIndex != std::numeric_limits<size_t>::max() &&
      subResponseCodeIndex != std::numeric_limits<size_t>::max()) {
    return finalCodeIndex <= subResponseCodeIndex ? finalCode : subResponseCode;
  }
  if (subResponseCode == 500 || finalCode == 500) {
    return 500;
  }
  if (subResponseCode > 500 || finalCode > 500) {
    return std::max(finalCode, subResponseCode);
  }
  if (subResponseCode == 401) {
    return subResponseCode;
  }
  return std::max(finalCode, subResponseCode);
}

// Propogates all error messages into |finalResponse|
void propogateError(crow::Response& finalResponse,
                    crow::Response& subResponse) {
  // no errors
  if (subResponse.resultInt() >= 200 && subResponse.resultInt() < 400) {
    return;
  }
  messages::moveErrorsToErrorJson(finalResponse.jsonValue,
                                  subResponse.jsonValue);
  finalResponse.result(
      propogateErrorCode(finalResponse.resultInt(), subResponse.resultInt()));
}

class MultiAsyncResp : public std::enable_shared_from_this<MultiAsyncResp> {
 public:
  // This object takes a single asyncResp object as the "final" one, then
  // allows callers to attach sub-responses within the json tree that need
  // to be executed and filled into their appropriate locations.  This
  // class manages the final "merge" of the json resources.
  MultiAsyncResp(crow::App& appIn,
                 std::shared_ptr<bmcweb::AsyncResp> finalResIn,
                 const crow::Request& request)
      : app(appIn),
        finalRes(std::move(finalResIn)),
        fromGrpc(request.fromGrpc),
        with_trust_bundle(request.with_trust_bundle),
        peer_authenticated(request.peer_authenticated),
        peer_privileges(request.peer_privileges) {}

  void addAwaitingResponse(
      const std::shared_ptr<bmcweb::AsyncResp>& res,
      const nlohmann::json::json_pointer& finalExpandLocation) {
    res->res.setCompleteRequestHandler(std::bind_front(
        placeResultStatic, shared_from_this(), finalExpandLocation));
  }

  void placeResult(const nlohmann::json::json_pointer& locationToPlace,
                   crow::Response& res) {
    propogateError(finalRes->res, res);
    if (!res.jsonValue.is_object() || res.jsonValue.empty()) {
      return;
    }
    nlohmann::json& finalObj = finalRes->res.jsonValue[locationToPlace];
    finalObj = std::move(res.jsonValue);
    BMCWEB_LOG_DEBUG << "placeResult for " << locationToPlace;
  }

  // Handles the very first level of Expand, and starts a chain of sub-queries
  // for deeper levels.
  void startQuery(const Query& query) {
    std::vector<ExpandNode> nodes = findNavigationReferences(
        query.expandType, query.expandLevel, finalRes->res.jsonValue);
    BMCWEB_LOG_DEBUG << nodes.size() << " nodes to traverse";
    const std::optional<std::string> queryStr = formatQueryForExpand(query);
    if (!queryStr) {
      messages::internalError(finalRes->res);
      return;
    }
    for (const ExpandNode& node : nodes) {
      const std::string subQuery = node.uri + *queryStr;
      BMCWEB_LOG_DEBUG << "URL of subquery:  " << subQuery;
      std::error_code ec;
      crow::Request newReq({boost::beast::http::verb::get, subQuery, 11}, ec);
      if (ec) {
        messages::internalError(finalRes->res);
        return;
      }

      newReq.fromGrpc = fromGrpc;
      newReq.with_trust_bundle = with_trust_bundle;
      newReq.peer_authenticated = peer_authenticated;
      newReq.peer_privileges = peer_privileges;

      auto asyncResp = std::make_shared<bmcweb::AsyncResp>(finalRes->strand_);
      BMCWEB_LOG_DEBUG << "setting completion handler on " << &asyncResp->res;

      addAwaitingResponse(asyncResp, node.location);

      BMCWEB_LOG_DEBUG << "Single-threaded expand";
      app.handle(newReq, asyncResp);
    }
  }

 private:
  static void placeResultStatic(
      const std::shared_ptr<MultiAsyncResp>& multi,
      const nlohmann::json::json_pointer& locationToPlace,
      crow::Response& res) {
    multi->placeResult(locationToPlace, res);
  }

  crow::App& app;
  std::shared_ptr<bmcweb::AsyncResp> finalRes;

  bool fromGrpc;
  bool with_trust_bundle;
  bool peer_authenticated;
  std::unordered_set<std::string> peer_privileges;
  absl::Mutex mutex_;
};

void processTopAndSkip(const Query& query, crow::Response& res) {
  if (!query.skip && !query.top) {
    // No work to do.
    return;
  }
  nlohmann::json::object_t* obj =
      res.jsonValue.get_ptr<nlohmann::json::object_t*>();
  if (obj == nullptr) {
    // Shouldn't be possible.  All responses should be objects.
    messages::internalError(res);
    return;
  }

  BMCWEB_LOG_DEBUG << "Handling top/skip";
  nlohmann::json::object_t::iterator members = obj->find("Members");
  if (members == obj->end()) {
    // From the Redfish specification 7.3.1
    // ... the HTTP 400 Bad Request status code with the
    // QueryNotSupportedOnResource message from the Base Message Registry
    // for any supported query parameters that apply only to resource
    // collections but are used on singular resources.
    messages::queryNotSupportedOnResource(res);
    return;
  }

  nlohmann::json::array_t* arr =
      members->second.get_ptr<nlohmann::json::array_t*>();
  if (arr == nullptr) {
    messages::internalError(res);
    return;
  }

  if (query.skip) {
    // Per section 7.3.1 of the Redfish specification, $skip is run before
    // $top Can only skip as many values as we have
    size_t skip = std::min(arr->size(), *query.skip);
    arr->erase(arr->begin(), arr->begin() + static_cast<ssize_t>(skip));
  }
  if (query.top) {
    size_t top = std::min(arr->size(), *query.top);
    arr->erase(arr->begin() + static_cast<ssize_t>(top), arr->end());
  }
}

// Given a JSON subtree |currRoot|, this function erases leaves whose keys are
// not in the |currNode| Trie node.
void recursiveSelect(nlohmann::json& currRoot, const SelectTrieNode& currNode) {
  nlohmann::json::object_t* object =
      currRoot.get_ptr<nlohmann::json::object_t*>();
  if (object != nullptr) {
    BMCWEB_LOG_DEBUG << "Current JSON is an object";
    auto it = currRoot.begin();
    while (it != currRoot.end()) {
      auto nextIt = std::next(it);
      BMCWEB_LOG_DEBUG << "key=" << it.key();
      const SelectTrieNode* nextNode = currNode.find(it.key());
      // Per the Redfish spec section 7.3.3, the service shall select
      // certain properties as if $select was omitted. This applies to
      // every TrieNode that contains leaves and the root.
      constexpr std::array<std::string_view, 5> reservedProperties = {
          "@odata.id", "@odata.type", "@odata.context", "@odata.etag", "error"};
      bool reserved =
          std::find(reservedProperties.begin(), reservedProperties.end(),
                    it.key()) != reservedProperties.end();
      if (reserved || (nextNode != nullptr && nextNode->isSelected())) {
        it = nextIt;
        continue;
      }
      if (nextNode != nullptr) {
        BMCWEB_LOG_DEBUG << "Recursively select: " << it.key();
        recursiveSelect(*it, *nextNode);
        it = nextIt;
        continue;
      }
      BMCWEB_LOG_DEBUG << it.key() << " is getting removed!";
      it = currRoot.erase(it);
    }
  }
  nlohmann::json::array_t* array = currRoot.get_ptr<nlohmann::json::array_t*>();
  if (array != nullptr) {
    BMCWEB_LOG_DEBUG << "Current JSON is an array";
    // Array index is omitted, so reuse the same Trie node
    for (nlohmann::json& nextRoot : *array) {
      recursiveSelect(nextRoot, currNode);
    }
  }
}

// The current implementation of $select still has the following TODOs due to
//  ambiguity and/or complexity.
// 1. combined with $expand; https://github.com/DMTF/Redfish/issues/5058 was
// created for clarification.
// 2. respect the full odata spec; e.g., deduplication, namespace, star (*),
// etc.
void processSelect(crow::Response& intermediateResponse,
                   const SelectTrieNode& trieRoot) {
  BMCWEB_LOG_DEBUG << "Process $select quary parameter";
  recursiveSelect(intermediateResponse.jsonValue, trieRoot);
}

void processAllParams(
    crow::App& app, const Query& query, const crow::Request& request,
    std::function<void(crow::Response&)>& completionHandler,
    crow::Response& intermediateResponse,
    const std::shared_ptr<boost::asio::io_context::strand>& strand) {
  if (!completionHandler) {
    BMCWEB_LOG_DEBUG << "Function was invalid?";
    return;
  }

  BMCWEB_LOG_DEBUG << "Processing query params";
  // If the request failed, there's no reason to even try to run query
  // params.
  if (intermediateResponse.resultInt() < 200 ||
      intermediateResponse.resultInt() >= 400) {
    completionHandler(intermediateResponse);
    return;
  }
  if (query.isOnly) {
    processOnly(app, intermediateResponse, completionHandler, strand);
    return;
  }

  if (query.top || query.skip) {
    processTopAndSkip(query, intermediateResponse);
  }

  if (query.expandType != ExpandType::None) {
    BMCWEB_LOG_DEBUG << "Executing expand query";
    auto asyncResp = std::make_shared<bmcweb::AsyncResp>(
        std::move(intermediateResponse), strand);

    asyncResp->res.setCompleteRequestHandler(std::move(completionHandler));
    auto multi = std::make_shared<MultiAsyncResp>(app, asyncResp, request);

    multi->startQuery(query);
    return;
  }

  // According to Redfish Spec Section 7.3.1, $select is the last parameter to
  // to process
  if (!query.selectTrie.root.empty()) {
    processSelect(intermediateResponse, query.selectTrie.root);
  }

  completionHandler(intermediateResponse);
}

}  // namespace query_param

namespace {

void afterIfMatchRequest(crow::App& app,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         crow::Request& req, const std::string& ifMatchHeader,
                         const crow::Response& resIn) {
  std::string computedEtag = resIn.computeEtag();
  BMCWEB_LOG_DEBUG << "User provided if-match etag " << ifMatchHeader
                   << " computed etag " << computedEtag;
  if (computedEtag != ifMatchHeader) {
    messages::preconditionFailed(asyncResp->res);
    return;
  }
  // Restart the request without if-match
  req.req.erase(boost::beast::http::field::if_match);
  BMCWEB_LOG_DEBUG << "Restarting request";
  app.handle(req, asyncResp);
}

bool handleIfMatch(crow::App& app, const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (req.session == nullptr) {
    // If the user isn't authenticated, don't even attempt to parse match
    // parameters
    return true;
  }

  std::string ifMatch{req.getHeaderValue(boost::beast::http::field::if_match)};
  if (ifMatch.empty()) {
    // No If-Match header.  Nothing to do
    return true;
  }
  if (req.req.method() != boost::beast::http::verb::patch &&
      req.req.method() != boost::beast::http::verb::post &&
      req.req.method() != boost::beast::http::verb::delete_) {
    messages::preconditionFailed(asyncResp->res);
    return false;
  }
  boost::system::error_code ec;

  // Try to GET the same resource
  crow::Request newReq(
      {boost::beast::http::verb::get, req.url().encoded_path(), 11}, ec);

  if (ec) {
    messages::internalError(asyncResp->res);
    return false;
  }

  // New request has the same credentials as the old request
  newReq.session = req.session;

  // Construct a new response object to fill in, and check the hash of before
  // we modify the Resource.
  std::shared_ptr<bmcweb::AsyncResp> getReqAsyncResp =
      std::make_shared<bmcweb::AsyncResp>(asyncResp->strand_);

  getReqAsyncResp->res.setCompleteRequestHandler(std::bind_front(
      afterIfMatchRequest, std::ref(app), asyncResp, req, ifMatch));

  app.handle(newReq, getReqAsyncResp);
  return false;
}

}  // namespace

bool setUpRedfishRouteWithDelegation(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    query_param::Query& delegated,
    const query_param::QueryCapabilities& queryCapabilities) {
  BMCWEB_LOG_DEBUG << "setup redfish route";

  if (asyncResp->response_type ==
          bmcweb::AsyncResp::ResponseType::kSubscription &&
      !queryCapabilities.canHandleSubscription) {
    BMCWEB_LOG_ALWAYS << "Cannot delegate subscription for route: "
                      << req.url();
    return false;
  }

  // Section 7.4 of the redfish spec "Redfish Services shall process the
  // [OData-Version header] in the following table as defined by the HTTP 1.1
  // specification..."
  // Required to pass redfish-protocol-validator REQ_HEADERS_ODATA_VERSION
  std::string_view odataHeader = req.getHeaderValue("OData-Version");
  if (!odataHeader.empty() && odataHeader != "4.0") {
    messages::preconditionFailed(asyncResp->res);
    return false;
  }

  asyncResp->res.addHeader("OData-Version", "4.0");

  std::optional<query_param::Query> queryOpt =
      query_param::parseParameters(req.url().params(), asyncResp->res);
  if (queryOpt == std::nullopt) {
    return false;
  }

  if (!handleIfMatch(app, req, asyncResp)) {
    return false;
  }

  bool needToCallHandlers = true;

#ifdef BMCWEB_ENABLE_REDFISH_AGGREGATION
  needToCallHandlers = RedfishAggregator::getInstance().beginAggregation(
                           req, asyncResp) == Result::LocalHandle;

  // If the request should be forwarded to a satellite BMC then we don't want
  // to write anything to the asyncResp since it will get overwritten later.
#endif

  // If this isn't a get, no need to do anything with parameters
  if (req.method() != boost::beast::http::verb::get) {
    return needToCallHandlers;
  }

  delegated = query_param::delegate(queryCapabilities, *queryOpt, asyncResp);
  std::function<void(crow::Response&)> handler =
      asyncResp->res.releaseCompleteRequestHandler();
  auto strand = asyncResp->strand_;

  asyncResp->res.setCompleteRequestHandler(
      [&app, handler(std::move(handler)), query{std::move(*queryOpt)},
       request(req), strand](crow::Response& resIn) mutable {
        query_param::processAllParams(app, query, request, handler, resIn,
                                      strand);
      });

  return needToCallHandlers;
}

}  // namespace redfish
