#pragma once

#include <app.hpp>
#include <async_resp.hpp>
#include <dbus_utility.hpp>
#include <error_messages.hpp>
#include <nlohmann/json.hpp>
#include <utils/collection.hpp>
#include <utils/hex_utils.hpp>
#include <utils/json_utils.hpp>

#include <vector>

namespace crow
{
namespace google_api
{

inline void
    handleGoogleV1Get(const crow::Request& /*req*/,
                      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    asyncResp->res.jsonValue["@odata.type"] =
        "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
    asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
    asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
    asyncResp->res.jsonValue["Name"] = "Google Service Root";
    asyncResp->res.jsonValue["Version"] = "1.0.0";
    asyncResp->res.jsonValue["RootOfTrustCollection"]["@odata.id"] =
        "/google/v1/RootOfTrustCollection";
}

inline void handleRootOfTrustCollectionGet(
    const crow::Request& /*req*/,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    asyncResp->res.jsonValue["@odata.id"] = "/google/v1/RootOfTrustCollection";
    asyncResp->res.jsonValue["@odata.type"] =
        "#RootOfTrustCollection.RootOfTrustCollection";
    redfish::collection_util::getCollectionMembers(
        asyncResp, boost::urls::url("/google/v1/RootOfTrustCollection"),
        {"xyz.openbmc_project.Control.Hoth"}, "/xyz/openbmc_project");
}

// Helper struct to identify a resolved D-Bus object interface
struct ResolvedEntity
{
    std::string id;
    std::string service;
    std::string object;
    std::string interface;
};

using ResolvedEntityHandler = std::function<void(
    const std::string&, const std::shared_ptr<bmcweb::AsyncResp>&,
    const ResolvedEntity&)>;

inline void hothGetSubtreeCallback(
    const std::string& command,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& rotId, const ResolvedEntityHandler& entityHandler,
    const boost::system::error_code ec,
    const dbus::utility::MapperGetSubTreeResponse& subtree)
{
    if (ec)
    {
        redfish::messages::internalError(asyncResp->res);
        return;
    }
    for (const auto& [path, services] : subtree)
    {
        sdbusplus::message::object_path objPath(path);
        if (objPath.filename() != rotId || services.empty())
        {
            continue;
        }

        ResolvedEntity resolvedEntity = {
            .id = rotId,
            .service = services[0].first,
            .object = path,
            .interface = "xyz.openbmc_project.Control.Hoth"};
        entityHandler(command, asyncResp, resolvedEntity);
        return;
    }

    // Couldn't find an object with that name.  return an error
    redfish::messages::resourceNotFound(asyncResp->res, "RootOfTrust", rotId);
}

inline void resolveRoT(const std::string& command,
                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::string& rotId,
                       ResolvedEntityHandler&& entityHandler)
{

    std::array<std::string, 1> hothIfaces = {
        "xyz.openbmc_project.Control.Hoth"};
    crow::connections::systemBus->async_method_call(
        [command, asyncResp, rotId,
         entityHandler{std::forward<ResolvedEntityHandler>(entityHandler)}](
            const boost::system::error_code ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        hothGetSubtreeCallback(command, asyncResp, rotId, entityHandler, ec,
                               subtree);
        },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTree",
        "/xyz/openbmc_project",
        /*depth=*/0, hothIfaces);
}

inline void populateRootOfTrustEntity(
    const std::string& /*unused*/,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const ResolvedEntity& resolvedEntity)
{
    asyncResp->res.jsonValue["@odata.type"] = "#RootOfTrust.v1_0_0.RootOfTrust";
    asyncResp->res.jsonValue["@odata.id"] =
        "/google/v1/RootOfTrustCollection/" + resolvedEntity.id;

    asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
    asyncResp->res.jsonValue["Id"] = resolvedEntity.id;
    // Need to fix this later to a stabler property.
    asyncResp->res.jsonValue["Name"] = resolvedEntity.id;
    asyncResp->res.jsonValue["Description"] = "Google Root Of Trust";
    asyncResp->res.jsonValue["Actions"]["#RootOfTrust.SendCommand"]["target"] =
        "/google/v1/RootOfTrustCollection/" + resolvedEntity.id +
        "/Actions/RootOfTrust.SendCommand";

    asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
        resolvedEntity.id;
    asyncResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
        "Embedded";
}

inline void
    handleRootOfTrustGet(const crow::Request& /*req*/,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::string& param)
{
    std::string emptyCommand;
    resolveRoT(emptyCommand, asyncResp, param, populateRootOfTrustEntity);
}

inline void
    invocationCallback(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const boost::system::error_code ec,
                       const std::vector<uint8_t>& responseBytes)
{
    if (ec)
    {
        BMCWEB_LOG_ERROR << "RootOfTrust.Actions.SendCommand failed: "
                         << ec.message();
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    asyncResp->res.jsonValue["CommandResponse"] =
        bytesToHexString(responseBytes);
}

inline void
    invokeRoTCommand(const std::string& command,
                     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                     const ResolvedEntity& resolvedEntity)
{
    std::vector<uint8_t> bytes = hexStringToBytes(command);
    if (bytes.empty())
    {
        BMCWEB_LOG_DEBUG << "Invalid command: " << command;
        redfish::messages::actionParameterValueTypeError(command, "Command",
                                                         "SendCommand");
        return;
    }

    crow::connections::systemBus->async_method_call(
        [asyncResp{asyncResp}](const boost::system::error_code ec,
                               const std::vector<uint8_t>& responseBytes) {
        invocationCallback(asyncResp, ec, responseBytes);
        },
        resolvedEntity.service, resolvedEntity.object, resolvedEntity.interface,
        "SendHostCommand", bytes);
}

inline void handleRoTSendCommandPost(
    const crow::Request& request,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& rotId)
{
    std::string command;
    if (!redfish::json_util::readJsonAction(request, asyncResp->res, "Command",
                                            command))
    {
        BMCWEB_LOG_DEBUG << "Missing property Command.";
        redfish::messages::actionParameterMissing(asyncResp->res, "SendCommand",
                                                  "Command");
        return;
    }

    resolveRoT(command, asyncResp, rotId, invokeRoTCommand);
}

inline void requestRoutes(App& app)
{
    BMCWEB_ROUTE(app, "/google/v1/")
        .methods(boost::beast::http::verb::get)(handleGoogleV1Get);

    BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::get)(handleRootOfTrustCollectionGet);

    BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/<str>")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::get)(handleRootOfTrustGet);

    BMCWEB_ROUTE(
        app,
        "/google/v1/RootOfTrustCollection/<str>/Actions/RootOfTrust.SendCommand")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::post)(handleRoTSendCommandPost);
}

} // namespace google_api
} // namespace crow
