#pragma once

#include <dbus/connection.hpp>
#include <dbus/endpoint.hpp>
#include <dbus/filter.hpp>
#include <dbus/match.hpp>
#include <dbus/message.hpp>
#include <persistent_data_middleware.hpp>
#include <token_authorization_middleware.hpp>
#include <fstream>
#include <streambuf>
#include <string>
#include <crow/app.h>
#include <boost/algorithm/string.hpp>
namespace crow {
namespace redfish {

template <typename... Middlewares>
void get_redfish_sub_routes(Crow<Middlewares...>& app, const std::string& url,
                            nlohmann::json& j) {
  std::vector<const std::string*> routes = app.get_routes(url);
  for (auto route : routes) {
    auto redfish_sub_route =
        route->substr(url.size(), route->size() - url.size() - 1);
    // check if the route is at this level, and we didn't find and exact match
    // also, filter out resources that start with $ to remove $metadata
    if (!redfish_sub_route.empty() && redfish_sub_route[0] != '$' &&
        redfish_sub_route.find('/') == std::string::npos) {
      j[redfish_sub_route] = nlohmann::json{{"@odata.id", *route}};
    }
  }
}

std::string execute_process(const char* cmd) {
  std::array<char, 128> buffer;
  std::string result;
  std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
  if (!pipe) throw std::runtime_error("popen() failed!");
  while (!feof(pipe.get())) {
    if (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
      result += buffer.data();
  }
  return result;
}

using ManagedObjectType = std::vector<std::pair<
    dbus::object_path, boost::container::flat_map<
                           std::string, boost::container::flat_map<
                                            std::string, dbus::dbus_variant>>>>;

template <typename... Middlewares>
void request_routes(Crow<Middlewares...>& app) {
  CROW_ROUTE(app, "/redfish/")
      .methods("GET"_method)([](const crow::request& req, crow::response& res) {
        res.json_value = {{"v1", "/redfish/v1/"}};
        res.end();
      });

  CROW_ROUTE(app, "/redfish/v1/AccountService/Accounts/")
      .methods(
          "GET"_method)([&](const crow::request& req, crow::response& res) {
        crow::connections::system_bus->async_method_call(
            [&](const boost::system::error_code ec,
                const ManagedObjectType& users) {
              if (ec) {
                res.code = 500;
              } else {
                res.json_value = {
                    {"@odata.context",
                     "/redfish/v1/"
                     "$metadata#ManagerAccountCollection."
                     "ManagerAccountCollection"},
                    {"@odata.id", "/redfish/v1/AccountService/Accounts"},
                    {"@odata.type",
                     "#ManagerAccountCollection.ManagerAccountCollection"},
                    {"Name", "Accounts Collection"},
                    {"Description", "BMC User Accounts"},
                    {"Members@odata.count", users.size()}};
                nlohmann::json member_array = nlohmann::json::array();
                int user_index = 0;
                for (auto& user : users) {
                  const std::string& path = user.first.value;
                  std::size_t last_index = path.rfind("/");
                  if (last_index == std::string::npos) {
                    last_index = 0;
                  } else {
                    last_index += 1;
                  }
                  member_array.push_back(
                      {{"@odata.id", "/redfish/v1/AccountService/Accounts/" +
                                         path.substr(last_index)}});
                }
                res.json_value["Members"] = member_array;
              }
              res.end();
            },
            {"xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
             "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"});
      });

  CROW_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/")
      .methods("GET"_method)([](const crow::request& req, crow::response& res,
                                const std::string& account_name) {

        crow::connections::system_bus->async_method_call(
            [&, account_name{std::move(account_name)} ](
                const boost::system::error_code ec,
                const ManagedObjectType& users) {
              if (ec) {
                res.code = 500;
              } else {
                for (auto& user : users) {
                  const std::string& path = user.first.value;
                  std::size_t last_index = path.rfind("/");
                  if (last_index == std::string::npos) {
                    last_index = 0;
                  } else {
                    last_index += 1;
                  }
                  if (path.substr(last_index) == account_name) {
                    res.json_value = {
                        {"@odata.context",
                         "/redfish/v1/$metadata#ManagerAccount.ManagerAccount"},
                        {"@odata.id", "/redfish/v1/AccountService/Accounts/1"},
                        {"@odata.type",
                         "#ManagerAccount.v1_0_3.ManagerAccount"},
                        {"Id", "1"},
                        {"Name", "User Account"},
                        {"Description", "User Account"},
                        {"Enabled", false},
                        {"Password", nullptr},
                        {"UserName", account_name},
                        {"RoleId", "Administrator"},
                        {"Links",
                         {{"Role",
                           {{"@odata.id",
                             "/redfish/v1/AccountService/Roles/"
                             "Administrator"}}}}}};
                    break;
                  }
                }
                if (res.json_value.is_null()) {
                  res.code = 404;
                }
              }
              res.end();
            },
            {"xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
             "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"});
      });
}
}  // namespace redfish
}  // namespace crow
