#ifndef THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_SMART_ROUTER_H_
#define THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_SMART_ROUTER_H_

#include <array>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>

#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "boost/asio/io_context.hpp"  // NOLINT
#include "boost/beast/http/message.hpp"  //NOLINT
#include "boost/beast/http/string_body.hpp"  //NOLINT
#include "boost/beast/http/verb.hpp"  // NOLINT
#include "boost/system/error_code.hpp"  // NOLINT
#include "boost/url/parse.hpp"  // NOLINT
#include "boost/url/url.hpp"  // NOLINT
#include "utility.hpp"
#include "app_interface.h"
#include "dbus_utility.hpp" // NOLINT
#include "async_resp.hpp" // NOLINT
#include "http_request.hpp" // NOLINT
#include "routing.hpp"
#include "router_interface.h"

// DO NOT MODIFY THIS FILE IN GERRIT. THIS FILE SHOULD ONLY BE MODIFIED IN G3

namespace crow {

// This router will automatically route the requests to the appropriate
// router based on the request path.
class SmartRouter : public RouterInterface {
 public:
  // Clang thinks that the following constructor is deleted, but on gcc, it is
  // not.
  SmartRouter() = default;  // NOLINT
  ~SmartRouter() override = default;

  SmartRouter(const SmartRouter&) = delete;
  SmartRouter& operator=(const SmartRouter&) = delete;
  SmartRouter(SmartRouter&&) = delete;
  SmartRouter& operator=(SmartRouter&&) = delete;

  SmartRouter(bool allow_session_empty, AppInterface* tlbmc_app)
      : gbmcweb_router_(allow_session_empty),
        tlbmc_app_(tlbmc_app),
        tlbmc_owned_urls_(GetTlbmcOwnedUrls()) {
    // We still need this logic to set the smart router for the tlbmc router.
    if (tlbmc_app_ != nullptr) {
      tlbmc_app_->SetSmartRouter(this);
    }
  }
  void Validate();

  void Handle(crow::Request& req,
              const std::shared_ptr<bmcweb::AsyncResp>& async_resp) override;

  // This is a wrapper around the gbmcweb router's handleUpgrade function.
  template <typename Adaptor>
  void HandleUpgrade(Request& req,
                     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                     Adaptor&& adaptor) {
    gbmcweb_router_.handleUpgrade(req, asyncResp,
                                  std::forward<Adaptor>(adaptor));
  }

  DynamicRule& NewRuleDynamic(std::string&& rule);

  std::vector<const std::string*> GetRoutes(const std::string& parent);

  void DebugPrint();

  template <uint64_t N>
  typename black_magic::Arguments<
      N>::type::template rebind<TaggedRule>&
  NewRuleTagged(std::string_view rule) {
    return gbmcweb_router_.newRuleTagged<N>(rule);
  }

  // Plugin Routes
  template <uint64_t Tag, typename Func, size_t N>
  void AddHandler(absl::string_view url, boost::beast::http::verb verb,
                  const std::array<redfish::Privileges, N>& p, Func&& func) {
    gbmcweb_router_.newRuleTagged<Tag>(url).methods(verb).privileges(p)(func);
    // TODO(b/396518102): Add support for plugins in tlbmc.
    // tlbmc_app_->AddRoute<Tag>(url).methods(verb)(func);
  }

  template <uint64_t Tag, typename Func>
  void ReplaceHandler(std::string_view url, boost::beast::http::verb verb,
                      Func&& func) {
    gbmcweb_router_.replaceHandler<Tag>(url, verb, func);
    // TODO(b/396518102): Add support for plugins in tlbmc.
    // tlbmc_app_->ReplaceHandler<Tag>(url, verb, func);
  }

  template <uint64_t Tag>
  void RemoveHandler(std::string_view url, boost::beast::http::verb verb) {
    gbmcweb_router_.removeRuleTagged<Tag>(url, verb);
    // TODO(b/396518102): Add support for plugins in tlbmc.
    // tlbmc_app_->RemoveHandler<Tag>(url, verb);
  }
  template <uint64_t Tag, typename Func>
  void AppendHandler(std::string_view url, boost::beast::http::verb verb,
                     Func&& func) {
    gbmcweb_router_.appendHandler<Tag>(url, verb, func);
    // TODO(b/396518102): Add support for plugins in tlbmc.
    // tlbmc_app_->AppendHandler<Tag>(url, verb, func);
  }

  bool IsTlbmcOwnedUrl(std::string_view url);

  Router& GetGbmcwebRouter() { return gbmcweb_router_; }

  void UpdateTlbmcOwnedUrls() override;

 protected:
  // Store both the gbmcweb and tlbmc routers.
  Router gbmcweb_router_;
  AppInterface* const tlbmc_app_ = nullptr;
  absl::Mutex tlbmc_owned_urls_mutex_;
  absl::flat_hash_set<std::string> tlbmc_owned_urls_
      ABSL_GUARDED_BY(tlbmc_owned_urls_mutex_);

 private:
  absl::flat_hash_set<std::string> GetTlbmcOwnedUrls();
};

}  // namespace crow

#endif  // THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_SMART_ROUTER_H_
