#pragma once

#include "bmcweb_config.h"

#include "aggregation_utils.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "http_client.hpp"
#include "http_connection.hpp"
#include "managed_store.hpp"

#include <boost/algorithm/string/predicate.hpp>

#include <array>
#include <random>

namespace redfish
{

constexpr unsigned int aggregatorReadBodyLimit = 50 * 1024 * 1024; // 50MB

enum class Result
{
    LocalHandle,
    NoLocalHandle
};

enum class SearchType
{
    Collection,
    CollOrCon,
    ContainsSubordinate,
    Resource
};

struct RdeSatelliteConfig
{
    std::string name;
    std::string vid;
    std::string udevid;
    std::string usbport;
    std::string objectpath;
};

// clang-format off
// These are all of the properties as of version 2022.2 of the Redfish Resource
// and Schema Guide whose Type is "string (URI)" and the name does not end in a
// case-insensitive form of "uri".  That version of the schema is associated
// with version 1.16.0 of the Redfish Specification.  Going forward, new URI
// properties should end in URI so this list should not need to be maintained as
// the spec is updated.  NOTE: These have been pre-sorted in order to be
// compatible with binary search
constexpr std::array nonUriProperties{
    "@Redfish.ActionInfo",
    // "@odata.context", // We can't fix /redfish/v1/$metadata URIs
    "@odata.id",
    // "Destination", // Only used by EventService and won't be a Redfish URI
    // "HostName", // Isn't actually a Redfish URI
    "Image",
    "MetricProperty",
    // "OriginOfCondition", // Is URI when in request, but is object in response
    "TaskMonitor",
    "target", // normal string, but target URI for POST to invoke an action
};
// clang-format on

// Search the top collection array to determine if the passed URI is of a
// desired type
inline bool searchCollectionsArray(std::string_view uri,
                                   const SearchType searchType)
{
    constexpr std::string_view serviceRootUri = "/redfish/v1";

    // The passed URI must begin with "/redfish/v1", but we have to strip it
    // from the URI since topCollections does not include it in its URIs
    if (!uri.starts_with(serviceRootUri))
    {
        return false;
    }

    // Catch empty final segments such as "/redfish/v1/Chassis//"
    if (uri.ends_with("//"))
    {
        return false;
    }

    std::size_t parseCount = uri.size() - serviceRootUri.size();
    // Don't include the trailing "/" if it exists such as in "/redfish/v1/"
    if (uri.ends_with("/"))
    {
        parseCount--;
    }

    boost::urls::result<boost::urls::url_view> parsedUrl =
        boost::urls::parse_relative_ref(
            uri.substr(serviceRootUri.size(), parseCount));
    if (!parsedUrl)
    {
        BMCWEB_LOG_ERROR << "Failed to get target URI from "
                         << uri.substr(serviceRootUri.size());
        return false;
    }

    if (!parsedUrl->segments().is_absolute() && !parsedUrl->segments().empty())
    {
        return false;
    }

    // If no segments() then the passed URI was either "/redfish/v1" or
    // "/redfish/v1/".
    if (parsedUrl->segments().empty())
    {
        return (searchType == SearchType::ContainsSubordinate) ||
               (searchType == SearchType::CollOrCon);
    }

    const auto* it = std::lower_bound(
        topCollections.begin(), topCollections.end(), parsedUrl->buffer());
    if (it == topCollections.end())
    {
        // parsedUrl is alphabetically after the last entry in the array so it
        // can't be a top collection or up tree from a top collection
        return false;
    }

    boost::urls::url collectionUrl(*it);
    boost::urls::segments_view collectionSegments = collectionUrl.segments();
    boost::urls::segments_view::iterator itCollection =
        collectionSegments.begin();
    const boost::urls::segments_view::const_iterator endCollection =
        collectionSegments.end();

    // Each segment in the passed URI should match the found collection
    for (const auto& segment : parsedUrl->segments())
    {
        if (itCollection == endCollection)
        {
            // Leftover segments means the target is for an aggregation
            // supported resource
            return searchType == SearchType::Resource;
        }

        if (segment != (*itCollection))
        {
            return false;
        }
        itCollection++;
    }

    // No remaining segments means the passed URI was a top level collection
    if (searchType == SearchType::Collection)
    {
        return itCollection == endCollection;
    }
    if (searchType == SearchType::ContainsSubordinate)
    {
        return itCollection != endCollection;
    }

    // Return this check instead of "true" in case other SearchTypes get added
    return searchType == SearchType::CollOrCon;
}

// Determines if the passed property contains a URI.  Those property names
// either end with a case-insensitive version of "uri" or are specifically
// defined in the above array.
inline bool isPropertyUri(std::string_view propertyName)
{
    return boost::iends_with(propertyName, "uri") ||
           std::binary_search(nonUriProperties.begin(), nonUriProperties.end(),
                              propertyName);
}

static inline void addPrefixToStringItem(std::string& strValue,
                                         std::string_view prefix)
{
    // Make sure the value is a properly formatted URI
    auto parsed = boost::urls::parse_relative_ref(strValue);
    if (!parsed)
    {
        BMCWEB_LOG_CRITICAL << "Couldn't parse URI from resource " << strValue;
        return;
    }

    boost::urls::url_view thisUrl = *parsed;

    // We don't need to aggregate JsonSchemas due to potential issues such as
    // version mismatches between aggregator and satellite BMCs.  For now
    // assume that the aggregator has all the schemas and versions that the
    // aggregated server has.
    if (crow::utility::readUrlSegments(thisUrl, "redfish", "v1", "JsonSchemas",
                                       crow::utility::OrMorePaths()))
    {
        BMCWEB_LOG_DEBUG << "Skipping JsonSchemas URI prefix fixing";
        return;
    }

    // The first two segments should be "/redfish/v1".  We need to check that
    // before we can search topCollections
    if (!crow::utility::readUrlSegments(thisUrl, "redfish", "v1",
                                        crow::utility::OrMorePaths()))
    {
        return;
    }

    // Check array adding a segment each time until collection is identified
    // Add prefix to segment after the collection
    const boost::urls::segments_view urlSegments = thisUrl.segments();
    bool addedPrefix = false;
    boost::urls::url url("/");
    boost::urls::segments_view::iterator it = urlSegments.begin();
    const boost::urls::segments_view::const_iterator end = urlSegments.end();

    // Skip past the leading "/redfish/v1"
    it++;
    it++;
    for (; it != end; it++)
    {
        // Trailing "/" will result in an empty segment.  In that case we need
        // to return so we don't apply a prefix to top level collections such
        // as "/redfish/v1/Chassis/"
        if ((*it).empty())
        {
            return;
        }

        if (std::binary_search(topCollections.begin(), topCollections.end(),
                               url.buffer()))
        {
            std::string collectionItem(prefix);
            collectionItem += "_" + (*it);
            url.segments().push_back(collectionItem);
            it++;
            addedPrefix = true;
            break;
        }

        url.segments().push_back(*it);
    }

    // Finish constructing the URL here (if needed) to avoid additional checks
    for (; it != end; it++)
    {
        url.segments().push_back(*it);
    }

    if (addedPrefix)
    {
        url.segments().insert(url.segments().begin(), {"redfish", "v1"});
        strValue = url.buffer();
    }
}

static inline void addPrefixToItem(nlohmann::json& item,
                                   std::string_view prefix)
{
    std::string* strValue = item.get_ptr<std::string*>();
    if (strValue == nullptr)
    {
        BMCWEB_LOG_CRITICAL << "Field wasn't a string????";
        return;
    }
    addPrefixToStringItem(*strValue, prefix);
    item = *strValue;
}

static inline int generateRandomInt()
{
    std::random_device randomDevice;
    std::mt19937 generator(randomDevice());
    std::uniform_int_distribution<> distribution(1, 9999);
    int randomNumber = distribution(generator);
    return randomNumber;
}

static inline void addAggregatedHeaders(crow::Response& asyncResp,
                                        const crow::Response& resp,
                                        std::string_view prefix)
{
    if (!resp.getHeaderValue("Content-Type").empty())
    {
        asyncResp.addHeader(boost::beast::http::field::content_type,
                            resp.getHeaderValue("Content-Type"));
    }
    if (!resp.getHeaderValue("Allow").empty())
    {
        asyncResp.addHeader(boost::beast::http::field::allow,
                            resp.getHeaderValue("Allow"));
    }
    std::string_view header = resp.getHeaderValue("Location");
    if (!header.empty())
    {
        std::string location(header);
        addPrefixToStringItem(location, prefix);
        asyncResp.addHeader(boost::beast::http::field::location, location);
    }
    if (!resp.getHeaderValue("Retry-After").empty())
    {
        asyncResp.addHeader(boost::beast::http::field::retry_after,
                            resp.getHeaderValue("Retry-After"));
    }
    // TODO: we need special handling for Link Header Value
}

// Fix HTTP headers which appear in responses from Task resources among others
static inline void addPrefixToHeadersInResp(nlohmann::json& json,
                                            std::string_view prefix)
{
    // The passed in "HttpHeaders" should be an array of headers
    nlohmann::json::array_t* array = json.get_ptr<nlohmann::json::array_t*>();
    if (array == nullptr)
    {
        BMCWEB_LOG_ERROR << "Field wasn't an array_t????";
        return;
    }

    for (nlohmann::json& item : *array)
    {
        // Each header is a single string with the form "<Field>: <Value>"
        std::string* strHeader = item.get_ptr<std::string*>();
        if (strHeader == nullptr)
        {
            BMCWEB_LOG_CRITICAL << "Field wasn't a string????";
            continue;
        }

        constexpr std::string_view location = "Location: ";
        if (strHeader->starts_with(location))
        {
            std::string header = strHeader->substr(location.size());
            addPrefixToStringItem(header, prefix);
            *strHeader = std::string(location) + header;
        }
    }
}

// Search the json for all URIs and add the supplied prefix if the URI is for
// an aggregated resource.
static inline void addPrefixes(nlohmann::json& json, std::string_view prefix)
{
    nlohmann::json::object_t* object =
        json.get_ptr<nlohmann::json::object_t*>();
    if (object != nullptr)
    {
        for (std::pair<const std::string, nlohmann::json>& item : *object)
        {
            if (isPropertyUri(item.first))
            {
                addPrefixToItem(item.second, prefix);
                continue;
            }

            // "HttpHeaders" contains HTTP headers.  Among those we need to
            // attempt to fix the "Location" header
            if (item.first == "HttpHeaders")
            {
                addPrefixToHeadersInResp(item.second, prefix);
                continue;
            }

            // Recusively parse the rest of the json
            addPrefixes(item.second, prefix);
        }
        return;
    }
    nlohmann::json::array_t* array = json.get_ptr<nlohmann::json::array_t*>();
    if (array != nullptr)
    {
        for (nlohmann::json& item : *array)
        {
            addPrefixes(item, prefix);
        }
    }
}

inline std::unordered_map<std::string, std::string>
    rdePrefixMap({{"/xyz/openbmc_project/rde_devices/1_1_1_1", "BCX5VT"},
                  {"/xyz/openbmc_project/rde_devices/1_1_2_1", "A61MJ0"},
                  {"/xyz/openbmc_project/rde_devices/1_1_3_1", "K298LC"},
                  {"/xyz/openbmc_project/rde_devices/1_1_4_1", "2HMMCS"}});

inline std::unordered_map<std::string, std::string>
    rdeServiceLabelMap({{"BCX5VT", "MS0"},
                        {"A61MJ0", "MS1"},
                        {"K298LC", "MS2"},
                        {"2HMMCS", "PCIE0"}});

static bool generatePrefix(std::string objPath, std::string& prefix)
{
    const auto& it = rdePrefixMap.find(objPath);
    if (it == rdePrefixMap.end())
    {
        BMCWEB_LOG_DEBUG << "objPath does not exist in prefix map " << objPath
                         << "\n";
        return false;
    }
    prefix = it->second;
    return true;
}

static inline bool isMemberStartsWithKnownPrefix(const std::string& memberName)
{
    BMCWEB_LOG_DEBUG << "isMemberStartsWithKnownPrefix";
    for (auto const& [path, prefix] : rdePrefixMap)
    {
        BMCWEB_LOG_DEBUG << "path " << path << " " << prefix;
        if (memberName.starts_with(prefix))
        {
            BMCWEB_LOG_DEBUG << " Known prefix " << memberName;
            return true;
        }
    }
    return false;
}

inline boost::system::error_code aggregationRetryHandler(unsigned int respCode)
{
    // Allow all response codes because we want to surface any satellite
    // issue to the client
    BMCWEB_LOG_DEBUG << "Received " << respCode << " response from satellite";
    return boost::system::errc::make_error_code(boost::system::errc::success);
}

inline crow::ConnectionPolicy getAggregationPolicy()
{
    return {.maxRetryAttempts = 1,
            .requestByteLimit = aggregatorReadBodyLimit,
            .maxConnections = 20,
            .retryPolicyAction = "TerminateAfterRetries",
            .retryIntervalSecs = std::chrono::seconds(0),
            .invalidResp = aggregationRetryHandler};
}

class RedfishAggregator
{
  private:
    crow::HttpClient client;

    RedfishAggregator() :
        client(std::make_shared<crow::ConnectionPolicy>(getAggregationPolicy()))
    {
        getSatelliteConfigs(constructorCallback);
    }

    // Dummy callback used by the Constructor so that it can report the number
    // of satellite configs when the class is first created
    static void constructorCallback(
        const boost::system::error_code& ec,
        const std::unordered_map<std::string, boost::urls::url>& satelliteInfo,
        const std::unordered_map<std::string, RdeSatelliteConfig>&
            rdeSatelliteInfo)
    {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Something went wrong while querying dbus!";
            return;
        }

        BMCWEB_LOG_DEBUG << "There were "
                         << std::to_string(satelliteInfo.size())
                         << " satellite configs found at startup";
        BMCWEB_LOG_DEBUG << "There were "
                         << std::to_string(rdeSatelliteInfo.size())
                         << " RDE Device configs found at startup";
    }

    // Search D-Bus objects for satellite config objects and add their
    // information if valid
    static void findSatelliteConfigs(
        const dbus::utility::ManagedObjectType& objects,
        std::unordered_map<std::string, boost::urls::url>& satelliteInfo,
        std::unordered_map<std::string, RdeSatelliteConfig>& rdeSatelliteInfo)
    {
        for (const auto& objectPath : objects)
        {
            for (const auto& interface : objectPath.second)
            {
                if (interface.first ==
                    "xyz.openbmc_project.Configuration.SatelliteController")
                {
                    BMCWEB_LOG_DEBUG << "Found Satellite Controller at "
                                     << objectPath.first.str;

                    if (!satelliteInfo.empty())
                    {
                        BMCWEB_LOG_ERROR
                            << "Redfish Aggregation only supports one satellite!";
                        BMCWEB_LOG_DEBUG << "Clearing all satellite data";
                        satelliteInfo.clear();
                        return;
                    }

                    // For now assume there will only be one satellite config.
                    // Assign it the name/prefix "5B247A"
                    addSatelliteConfig("5B247A", interface.second,
                                       satelliteInfo);
                }
                else if (
                    interface.first ==
                    "xyz.openbmc_project.Configuration.RdeSatelliteController")
                {
                    BMCWEB_LOG_DEBUG << "Found RDE Satellite Controller at "
                                     << objectPath.first.str;
                    addRdeSatelliteConfig(interface.second, rdeSatelliteInfo);
                }
            }
        }
    }

    // Parse the properties of a satellite config object and add the
    // configuration if the properties are valid
    static void addSatelliteConfig(
        const std::string& name,
        const dbus::utility::DBusPropertiesMap& properties,
        std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
    {
        boost::urls::url url;

        for (const auto& prop : properties)
        {
            if (prop.first == "Hostname")
            {
                const std::string* propVal =
                    std::get_if<std::string>(&prop.second);
                if (propVal == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Invalid Hostname value";
                    return;
                }
                url.set_host(*propVal);
            }

            else if (prop.first == "Port")
            {
                const uint64_t* propVal = std::get_if<uint64_t>(&prop.second);
                if (propVal == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Invalid Port value";
                    return;
                }

                if (*propVal > std::numeric_limits<uint16_t>::max())
                {
                    BMCWEB_LOG_ERROR << "Port value out of range";
                    return;
                }
                url.set_port(std::to_string(static_cast<uint16_t>(*propVal)));
            }

            else if (prop.first == "AuthType")
            {
                const std::string* propVal =
                    std::get_if<std::string>(&prop.second);
                if (propVal == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Invalid AuthType value";
                    return;
                }

                // For now assume authentication not required to communicate
                // with the satellite BMC
                if (*propVal != "None")
                {
                    BMCWEB_LOG_ERROR
                        << "Unsupported AuthType value: " << *propVal
                        << ", only \"none\" is supported";
                    return;
                }
                url.set_scheme("http");
            }
        } // Finished reading properties

        // Make sure all required config information was made available
        if (url.host().empty())
        {
            BMCWEB_LOG_ERROR << "Satellite config " << name << " missing Host";
            return;
        }

        if (!url.has_port())
        {
            BMCWEB_LOG_ERROR << "Satellite config " << name << " missing Port";
            return;
        }

        if (!url.has_scheme())
        {
            BMCWEB_LOG_ERROR << "Satellite config " << name
                             << " missing AuthType";
            return;
        }

        std::string resultString;
        auto result = satelliteInfo.insert_or_assign(name, std::move(url));
        if (result.second)
        {
            resultString = "Added new satellite config ";
        }
        else
        {
            resultString = "Updated existing satellite config ";
        }

        BMCWEB_LOG_DEBUG << resultString << name << " at "
                         << result.first->second.scheme() << "://"
                         << result.first->second.encoded_host_and_port();
    }

    // Parse the properties of a RDE Device config object and add the
    // configuration if the properties are valid
    static void addRdeSatelliteConfig(
        const dbus::utility::DBusPropertiesMap& properties,
        std::unordered_map<std::string, RdeSatelliteConfig>& rdeSatelliteInfo)
    {
        RdeSatelliteConfig rdeConfig;
        std::string name;
        for (const auto& prop : properties)
        {
            if (prop.first == "Name")
            {
                const std::string* propVal =
                    std::get_if<std::string>(&prop.second);
                if (propVal == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Invalid Name value";
                    return;
                }
                rdeConfig.name = *propVal;
            }
            else if (prop.first == "VID")
            {
                const std::string* propVal =
                    std::get_if<std::string>(&prop.second);
                if (propVal == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Invalid VID value";
                    return;
                }
                rdeConfig.vid = *propVal;
            }
            else if (prop.first == "UDEVID")
            {
                const std::string* propVal =
                    std::get_if<std::string>(&prop.second);
                if (propVal == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Invalid UDEVID value";
                    return;
                }
                rdeConfig.udevid = *propVal;
            }
            else if (prop.first == "USBPORT")
            {
                const std::string* propVal =
                    std::get_if<std::string>(&prop.second);
                if (propVal == nullptr)
                {
                    BMCWEB_LOG_ERROR << "Invalid USBPORT value";
                    return;
                }
                rdeConfig.usbport = *propVal;
            }
        } // Finished reading properties

        if (rdeConfig.udevid.empty())
        {
            BMCWEB_LOG_ERROR << "Empty udevid";
            return;
        }
        rdeConfig.objectpath =
            "/xyz/openbmc_project/rde_devices/" + rdeConfig.udevid;

        // Set the prefix to a random string 'E0SB8D'
        // (TODO) Generate a unique random prefix for each RDE Device
        if constexpr (bmcwebEnableRdeDevice)
        {
            if (!generatePrefix(rdeConfig.objectpath, name))
            {
                BMCWEB_LOG_ERROR << " Failed to get a prefix for "
                                 << rdeConfig.objectpath;
                return;
            }
            BMCWEB_LOG_DEBUG << " Got prefix " << name;
        }
        std::string resultString;
        auto result = rdeSatelliteInfo.emplace(name, std::move(rdeConfig));
        if (result.second)
        {
            resultString = "Added new RDE Device config ";
        }
        else
        {
            resultString = "Updated existing RDE Device config ";
        }
    }

    enum AggregationType
    {
        Collection,
        ContainsSubordinate,
        Resource,
    };

    static void
        startAggregation(AggregationType aggType, const crow::Request& thisReq,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
    {
        if (thisReq.method() != boost::beast::http::verb::get)
        {
            if (aggType == AggregationType::Collection)
            {
                BMCWEB_LOG_DEBUG
                    << "Only aggregate GET requests to top level collections";
                return;
            }

            if (aggType == AggregationType::ContainsSubordinate)
            {
                BMCWEB_LOG_DEBUG << "Only aggregate GET requests when uptree of"
                                 << " a top level collection";
                return;
            }
        }

        // Create a copy of thisReq so we we can still locally process the req
        std::error_code ec;
        auto localReq = std::make_shared<crow::Request>(thisReq.req, ec);
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Failed to create copy of request";
            if (aggType == AggregationType::Resource)
            {
                messages::internalError(asyncResp->res);
            }
            return;
        }

        getSatelliteConfigs(
            std::bind_front(aggregateAndHandle, aggType, localReq, asyncResp));
    }

    static void findSatellite(
        const crow::Request& req,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
        const std::unordered_map<std::string, boost::urls::url>& satelliteInfo,
        const std::unordered_map<std::string, RdeSatelliteConfig>&
            rdeSatelliteInfo,
        std::string_view memberName)
    {
        bool validPrefix = false;
        // Determine if the resource ID begins with a known prefix
        for (const auto& satellite : satelliteInfo)
        {
            std::string targetPrefix = satellite.first;
            targetPrefix += "_";
            if (memberName.starts_with(targetPrefix))
            {
                BMCWEB_LOG_DEBUG << "\"" << satellite.first
                                 << "\" is a known prefix";

                // Remove the known prefix from the request's URI and
                // then forward to the associated satellite BMC
                getInstance().forwardRequest(req, asyncResp, satellite.first,
                                             satelliteInfo);
                validPrefix = true;
            }
        }
        // Determine if the resource ID begins with a known prefix
        for (const auto& rdeSatellite : rdeSatelliteInfo)
        {
            std::string targetPrefix = rdeSatellite.first;
            targetPrefix += "_";
            if (memberName.starts_with(targetPrefix))
            {
                BMCWEB_LOG_DEBUG << "\"" << rdeSatellite.first
                                 << "\" is a known prefix";
                // Remove the known prefix from the request's URI and
                // then forward to RDE Daemon
                forwardRdeRequest(req, asyncResp, rdeSatellite.first,
                                  rdeSatelliteInfo);
                validPrefix = true;
            }
        }
        if (validPrefix)
        {
            return;
        }
        // We didn't recognize the prefix and need to return a 404
        std::string nameStr = req.url().segments().back();
        messages::resourceNotFound(asyncResp->res, "", nameStr);
    }

    // Intended to handle an incoming request based on if Redfish Aggregation
    // is enabled.  Forwards request to satellite BMC if it exists.
    static void aggregateAndHandle(
        AggregationType aggType,
        const std::shared_ptr<crow::Request>& sharedReq,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
        const boost::system::error_code& ec,
        const std::unordered_map<std::string, boost::urls::url>& satelliteInfo,
        const std::unordered_map<std::string, RdeSatelliteConfig>&
            rdeSatelliteInfo)
    {
        if (sharedReq == nullptr)
        {
            return;
        }
        // Something went wrong while querying dbus
        if (ec)
        {
            messages::internalError(asyncResp->res);
            return;
        }

        // No satellite or RDE configs means we don't need to keep attempting to
        // aggregate
        if (satelliteInfo.empty() && rdeSatelliteInfo.empty())
        {
            // For collections or resources that can contain a subordinate
            // top level collection we'll also handle the request locally so we
            // don't need to write an error code
            if (aggType == AggregationType::Resource)
            {
                std::string nameStr = sharedReq->url().segments().back();
                messages::resourceNotFound(asyncResp->res, "", nameStr);
            }
            return;
        }

        const crow::Request& thisReq = *sharedReq;
        if constexpr (enablePlatform9)
        {
            BMCWEB_LOG_DEBUG << "Aggregation is enabled, begin processing of "
                             << thisReq.url();
        }
        else
        {
            BMCWEB_LOG_DEBUG << "Aggregation is enabled, begin processing of "
                             << thisReq.target();
        }

        // We previously determined the request is for a collection.  No need to
        // check again
        if (aggType == AggregationType::Collection)
        {
            BMCWEB_LOG_DEBUG << "Aggregating a collection";
            // We need to use a specific response handler and send the
            // request to all known satellites
            getInstance().forwardCollectionRequests(
                thisReq, asyncResp, satelliteInfo, rdeSatelliteInfo);
            return;
        }

        // We previously determined the request may contain a subordinate
        // collection.  No need to check again
        if (aggType == AggregationType::ContainsSubordinate)
        {
            BMCWEB_LOG_DEBUG
                << "Aggregating what may have a subordinate collection";
            // We need to use a specific response handler and send the
            // request to all known satellites
            getInstance().forwardContainsSubordinateRequests(thisReq, asyncResp,
                                                             satelliteInfo);
            return;
        }

        const boost::urls::segments_view urlSegments = thisReq.url().segments();
        boost::urls::url currentUrl("/");
        boost::urls::segments_view::iterator it = urlSegments.begin();
        const boost::urls::segments_view::const_iterator end =
            urlSegments.end();

        // Skip past the leading "/redfish/v1"
        it++;
        it++;
        for (; it != end; it++)
        {
            if (std::binary_search(topCollections.begin(), topCollections.end(),
                                   currentUrl.buffer()))
            {
                // We've matched a resource collection so this current segment
                // must contain an aggregation prefix
                findSatellite(thisReq, asyncResp, satelliteInfo,
                              rdeSatelliteInfo, *it);
                return;
            }

            currentUrl.segments().push_back(*it);
        }

        // We shouldn't reach this point since we should've hit one of the
        // previous exits
        messages::internalError(asyncResp->res);
    }

    // Attempt to forward a request to the satellite BMC associated with the
    // prefix.
    void forwardRequest(
        const crow::Request& thisReq,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
        const std::string& prefix,
        const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
    {
        const auto& sat = satelliteInfo.find(prefix);
        if (sat == satelliteInfo.end())
        {
            // Realistically this shouldn't get called since we perform an
            // earlier check to make sure the prefix exists
            BMCWEB_LOG_ERROR << "Unrecognized satellite prefix \"" << prefix
                             << "\"";
            return;
        }

        // We need to strip the prefix from the request's path
        std::string targetURI;
        if constexpr (enablePlatform9)
        {
            targetURI = std::string(thisReq.url().path());
        }
        else
        {
            targetURI = std::string(thisReq.target());
        }

        size_t pos = targetURI.find(prefix + "_");
        if (pos == std::string::npos)
        {
            // If this fails then something went wrong
            BMCWEB_LOG_ERROR << "Error removing prefix \"" << prefix
                             << "_\" from request URI";
            messages::internalError(asyncResp->res);
            return;
        }
        targetURI.erase(pos, prefix.size() + 1);

        std::function<void(crow::Response&)> cb =
            std::bind_front(processResponse, prefix, asyncResp);

        std::string data = thisReq.req.body();
        client.sendDataWithCallback(data, std::string(sat->second.host()),
                                    sat->second.port_number(), targetURI,
                                    false /*useSSL*/, thisReq.fields(),
                                    thisReq.method(), cb);
    }

    // Forward a request for a collection URI to each known satellite BMC
    void forwardCollectionRequests(
        const crow::Request& thisReq,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
        const std::unordered_map<std::string, boost::urls::url>& satelliteInfo,
        const std::unordered_map<std::string, RdeSatelliteConfig>&
            rdeSatelliteInfo)
    {
        for (const auto& sat : satelliteInfo)
        {
            std::function<void(crow::Response&)> cb = std::bind_front(
                processCollectionResponse, sat.first, asyncResp);

            std::string targetURI;
            if constexpr (enablePlatform9)
            {
                targetURI = std::string(thisReq.url().path());
            }
            else
            {
                targetURI = std::string(thisReq.target());
            }
            std::string data = thisReq.req.body();
            client.sendDataWithCallback(data, std::string(sat.second.host()),
                                        sat.second.port_number(), targetURI,
                                        false /*useSSL*/, thisReq.fields(),
                                        thisReq.method(), cb);
        }
        for (const auto& rsat : rdeSatelliteInfo)
        {

            uint8_t operationId = 1;
            std::string requestPayload = "";
            BMCWEB_LOG_DEBUG << " Collection Request: dbus call to RDE Daemon "
                             << " operationId " << operationId;
            std::string targetURI(thisReq.target());
            BMCWEB_LOG_DEBUG << "Collections objpath " << rsat.second.objectpath
                             << " targetURI " << targetURI << " udevid "
                             << rsat.second.udevid;
            crow::connections::systemBus->async_method_call(
                [&operationId, rsat,
                 asyncResp](const boost::system::error_code ec,
                            const std::string& jsonString) {
                if (ec)
                {
                    BMCWEB_LOG_ERROR << "DBUS response error operationId "
                                     << operationId << " , " << ec.value()
                                     << ", " << ec.message();
                    return;
                }
                processRdeCollectionResponse(rsat.first, asyncResp, jsonString);
                },
                "xyz.openbmc_project.rdeoperation", rsat.second.objectpath,
                "xyz.openbmc_project.RdeDevice", "execute_rde",
                generateRandomInt(), operationId, targetURI, rsat.second.udevid,
                requestPayload);
        }
    }

    // Forward request for a URI that is uptree of a top level collection to
    // each known satellite BMC
    void forwardContainsSubordinateRequests(
        const crow::Request& thisReq,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
        const std::unordered_map<std::string, boost::urls::url>& satelliteInfo)
    {
        for (const auto& sat : satelliteInfo)
        {
            std::function<void(crow::Response&)> cb = std::bind_front(
                processContainsSubordinateResponse, sat.first, asyncResp);

            std::string targetURI(thisReq.target());
            std::string data = thisReq.req.body();
            client.sendDataWithCallback(data, std::string(sat.second.host()),
                                        sat.second.port_number(), targetURI,
                                        false /*useSSL*/, thisReq.fields(),
                                        thisReq.method(), cb);
        }
    }

    // Attempt to forward a request to the RDE Daemon associated with the
    // prefix.
    static void forwardRdeRequest(
        const crow::Request& thisReq,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
        const std::string& prefix,
        const std::unordered_map<std::string, RdeSatelliteConfig>&
            rdeSatelliteInfo)
    {
        const auto& sat = rdeSatelliteInfo.find(prefix);
        if (sat == rdeSatelliteInfo.end())
        {
            // Realistically this shouldn't get called since we perform an
            // earlier check to make sure the prefix exists
            BMCWEB_LOG_ERROR << "Unrecognized RDE Device prefix \"" << prefix
                             << "\"";
            return;
        }

        // We need to strip the prefix from the request's path
        std::string targetURI(thisReq.target());
        size_t pos = targetURI.find(prefix + "_");
        if (pos == std::string::npos)
        {
            // If this fails then something went wrong
            BMCWEB_LOG_ERROR << "Error removing prefix \"" << prefix
                             << "_\" from request URI";
            messages::internalError(asyncResp->res);
            return;
        }
        targetURI.erase(pos, prefix.size() + 1);

        uint8_t operationId = 1;
        std::string requestPayload = "";
        boost::beast::http::verb method = thisReq.method();
        if (thisReq.method() == boost::beast::http::verb::post)
        {
            operationId = 8;
            requestPayload = thisReq.body().data();
        }
        BMCWEB_LOG_DEBUG
            << " Resource Request: dbus call to RDE Daemon operationId "
            << operationId;
        BMCWEB_LOG_DEBUG << "objpath " << sat->second.objectpath
                         << " targetURI " << targetURI << " udevid "
                         << sat->second.udevid << " method " << method;
        crow::connections::systemBus->async_method_call(
            [&operationId, method, prefix,
             asyncResp](const boost::system::error_code ec,
                        const std::string& jsonString) {
            if (ec)
            {
                BMCWEB_LOG_ERROR << "DBUS response error operationId "
                                 << operationId << " , " << ec.value() << ", "
                                 << ec.message();
                return;
            }
            processRdeResponse(prefix, method, asyncResp, jsonString);
            },
            "xyz.openbmc_project.rdeoperation", sat->second.objectpath,
            "xyz.openbmc_project.RdeDevice", "execute_rde", generateRandomInt(),
            operationId, targetURI, sat->second.udevid, requestPayload);
    }
    // Processes the response returned by a RDE Device and loads its
    // contents into asyncResp
    static void
        processRdeResponse(std::string_view prefix,
                           boost::beast::http::verb method,
                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& respString)
    {

        nlohmann::json jsonVal =
            nlohmann::json::parse(respString, nullptr, false);
        if (jsonVal.is_discarded())
        {
            BMCWEB_LOG_ERROR << "Error parsing RDE Device response as JSON "
                             << respString;
            messages::operationFailed(asyncResp->res);
            return;
        }

        BMCWEB_LOG_DEBUG << "Successfully parsed RDE Device response";

        if (method == boost::beast::http::verb::post)
        {
            if (jsonVal["Status"] == "Completed")
            {
                asyncResp->res.result(200);
            }
            else
            {
                messages::operationFailed(asyncResp->res);
            }
            return;
        }
        // TODO: For collections we  want to add the satellite responses to
        // our response rather than just straight overwriting them if our
        // local handling was successful (i.e. would return a 200).
        addPrefixes(jsonVal, prefix);

        if constexpr (bmcwebEnableRdeDevice)
        {
            if (jsonVal.contains(
                    "/Location/PartLocation/ServiceLabel"_json_pointer))
            {
                BMCWEB_LOG_ERROR << " @odata.type " << jsonVal["@odata.type"];
                if (jsonVal["Model"] == platform6Chassis1 ||
                    jsonVal["Model"] == platform6Chassis2)
                {
                    BMCWEB_LOG_DEBUG << "Setting up service label "
                                     << rdeServiceLabelMap[std::string{prefix}]
                                     << " for prefix " << prefix;
                    jsonVal["Location"]["PartLocation"]["ServiceLabel"] =
                        rdeServiceLabelMap[std::string{prefix}];
                }
            }
        }

        asyncResp->res.result(200);
        asyncResp->res.jsonValue = std::move(jsonVal);

        BMCWEB_LOG_DEBUG << "Finished writing asyncResp";
    }

    // Processes the collection response returned by a RDE Device and merges
    // its "@odata.id" values
    static void processRdeCollectionResponse(
        const std::string& prefix,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
        const std::string& respString)
    {
        nlohmann::json jsonVal =
            nlohmann::json::parse(respString, nullptr, false);
        if (jsonVal.is_discarded())
        {
            BMCWEB_LOG_ERROR << "Error parsing RDEd response as JSON";

            // Notify the user if doing so won't overwrite a valid response
            if ((asyncResp->res.resultInt() != 200) &&
                (asyncResp->res.resultInt() != 502))
            {
                messages::operationFailed(asyncResp->res);
            }
            return;
        }

        BMCWEB_LOG_DEBUG << "Successfully parsed RDEd response";

        // Now we need to add the prefix to the URIs contained in the
        // response.
        addPrefixes(jsonVal, prefix);

        BMCWEB_LOG_DEBUG << "Added prefix to parsed RDE Device response";

        // If this resource collection does not exist on the aggregating bmc
        // and has not already been added from processing the response from
        // a different satellite then we need to completely overwrite
        // asyncResp
        if (asyncResp->res.resultInt() != 200)
        {
            // We only want to aggregate collections that contain a
            // "Members" array
            if ((!jsonVal.contains("Members")) &&
                (!jsonVal["Members"].is_array()))
            {
                BMCWEB_LOG_DEBUG << "Skipping aggregating unsupported resource";
                return;
            }

            BMCWEB_LOG_DEBUG
                << "Collection does not exist, overwriting asyncResp";
            asyncResp->res.jsonValue = std::move(jsonVal);

            BMCWEB_LOG_DEBUG << "Finished overwriting asyncResp";
        }
        else
        {
            // We only want to aggregate collections that contain a
            // "Members" array
            if ((!asyncResp->res.jsonValue.contains("Members")) &&
                (!asyncResp->res.jsonValue["Members"].is_array()))

            {
                BMCWEB_LOG_DEBUG << "Skipping aggregating unsupported resource";
                return;
            }

            BMCWEB_LOG_DEBUG << "Adding aggregated resources from \"" << prefix
                             << "\" to collection";

            // TODO: This is a potential race condition with multiple
            // satellites and the aggregating bmc attempting to write to
            // update this array.  May need to cascade calls to the next
            // satellite at the end of this function.
            auto& members = asyncResp->res.jsonValue["Members"];
            auto& satMembers = jsonVal["Members"];
            for (auto& satMem : satMembers)
            {
                members.push_back(std::move(satMem));
            }
            asyncResp->res.jsonValue["Members@odata.count"] = members.size();

            // TODO: Do we need to sort() after updating the array?
        }
    } // End processRdeCollectionResponse()

  public:
    RedfishAggregator(const RedfishAggregator&) = delete;
    RedfishAggregator& operator=(const RedfishAggregator&) = delete;
    RedfishAggregator(RedfishAggregator&&) = delete;
    RedfishAggregator& operator=(RedfishAggregator&&) = delete;
    ~RedfishAggregator() = default;

    static RedfishAggregator& getInstance()
    {
        static RedfishAggregator handler;
        return handler;
    }

    // Polls D-Bus to get all available satellite config information
    // Expects a handler which interacts with the returned configs
    static void getSatelliteConfigs(
        std::function<
            void(const boost::system::error_code&,
                 const std::unordered_map<std::string, boost::urls::url>&,
                 const std::unordered_map<std::string, RdeSatelliteConfig>&)>
            handler)
    {
        BMCWEB_LOG_DEBUG << "Gathering satellite configs";

        // TODO:: convert to getManagedObjectsWithContext when needed:
        managedStore::managedObjectStore->getManagedObjects(
            "xyz.openbmc_project.EntityManager",
            {"/xyz/openbmc_project/inventory"},
            [handler{std::move(handler)}](
                const boost::system::error_code& ec,
                const dbus::utility::ManagedObjectType& objects) {
            std::unordered_map<std::string, boost::urls::url> satelliteInfo;
            std::unordered_map<std::string, RdeSatelliteConfig>
                rdeSatelliteInfo;
            if (ec)
            {
                BMCWEB_LOG_ERROR << "DBUS response error " << ec.value() << ", "
                                 << ec.message();
                handler(ec, satelliteInfo, rdeSatelliteInfo);
                return;
            }

            // Maps a chosen alias representing a satellite BMC to a url
            // containing the information required to create a http
            // connection to the satellite
            findSatelliteConfigs(objects, satelliteInfo, rdeSatelliteInfo);

            if (!satelliteInfo.empty())
            {
                BMCWEB_LOG_DEBUG << "Redfish Aggregation enabled with "
                                 << std::to_string(satelliteInfo.size())
                                 << " satellite BMCs";
            }
            else if (!rdeSatelliteInfo.empty())
            {
                BMCWEB_LOG_DEBUG << "Redfish Aggregation enabled with "
                                 << std::to_string(rdeSatelliteInfo.size())
                                 << " RDE Device";
            }
            else
            {
                BMCWEB_LOG_DEBUG
                    << "No satellite BMCs detected.  Redfish Aggregation not enabled";
            }
            handler(ec, satelliteInfo, rdeSatelliteInfo);
            });
    }

    // Processes the response returned by a satellite BMC and loads its
    // contents into asyncResp
    static void
        processResponse(std::string_view prefix,
                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        crow::Response& resp)
    {
        // 429 and 502 mean we didn't actually send the request so don't
        // overwrite the response headers in that case
        if ((resp.result() == boost::beast::http::status::too_many_requests) ||
            (resp.result() == boost::beast::http::status::bad_gateway))
        {
            asyncResp->res.result(resp.result());
            return;
        }

        // We want to attempt prefix fixing regardless of response code
        // The resp will not have a json component
        // We need to create a json from resp's stringResponse
        std::string_view contentType = resp.getHeaderValue("Content-Type");
        if (boost::iequals(contentType, "application/json") ||
            boost::iequals(contentType, "application/json; charset=utf-8"))
        {
            nlohmann::json jsonVal =
                nlohmann::json::parse(resp.body(), nullptr, false);
            if (jsonVal.is_discarded())
            {
                BMCWEB_LOG_ERROR << "Error parsing satellite response as JSON";
                messages::operationFailed(asyncResp->res);
                return;
            }

            BMCWEB_LOG_DEBUG << "Successfully parsed satellite response";

            addPrefixes(jsonVal, prefix);

            if constexpr (enablePlatform9)
            {
                // Hardcode relation to aggregating BMC
                if ((jsonVal.contains("@odata.id")) &&
                    (jsonVal["@odata.id"].is_string()))
                {
                    std::string targetURI(jsonVal["@odata.id"]);
                    std::string aggRootURI(prefix);
                    aggRootURI = "/redfish/v1/Chassis/" + aggRootURI + "_" +
                                 std::string(platform9Chassis5);
                    if (targetURI == aggRootURI)
                    {
                        jsonVal["Links"]["ContainedBy"] = {
                            {"@odata.id", "/redfish/v1/Chassis/" +
                                              std::string(platform9Chassis4)}};
                    }
                }
                // End hardcoded workaround
            }

            BMCWEB_LOG_DEBUG << "Added prefix to parsed satellite response";

            asyncResp->res.result(resp.result());
            asyncResp->res.jsonValue = std::move(jsonVal);

            BMCWEB_LOG_DEBUG << "Finished writing asyncResp";
        }
        else
        {
            // We allow any Content-Type that is not "application/json" now
            asyncResp->res.result(resp.result());
            asyncResp->res.write(resp.body());
        }
        addAggregatedHeaders(asyncResp->res, resp, prefix);
    }

    // Processes the collection response returned by a satellite BMC and merges
    // its "@odata.id" values
    static void processCollectionResponse(
        const std::string& prefix,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
        crow::Response& resp)
    {
        // 429 and 502 mean we didn't actually send the request so don't
        // overwrite the response headers in that case
        if ((resp.result() == boost::beast::http::status::too_many_requests) ||
            (resp.result() == boost::beast::http::status::bad_gateway))
        {
            return;
        }

        if (resp.resultInt() != 200)
        {
            BMCWEB_LOG_DEBUG
                << "Collection resource does not exist in satellite BMC \""
                << prefix << "\"";
            // Return the error if we haven't had any successes
            if (asyncResp->res.resultInt() != 200)
            {
                asyncResp->res.result(resp.result());
                asyncResp->res.write(resp.body());
            }
            return;
        }

        // The resp will not have a json component
        // We need to create a json from resp's stringResponse
        std::string_view contentType = resp.getHeaderValue("Content-Type");
        if (boost::iequals(contentType, "application/json") ||
            boost::iequals(contentType, "application/json; charset=utf-8"))
        {
            nlohmann::json jsonVal =
                nlohmann::json::parse(resp.body(), nullptr, false);
            if (jsonVal.is_discarded())
            {
                BMCWEB_LOG_ERROR << "Error parsing satellite response as JSON";

                // Notify the user if doing so won't overwrite a valid response
                if (asyncResp->res.resultInt() != 200)
                {
                    messages::operationFailed(asyncResp->res);
                }
                return;
            }

            BMCWEB_LOG_DEBUG << "Successfully parsed satellite response";

            // Now we need to add the prefix to the URIs contained in the
            // response.
            addPrefixes(jsonVal, prefix);

            BMCWEB_LOG_DEBUG << "Added prefix to parsed satellite response";

            // If this resource collection does not exist on the aggregating bmc
            // and has not already been added from processing the response from
            // a different satellite then we need to completely overwrite
            // asyncResp
            if (asyncResp->res.resultInt() != 200)
            {
                // We only want to aggregate collections that contain a
                // "Members" array
                if ((!jsonVal.contains("Members")) &&
                    (!jsonVal["Members"].is_array()))
                {
                    BMCWEB_LOG_DEBUG
                        << "Skipping aggregating unsupported resource";
                    return;
                }

                BMCWEB_LOG_DEBUG
                    << "Collection does not exist, overwriting asyncResp";
                asyncResp->res.result(resp.result());
                asyncResp->res.jsonValue = std::move(jsonVal);
                asyncResp->res.addHeader("Content-Type", "application/json");

                BMCWEB_LOG_DEBUG << "Finished overwriting asyncResp";
            }
            else
            {
                // We only want to aggregate collections that contain a
                // "Members" array
                if ((!asyncResp->res.jsonValue.contains("Members")) &&
                    (!asyncResp->res.jsonValue["Members"].is_array()))

                {
                    BMCWEB_LOG_DEBUG
                        << "Skipping aggregating unsupported resource";
                    return;
                }

                BMCWEB_LOG_DEBUG << "Adding aggregated resources from \""
                                 << prefix << "\" to collection";

                // TODO: This is a potential race condition with multiple
                // satellites and the aggregating bmc attempting to write to
                // update this array.  May need to cascade calls to the next
                // satellite at the end of this function.
                // This is presumably not a concern when there is only a single
                // satellite since the aggregating bmc should have completed
                // before the response is received from the satellite.

                auto& members = asyncResp->res.jsonValue["Members"];
                auto& satMembers = jsonVal["Members"];
                for (auto& satMem : satMembers)
                {
                    members.push_back(std::move(satMem));
                }
                asyncResp->res.jsonValue["Members@odata.count"] =
                    members.size();

                // TODO: Do we need to sort() after updating the array?
            }
        }
        else
        {
            BMCWEB_LOG_ERROR << "Received unparsable response from \"" << prefix
                             << "\"";
            // We received a response that was not a json.
            // Notify the user only if we did not receive any valid responses
            // and if the resource collection does not already exist on the
            // aggregating BMC
            if (asyncResp->res.resultInt() != 200)
            {
                messages::operationFailed(asyncResp->res);
            }
        }
    } // End processCollectionResponse()

    // Processes the response returned by a satellite BMC and merges any
    // properties whose "@odata.id" value is the URI or either a top level
    // collection or is uptree from a top level collection
    static void processContainsSubordinateResponse(
        const std::string& prefix,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
        crow::Response& resp)
    {
        // 429 and 502 mean we didn't actually send the request so don't
        // overwrite the response headers in that case
        if ((resp.result() == boost::beast::http::status::too_many_requests) ||
            (resp.result() == boost::beast::http::status::bad_gateway))
        {
            return;
        }

        if (resp.resultInt() != 200)
        {
            BMCWEB_LOG_DEBUG
                << "Resource uptree from Collection does not exist in "
                << "satellite BMC \"" << prefix << "\"";
            // Return the error if we haven't had any successes
            if (asyncResp->res.resultInt() != 200)
            {
                asyncResp->res.result(resp.result());
                asyncResp->res.write(resp.body());
            }
            return;
        }

        // The resp will not have a json component
        // We need to create a json from resp's stringResponse
        std::string_view contentType = resp.getHeaderValue("Content-Type");
        if (boost::iequals(contentType, "application/json") ||
            boost::iequals(contentType, "application/json; charset=utf-8"))
        {
            bool addedLinks = false;
            nlohmann::json jsonVal =
                nlohmann::json::parse(resp.body(), nullptr, false);
            if (jsonVal.is_discarded())
            {
                BMCWEB_LOG_ERROR << "Error parsing satellite response as JSON";

                // Notify the user if doing so won't overwrite a valid response
                if (asyncResp->res.resultInt() != 200)
                {
                    messages::operationFailed(asyncResp->res);
                }
                return;
            }

            BMCWEB_LOG_DEBUG << "Successfully parsed satellite response";

            // Parse response and add properties missing from the AsyncResp
            // Valid properties will be of the form <property>.@odata.id and
            // @odata.id is a <URI>.  In other words, the json should contain
            // multiple properties such that
            // {"<property>":{"@odata.id": "<URI>"}}
            nlohmann::json::object_t* object =
                jsonVal.get_ptr<nlohmann::json::object_t*>();
            if (object == nullptr)
            {
                BMCWEB_LOG_ERROR << "Parsed JSON was not an object?";
                return;
            }

            for (std::pair<const std::string, nlohmann::json>& prop : *object)
            {
                if (!prop.second.contains("@odata.id"))
                {
                    continue;
                }

                std::string* strValue =
                    prop.second["@odata.id"].get_ptr<std::string*>();
                if (strValue == nullptr)
                {
                    BMCWEB_LOG_CRITICAL << "Field wasn't a string????";
                    continue;
                }
                if (!searchCollectionsArray(*strValue, SearchType::CollOrCon))
                {
                    continue;
                }

                addedLinks = true;
                if (!asyncResp->res.jsonValue.contains(prop.first))
                {
                    // Only add the property if it did not already exist
                    BMCWEB_LOG_DEBUG << "Adding link for " << *strValue
                                     << " from BMC " << prefix;
                    asyncResp->res.jsonValue[prop.first]["@odata.id"] =
                        *strValue;
                    continue;
                }
            }

            // If we added links to a previously unsuccessful (non-200) response
            // then we need to make sure the response contains the bare minimum
            // amount of additional information that we'd expect to have been
            // populated.
            if (addedLinks && (asyncResp->res.resultInt() != 200))
            {
                // This resource didn't locally exist or an error
                // occurred while generating the response.  Remove any
                // error messages and update the error code.
                asyncResp->res.jsonValue.erase(
                    asyncResp->res.jsonValue.find("error"));
                asyncResp->res.result(resp.result());

                const auto& it1 = object->find("@odata.id");
                if (it1 != object->end())
                {
                    asyncResp->res.jsonValue["@odata.id"] = (it1->second);
                }
                const auto& it2 = object->find("@odata.type");
                if (it2 != object->end())
                {
                    asyncResp->res.jsonValue["@odata.type"] = (it2->second);
                }
                const auto& it3 = object->find("Id");
                if (it3 != object->end())
                {
                    asyncResp->res.jsonValue["Id"] = (it3->second);
                }
                const auto& it4 = object->find("Name");
                if (it4 != object->end())
                {
                    asyncResp->res.jsonValue["Name"] = (it4->second);
                }
            }
        }
        else
        {
            BMCWEB_LOG_ERROR << "Received unparsable response from \"" << prefix
                             << "\"";
            // We received as response that was not a json
            // Notify the user only if we did not receive any valid responses,
            // and if the resource does not already exist on the aggregating BMC
            if (asyncResp->res.resultInt() != 200)
            {
                messages::operationFailed(asyncResp->res);
            }
        }
    }

    // Entry point to Redfish Aggregation
    // Returns Result stating whether or not we still need to locally handle the
    // request
    static Result
        beginAggregation(const crow::Request& thisReq,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
    {
        using crow::utility::OrMorePaths;
        using crow::utility::readUrlSegments;
        const boost::urls::url_view url = thisReq.url();

        // We don't need to aggregate JsonSchemas due to potential issues such
        // as version mismatches between aggregator and satellite BMCs.  For
        // now assume that the aggregator has all the schemas and versions that
        // the aggregated server has.
        if (crow::utility::readUrlSegments(url, "redfish", "v1", "JsonSchemas",
                                           crow::utility::OrMorePaths()))
        {
            return Result::LocalHandle;
        }

        // The first two segments should be "/redfish/v1".  We need to check
        // that before we can search topCollections
        if (!crow::utility::readUrlSegments(url, "redfish", "v1",
                                            crow::utility::OrMorePaths()))
        {
            return Result::LocalHandle;
        }

        // Parse the URI to see if it begins with a known top level collection
        // such as:
        // /redfish/v1/Chassis
        // /redfish/v1/UpdateService/FirmwareInventory
        const boost::urls::segments_view urlSegments = url.segments();
        boost::urls::url currentUrl("/");
        boost::urls::segments_view::iterator it = urlSegments.begin();
        const boost::urls::segments_view::const_iterator end =
            urlSegments.end();

        // Skip past the leading "/redfish/v1"
        it++;
        it++;
        for (; it != end; it++)
        {
            const std::string& collectionItem = *it;
            if (std::binary_search(topCollections.begin(), topCollections.end(),
                                   currentUrl.buffer()))
            {
                // We've matched a resource collection so this current segment
                // might contain an aggregation prefix
                // TODO: This needs to be rethought when we can support multiple
                // satellites due to
                // /redfish/v1/AggregationService/AggregationSources/5B247A
                // being a local resource describing the satellite
                if (collectionItem.starts_with("5B247A_") ||
                    isMemberStartsWithKnownPrefix(collectionItem))
                {
                    BMCWEB_LOG_DEBUG << "Need to forward a request";

                    // Extract the prefix from the request's URI, retrieve the
                    // associated satellite config information, and then forward
                    // the request to that satellite.
                    startAggregation(AggregationType::Resource, thisReq,
                                     asyncResp);
                    return Result::NoLocalHandle;
                }

                // Handle collection URI with a trailing backslash
                // e.g. /redfish/v1/Chassis/
                it++;
                if ((it == end) && collectionItem.empty())
                {
                    startAggregation(AggregationType::Collection, thisReq,
                                     asyncResp);
                }

                // We didn't recognize the prefix or it's a collection with a
                // trailing "/".  In both cases we still want to locally handle
                // the request
                return Result::LocalHandle;
            }

            currentUrl.segments().push_back(collectionItem);
        }

        // If we made it here then currentUrl could contain a top level
        // collection URI without a trailing "/", e.g. /redfish/v1/Chassis
        if (std::binary_search(topCollections.begin(), topCollections.end(),
                               currentUrl.buffer()))
        {
            startAggregation(AggregationType::Collection, thisReq, asyncResp);
            return Result::LocalHandle;
        }

        // If nothing else then the request could be for a resource which has a
        // top level collection as a subordinate
        if (searchCollectionsArray(url.buffer(),
                                   SearchType::ContainsSubordinate))
        {
            startAggregation(AggregationType::ContainsSubordinate, thisReq,
                             asyncResp);
            return Result::LocalHandle;
        }

        BMCWEB_LOG_DEBUG << "Aggregation not required";
        return Result::LocalHandle;
    }
};

} // namespace redfish
