#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_QUERY_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_QUERY_H_

#include <cstddef>
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "boost/beast/http/verb.hpp"  // NOLINT
#include "boost/url/params_view.hpp"  // NOLINT
#include "boost/url/url_view.hpp"  // NOLINT
#include "app.hpp"
#include "app_singleton.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "async_resp.hpp"
#include <nlohmann/json.hpp>

// IWYU pragma: no_forward_declare crow::App
// IWYU pragma: no_include <boost/url/impl/params_view.hpp>
// IWYU pragma: no_include <boost/url/impl/url_view.hpp>

namespace redfish {

namespace query_param {
enum class ExpandType : uint8_t {
  None,
  Links,
  NotLinks,
  Both,
};

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

// A simple implementation of Trie to help |recursiveSelect|.
class SelectTrieNode {
 public:
  SelectTrieNode() = default;

  const SelectTrieNode* find(const std::string& jsonKey) const {
    auto it = children.find(jsonKey);
    if (it == children.end()) {
      return nullptr;
    }
    return &it->second;
  }

  // Creates a new node if the key doesn't exist, returns the reference to the
  // newly created node; otherwise, return the reference to the existing node
  SelectTrieNode* emplace(std::string_view jsonKey) {
    auto [it, _] = children.emplace(jsonKey, SelectTrieNode{});
    return &it->second;
  }

  bool empty() const { return children.empty(); }

  void clear() { children.clear(); }

  void setToSelected() { selected = true; }

  bool isSelected() const { return selected; }

 private:
  std::map<std::string, SelectTrieNode, std::less<>> children;
  bool selected = false;
};

struct SelectTrie {
  SelectTrie() = default;

  // Inserts a $select value; returns false if the nestedProperty is illegal.
  bool insertNode(std::string_view nestedProperty);

  SelectTrieNode root;
};

// The struct stores the parsed query parameters of the default Redfish route.
struct Query {
  // Only
  bool isOnly = false;
  // Expand
  static constexpr uint8_t kMinExpandLevel = 0;
  static constexpr uint8_t kMaxExpandLevel = 6;
  uint8_t expandLevel = 0;
  ExpandType expandType = ExpandType::None;

  // Skip
  std::optional<size_t> skip = std::nullopt;

  // Top
  static constexpr size_t maxTop = 1000;  // Max entries a response contain
  std::optional<size_t> top = std::nullopt;

  // Select
  SelectTrie selectTrie = {};  // NOLINT

  // Filter
  // We only support delegate filter for now.
  // Unless explicitly enable canDelegateFilter capability, common queries
  // won't parse $filter in the query.
  std::string filter = "";  // NOLINT
};

// The struct defines how resource handlers in redfish-core/lib/ can handle
// query parameters themselves, so that the default Redfish route will delegate
// the processing.
struct QueryCapabilities {
  bool canDelegateOnly = false;
  bool canDelegateTop = false;
  bool canDelegateSkip = false;
  uint8_t canDelegateExpandLevel = 0;
  bool canDelegateSelect = false;
  bool canDelegateFilter = false;
  bool canHandleSubscription = false;
};

struct ExpandNode {
  nlohmann::json::json_pointer location;
  std::string uri;

  inline bool operator==(const ExpandNode& other) const {
    return location == other.location && uri == other.uri;
  }
};

Query delegate(const QueryCapabilities& queryCapabilities, Query& query,
               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp);
std::optional<std::string> formatQueryForExpand(const Query& query);
bool isSelectedPropertyAllowed(std::string_view property);
bool getSelectParam(std::string_view value, Query& query);
void recursiveSelect(nlohmann::json& currRoot, const SelectTrieNode& currNode);
unsigned propogateErrorCode(unsigned finalCode, unsigned subResponseCode);
void propogateError(crow::Response& finalResponse, crow::Response& subResponse);
std::optional<Query> parseParameters(boost::urls::params_view urlParams,
                                     crow::Response& res);
QueryError getExpandType(std::string_view value, Query& query);
std::vector<ExpandNode> findNavigationReferences(ExpandType eType, int depth,
                                                 nlohmann::json& jsonResponse);
}  // namespace query_param

// Sets up the Redfish Route and delegates some of the query parameter
// processing. |queryCapabilities| stores which query parameters will be
// handled by redfish-core/lib codes, then default query parameter handler won't
// process these parameters.
[[nodiscard]] 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);

// Sets up the Redfish Route. All parameters are handled by the default handler.
[[nodiscard]] inline bool setUpRedfishRoute(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  // This route |delegated| is never used
  query_param::Query delegated;
  return setUpRedfishRouteWithDelegation(app, req, asyncResp, delegated,
                                         query_param::QueryCapabilities{});
}

// See |setUpRedfishRouteWithDelegation| above for documentation.
[[nodiscard]] inline bool setUpRedfishRouteWithDelegationOnGlobalApp(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    query_param::Query& delegated,
    const query_param::QueryCapabilities& queryCapabilities) {
  return setUpRedfishRouteWithDelegation(*crow::globalBmcWebApp, req, asyncResp,
                                         delegated, queryCapabilities);
}

// See |setUpRedfishRoute| above for documentation.
[[nodiscard]] inline bool setUpRedfishRouteOnGlobalApp(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  return setUpRedfishRoute(*crow::globalBmcWebApp, req, asyncResp);
}

}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_QUERY_H_
