#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_LOCATION_UTILS_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_LOCATION_UTILS_H_

#include <algorithm>
#include <cstddef>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "logging.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "chassis_utils.hpp"
#include "dbus_utils.hpp"
#include <nlohmann/json.hpp>
#include "managed_store_types.hpp"
#include "sdbusplus/unpack_properties.hpp"

namespace redfish {
namespace location_util {

enum class PopulateLocationContextOptions {
  kWithPartLocationContext = 0,
  kWithOemDevpathOnly = 1,
  kWithPartLocationContextAndOemDevpath = 2,
};

/**
 * @brief Check if the interface is a supported connector
 *
 * @param[in]       interface   Location type interface.
 *
 * @return true if the interface is a supported connector
 */
inline bool isConnector(const std::string& interface) {
  return interface == "xyz.openbmc_project.Inventory.Connector.Backplane" ||
         interface == "xyz.openbmc_project.Inventory.Connector.Bay" ||
         interface == "xyz.openbmc_project.Inventory.Connector.Connector" ||
         interface == "xyz.openbmc_project.Inventory.Connector.Embedded" ||
         interface == "xyz.openbmc_project.Inventory.Connector.Slot" ||
         interface == "xyz.openbmc_project.Inventory.Connector.Socket";
}

/**
 * @brief Fill out location info of a resource by requesting data from the
 * given D-Bus object.
 *
 * @param[in,out]   asyncResp   Async HTTP response.
 * @param[in]       interface   Location type interface.
 *
 * @return location if interface is supported Connector, otherwise, return
 * std::nullopt.
 */
inline std::optional<std::string> getLocationType(
    const std::string& interface) {
  if (!isConnector(interface)) {
    return std::nullopt;
  }
  return interface.substr(interface.find_last_of('.') + 1);
}

void getPartLocationContext(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                            const nlohmann::json::json_pointer& jsonPtr,
                            const std::string& associationPath,
                            const std::string& locationCode = "");

void getLocationContextWithOemDevpath(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const std::string& associationPath, const std::string& locationCode = "");

void getLocationContextWithOemDevpathOnly(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const std::string& associationPath, const std::string& locationCode = "");

/**
 *
 * @brief Fill out location code of a resource by requesting data from the
 * given D-Bus object.
 *
 * @param[in,out]   asyncResp   Async HTTP response.
 * @param[in]       service     D-Bus service to query.
 * @param[in]       objPath     D-Bus object to query.
 * @param[in]       location    Json path of where to find the location
 *                                property.
 */
inline void getLocationCode(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& service, const std::string& objPath,
    const nlohmann::json::json_pointer& location,
    const std::optional<std::string>& contextPath = std::nullopt) {
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  dbus_utils::getProperty<std::string>(
      service, objPath, "xyz.openbmc_project.Inventory.Decorator.LocationCode",
      "LocationCode", requestContext,
      [asyncResp, location, contextPath](const boost::system::error_code ec,
                                         const std::string& property) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "DBUS response error for Location";
          messages::internalError(asyncResp->res);
          return;
        }

        asyncResp->res.jsonValue[location]["PartLocation"]["ServiceLabel"] =
            property;
        if (contextPath != std::nullopt) {
          getPartLocationContext(asyncResp, location, contextPath.value(),
                                 property);
        }
      });
}

/**
 * @brief Fill out PartLocationContext of a redfish resource.
 *
 * @param[in,out]   asyncResp  Async HTTP response
 * @param[in]       jsonPtr    Json path of where to put the location context
 * @param[in]       label      Service label to update the location context with
 */
inline void updateLocationContext(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr, const std::string& label) {
  BMCWEB_LOG_DEBUG << "Add service label " << label
                   << " to PartLocationContext";
  nlohmann::json& propertyJson =
      asyncResp->res.jsonValue[jsonPtr]["PartLocationContext"];
  const std::string* val = propertyJson.get_ptr<const std::string*>();
  if (val != nullptr && !val->empty()) {
    propertyJson = label + "/" + *val;
  } else {
    propertyJson = label;
  }
}

/**
 * @brief Fill out Oem.LocationContext.ServiceLabel of a redfish resource.
 *
 * @param[in,out]   asyncResp  Async HTTP response
 * @param[in]       jsonPtr    Json path of where to put the location context
 * @param[in]       label      Service label to update the location context with
 */
inline void updateOemServiceLabel(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr, const std::string& label) {
  asyncResp->res
      .jsonValue[jsonPtr]["Google"]["LocationContext"]["ServiceLabel"] = label;
}

/**
 * @brief Fill out Oem devpath of a redfish resource.
 *
 * @param[in,out]   asyncResp  Async HTTP response
 * @param[in]       jsonPtr    Json path of where to put the Oem Devpath
 * @param[in]       label      Service label to update the Oem Devpath with
 */
inline void updateLocationOemDevpath(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr, const std::string& label) {
  BMCWEB_LOG_DEBUG << "update devpath" << label << "to Oem/Google/Devpath";
  const std::string prefix = "/phys/";
  nlohmann::json& propertyJson =
      asyncResp->res.jsonValue[jsonPtr]["Oem"]["Google"]["Devpath"];
  std::string* val = propertyJson.get_ptr<std::string*>();
  if (val != nullptr && !val->empty()) {
    if (val->rfind(prefix, 0) == 0) {
      val->erase(0, prefix.length());
      propertyJson = prefix + label + "/" + *val;
    } else {
      BMCWEB_LOG_ERROR << "Oem devpath " << *val << " missing /phys/";
      return;
    }
  } else {
    propertyJson = prefix + label;
  }
}

/**
 * @brief Context for selecting the best cable among multiple attached cables.
 * Uses RAII to trigger the completion callback when all async requests are
 * done.
 */
struct CableSelectionContext {
  std::optional<std::pair<std::string, std::string>> bestCable;
  absl::AnyInvocable<void(
      const std::optional<std::pair<std::string, std::string>>&)>
      onComplete;

  explicit CableSelectionContext(
      absl::AnyInvocable<
          void(const std::optional<std::pair<std::string, std::string>>&)>
          callback)
      : onComplete(std::move(callback)) {}

  ~CableSelectionContext() { onComplete(bestCable); }

  CableSelectionContext(const CableSelectionContext&) = delete;
  CableSelectionContext& operator=(const CableSelectionContext&) = delete;
  CableSelectionContext(CableSelectionContext&&) = delete;
  CableSelectionContext& operator=(CableSelectionContext&&) = delete;
};

/**
 * @brief Parses given chassis subtree for object path and connection to retrive
 * chassis location code used to fill PartLocationContext.
 *
 * @param[in]       upstreamChassisPaths   Set of chassis object paths queried.
 * @param[in]       jsonPtr     Json location to fill PartLocationContext
 * @param[in]       currentLocationCode  Location code of the current chassis.
 * @param[in]       withOemDevpath  Whether to fill Oem Devpath.
 * @param[in]       associationPath Path used to associate with upstream chassis
 * @param[in,out]   asyncResp   Async HTTP response
 * @param[in]       subtree     Subtree associated with chassis endpoint
 */
inline void getAssociatedChassisSubtreeCallback(
    std::unordered_set<std::string> upstreamChassisPaths,
    const nlohmann::json::json_pointer& jsonPtr,
    const std::string& currentLocationCode,
    PopulateLocationContextOptions populateLocationContextOptions,
    const std::string& associationPath,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const dbus::utility::MapperGetSubTreeResponse& subtree) {
  // Base case as we recurse to get upstream chassis association.
  if (subtree.empty()) {
    BMCWEB_LOG_DEBUG << "Chassis association not found."
                        "Must be root chassis or link is broken";
    std::string currentPath;
    size_t pos = associationPath.find_last_of('/');
    if (pos != std::string::npos) {
      currentPath = associationPath.substr(0, pos);
    }

    if (currentPath.empty()) {
      return;
    }

    // Check for attached cables
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);

    dbus_utils::getProperty<std::vector<std::string>>(
        "xyz.openbmc_project.ObjectMapper", currentPath + "/attached_cables",
        "xyz.openbmc_project.Association", "endpoints", requestContext,
        [asyncResp, jsonPtr, populateLocationContextOptions,
         currentLocationCode, currentPath,
         upstreamChassisPaths](const boost::system::error_code ec,
                               const std::vector<std::string>& cableList) {
          if (ec || cableList.empty()) {
            return;
          }

          auto selectionContext = std::make_shared<CableSelectionContext>(
              [asyncResp, jsonPtr, populateLocationContextOptions,
               upstreamChassisPaths, currentLocationCode, currentPath](
                  const std::optional<std::pair<std::string, std::string>>&
                      bestResult) mutable {
                if (!bestResult.has_value()) {
                  return;
                }

                const auto& [bestLocationCode, bestCablePath] =
                    bestResult.value();

                switch (populateLocationContextOptions) {
                  case PopulateLocationContextOptions::kWithOemDevpathOnly:
                    updateLocationOemDevpath(asyncResp, jsonPtr,
                                             bestLocationCode);
                    break;
                  case PopulateLocationContextOptions::kWithPartLocationContext:
                    updateLocationContext(asyncResp, jsonPtr, bestLocationCode);
                    break;
                  case PopulateLocationContextOptions::
                      kWithPartLocationContextAndOemDevpath:
                    updateLocationContext(asyncResp, jsonPtr, bestLocationCode);
                    updateLocationOemDevpath(asyncResp, jsonPtr,
                                             bestLocationCode);
                    break;
                }

                // Recurse upward to the cable's upstream chassis.
                chassis_utils::getAssociatedChassisSubtree(
                    asyncResp, bestCablePath + "/upstream_chassis",
                    std::bind_front(getAssociatedChassisSubtreeCallback,
                                    upstreamChassisPaths, jsonPtr,
                                    bestLocationCode,
                                    populateLocationContextOptions,
                                    bestCablePath + "/upstream_chassis"));
              });

          for (const std::string& cablePath : cableList) {
            managedStore::ManagedObjectStoreContext cableAssocRequestContext(
                asyncResp);
            // Check if the chassis is downstream of this cable.
            dbus_utils::getProperty<std::vector<std::string>>(
                "xyz.openbmc_project.ObjectMapper",
                cablePath + "/downstream_chassis",
                "xyz.openbmc_project.Association", "endpoints",
                cableAssocRequestContext,
                [asyncResp, cablePath, currentPath, selectionContext](
                    const boost::system::error_code ec2,
                    const std::vector<std::string>& endpoints) mutable {
                  bool isMatchingCable = false;

                  if (!ec2) {
                    isMatchingCable =
                        std::find(endpoints.begin(), endpoints.end(),
                                  currentPath) != endpoints.end();
                  }

                  if (isMatchingCable) {
                    // Valid cable, so we need to get its LocationCode.
                    managedStore::ManagedObjectStoreContext cableRequestContext(
                        asyncResp);
                    dbus_utils::getProperty<std::string>(
                        "xyz.openbmc_project.EntityManager", cablePath,
                        "xyz.openbmc_project.Inventory.Decorator.LocationCode",
                        "LocationCode", cableRequestContext,
                        [selectionContext, cablePath](
                            const boost::system::error_code ec3,
                            const std::string& cableLocationCode) mutable {
                          if (!ec3) {
                            if (!selectionContext->bestCable ||
                                cableLocationCode <
                                    selectionContext->bestCable->first) {
                              selectionContext->bestCable = {cableLocationCode,
                                                             cablePath};
                            }
                          }
                        });
                  }
                });
          }
        });

    return;
  }

  if (subtree.size() > 1) {
    BMCWEB_LOG_ERROR << "Found multiple upstream chassis.";
    messages::internalError(asyncResp->res);
    return;
  }

  auto chassisPathToConnMap = subtree.begin();

  // Upstream chassis.
  const std::string& chassisPath = chassisPathToConnMap->first;
  if (!upstreamChassisPaths.emplace(chassisPath).second) {
    BMCWEB_LOG_ERROR << "Loop detected in upstream chassis associations.";
    messages::internalError(asyncResp->res);
    return;
  }

  const dbus::utility::MapperServiceMap& serviceMap =
      chassisPathToConnMap->second;
  if (serviceMap.empty()) {
    BMCWEB_LOG_ERROR << "Associated chassis obj path " << chassisPath
                     << " has no service mapping.";
    messages::internalError(asyncResp->res);
    return;
  }

  if (serviceMap.size() > 1) {
    BMCWEB_LOG_ERROR << "Associated chassis path " << chassisPath
                     << " found in multiple connections";
    messages::internalError(asyncResp->res);
    return;
  }

  // Get service name to retrieve upstream chassis location code property.
  const std::string& service = serviceMap.begin()->first;

  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  dbus_utils::getProperty<std::string>(
      service, chassisPath,
      "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
      requestContext,
      [asyncResp, jsonPtr, chassisPath, currentLocationCode,
       upstreamChassisPaths,
       populateLocationContextOptions](const boost::system::error_code ec2,
                                       const std::string& locationCode) {
        if (ec2) {
          BMCWEB_LOG_DEBUG << "DBUS response error for Location, ec: "
                           << ec2.message();
          return;
        }

        std::string nextLocationCode;
        if (currentLocationCode != locationCode) {
          switch (populateLocationContextOptions) {
            case PopulateLocationContextOptions::kWithOemDevpathOnly:
              updateLocationOemDevpath(asyncResp, jsonPtr, locationCode);
              break;
            case PopulateLocationContextOptions::kWithPartLocationContext:
              updateLocationContext(asyncResp, jsonPtr, locationCode);
              break;
            case PopulateLocationContextOptions::
                kWithPartLocationContextAndOemDevpath:
              updateLocationContext(asyncResp, jsonPtr, locationCode);
              updateLocationOemDevpath(asyncResp, jsonPtr, locationCode);
              break;
          }
        } else {
          // Continue checking to see if the locationCode matches
          nextLocationCode = currentLocationCode;
        }

        chassis_utils::getAssociatedChassisSubtree(
            asyncResp, chassisPath + "/contained_by",
            std::bind_front(getAssociatedChassisSubtreeCallback,
                            upstreamChassisPaths, jsonPtr, nextLocationCode,
                            populateLocationContextOptions,
                            chassisPath + "/contained_by"));
      });
}

/**
 * @brief Recursively gets LocationCode for upstream chassis to populate
 * PartLocationContext.
 *
 * @param[in,out]   asyncResp       Async HTTP response
 * @param[in]       jsonPtr         Json location to fill PartLocationContext
 * @param[in]       associationPath Path used to associate with upstream chassis
 */
inline void getPartLocationContext(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const std::string& associationPath, const std::string& locationCode) {
  BMCWEB_LOG_DEBUG << "Get chassis endpoints associated with "
                   << associationPath;
  // Set of chassis object paths used to detect cycle as we resolve usptream
  // chassis associations to get to root chassis to create PartLocationContext
  std::unordered_set<std::string> upstreamChassisPaths;
  chassis_utils::getAssociatedChassisSubtree(
      asyncResp, associationPath,
      std::bind_front(getAssociatedChassisSubtreeCallback,
                      std::move(upstreamChassisPaths), jsonPtr, locationCode,
                      PopulateLocationContextOptions::kWithPartLocationContext,
                      associationPath));
}

/**
 * @brief Recursively gets LocationCode for upstream chassis to populate oem
 * devpath. This translates "/phys/A/SL" to "/phys/.../DC_DC_A/DC_A/A/SL"
 *
 * @param[in,out]   asyncResp       Async HTTP response
 * @param[in]       jsonPtr         Json location to fill PartLocationContext
 * @param[in]       associationPath Path used to associate with upstream chassis
 */
inline void getLocationContextWithOemDevpath(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const std::string& associationPath, const std::string& locationCode) {
  BMCWEB_LOG_DEBUG << "Get chassis endpoints associated with "
                   << associationPath
                   << " for location context and oem devpath";
  // Set of chassis object paths used to detect cycle as we resolve upstream
  // chassis associations to get to root chassis to create PartLocationContext
  std::unordered_set<std::string> upstreamChassisPaths;
  chassis_utils::getAssociatedChassisSubtree(
      asyncResp, associationPath,
      std::bind_front(
          getAssociatedChassisSubtreeCallback, std::move(upstreamChassisPaths),
          jsonPtr, locationCode,
          PopulateLocationContextOptions::kWithPartLocationContextAndOemDevpath,
          associationPath));
}

/**
 * @brief Gets LocationContext for a given chassis.
 *
 * @param[in,out]   asyncResp       Async HTTP response
 * @param[in]       jsonPtr         Json location to fill PartLocationContext
 * @param[in]       associationPath Path used to associate with upstream chassis
 */
inline void getLocationContextWithOemDevpathOnly(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const std::string& associationPath, const std::string& locationCode) {
  BMCWEB_LOG_DEBUG << "Get chassis endpoints associated with "
                   << associationPath
                   << " for location context and oem devpath";
  // Set of chassis object paths used to detect cycle as we resolve upstream
  // chassis associations to get to root chassis to create PartLocationContext
  std::unordered_set<std::string> upstreamChassisPaths;
  chassis_utils::getAssociatedChassisSubtree(
      asyncResp, associationPath,
      std::bind_front(getAssociatedChassisSubtreeCallback,
                      std::move(upstreamChassisPaths), jsonPtr, locationCode,
                      PopulateLocationContextOptions::kWithOemDevpathOnly,
                      associationPath));
}

/**
 * @brief Fill out location code of a resource from given managed objects.
 *
 * @param[in,out]   aResp           Async HTTP response.
 * @param[in]       objPath         D-Bus object to query.
 * @param[in]       interface       D-Bus interface to query.
 * @param[in]       jsonPtr         Json pointer to populate.
 * @param[in]       managedObjects  Managed objects.
 */
inline void getLocationCodeFromManagedObject(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& objPath,
    const std::string& interface, const nlohmann::json::json_pointer& jsonPtr,
    const dbus::utility::ManagedObjectType& managedObjects) {
  dbus::utility::DBusPropertiesMap properties;
  dbus_utils::getPropertiesFromManagedObjects(managedObjects, objPath,
                                              interface, properties);

  const std::string* locationProperty = nullptr;

  const bool success = sdbusplus::unpackPropertiesNoThrow(
      dbus_utils::UnpackErrorPrinter(), properties, "LocationCode",
      locationProperty);

  if (!success) {
    messages::internalError(aResp->res);
    return;
  }

  if (locationProperty != nullptr) {
    aResp->res.jsonValue[jsonPtr]["PartLocation"]["ServiceLabel"] =
        *locationProperty;
  }
}

/**
 * @brief Validate the association subtree.
 *
 * @param[in]       upstreamChassisPaths   Set of chassis object paths queried.
 * @param[in]       subtree     Subtree associated with chassis endpoint
 */

inline bool validateSubtree(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const dbus::utility::MapperGetSubTreeResponse& subtree) {
  if (subtree.empty()) {
    BMCWEB_LOG_DEBUG << "Chassis association not found."
                        "Must be root chassis or link is broken";
    return false;
  }
  if (subtree.size() > 1) {
    BMCWEB_LOG_ERROR << "Found multiple upstream chassis.";
    messages::internalError(asyncResp->res);
    return false;
  }
  auto chassisPathToConnMap = subtree.begin();
  // Upstream chassis.
  const std::string& chassisPath = chassisPathToConnMap->first;
  const dbus::utility::MapperServiceMap& serviceMap =
      chassisPathToConnMap->second;
  if (serviceMap.empty()) {
    BMCWEB_LOG_ERROR << "Associated chassis obj path " << chassisPath
                     << " has no service mapping.";
    messages::internalError(asyncResp->res);
    return false;
  }
  if (serviceMap.size() > 1) {
    BMCWEB_LOG_ERROR << "Associated chassis path " << chassisPath
                     << " found in multiple connections";
    messages::internalError(asyncResp->res);
    return false;
  }
  return true;
}

/**
 * @brief Parses given chassis subtree for object path and connection to retrive
 * chassis location code used to fill Oem ServiceLabel.
 *
 * @param[in]       jsonPtr     Json location to fill PartLocationContext
 * @param[in,out]   asyncResp   Async HTTP response
 * @param[in]       subtree     Subtree associated with chassis endpoint
 */
inline void getOemServiceLabelCallback(
    const nlohmann::json::json_pointer& jsonPtr,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const dbus::utility::MapperGetSubTreeResponse& subtree) {
  if (!validateSubtree(asyncResp, subtree)) {
    BMCWEB_LOG_DEBUG << "Not a valid subree";
    return;
  }
  auto chassisPathToConnMap = subtree.begin();

  // Upstream chassis.
  const std::string& chassisPath = chassisPathToConnMap->first;
  const dbus::utility::MapperServiceMap& serviceMap =
      chassisPathToConnMap->second;
  // Get service name to retrieve upstream chassis location code property.
  const std::string& service = serviceMap.begin()->first;

  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  dbus_utils::getProperty<std::string>(
      service, chassisPath,
      "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
      requestContext,
      [asyncResp, jsonPtr, chassisPath](const boost::system::error_code ec2,
                                        const std::string& locationCode) {
        if (ec2) {
          BMCWEB_LOG_DEBUG << "DBUS response error for Location, ec: "
                           << ec2.message();
          return;
        }
        updateOemServiceLabel(asyncResp, jsonPtr, locationCode);
      });
}

/**
 * @brief gets LocationCode for upstream chassis to populate
 * Oem ServiceLabel.
 *
 * @param[in,out]   asyncResp       Async HTTP response
 * @param[in]       jsonPtr         Json location to fill ServiceLabel
 * @param[in]       associationPath Path used to associate with upstream chassis
 */
inline void getOemServiceLabel(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const std::string& associationPath) {
  // Oem.Google.LocationContext.ServiceLabel is ServiceLabel inherited from
  // parent replaceable resource.
  chassis_utils::getAssociatedChassisSubtree(
      asyncResp, associationPath,
      std::bind_front(getOemServiceLabelCallback, jsonPtr));
}

/**
 * @brief Fill out Oem PartLocationContext of a redfish resource.
 *
 * @param[in,out]   asyncResp  Async HTTP response
 * @param[in]       jsonPtr    Json path of where to put the location context
 * @param[in]       label      Service label to update the location context with
 */
inline void updateOemPartLocationContext(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr, const std::string& label) {
  nlohmann::json& propertyJson =
      asyncResp->res.jsonValue[jsonPtr]["Google"]["LocationContext"]
                              ["PartLocationContext"];
  const std::string* val = propertyJson.get_ptr<const std::string*>();
  if (val != nullptr && !val->empty()) {
    propertyJson = label + "/" + *val;
  } else {
    propertyJson = label;
  }
}

/**
 * @brief Parses given chassis subtree for object path and connection to retrive
 * chassis location code used to fill Oem PartLocationContext.
 *
 * @param[in]       upstreamChassisPaths   Set of chassis object paths queried.
 * @param[in]       jsonPtr     Json location to fill PartLocationContext
 * @param[in,out]   asyncResp   Async HTTP response
 * @param[in]       subtree     Subtree associated with chassis endpoint
 */
inline void getOemPartLocationContextCallback(
    std::unordered_set<std::string> upstreamChassisPaths,
    const nlohmann::json::json_pointer& jsonPtr,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const dbus::utility::MapperGetSubTreeResponse& subtree) {
  if (!validateSubtree(asyncResp, subtree)) {
    BMCWEB_LOG_DEBUG << "Not a valid subree";
    return;
  }

  auto chassisPathToConnMap = subtree.begin();
  // Upstream chassis.
  const std::string& chassisPath = chassisPathToConnMap->first;
  if (!upstreamChassisPaths.emplace(chassisPath).second) {
    BMCWEB_LOG_ERROR << "Loop detected in upstream chassis associations.";
    messages::internalError(asyncResp->res);
    return;
  }
  const dbus::utility::MapperServiceMap& serviceMap =
      chassisPathToConnMap->second;

  // Get service name to retrieve upstream chassis location code property.
  const std::string& service = serviceMap.begin()->first;
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  dbus_utils::getProperty<std::string>(
      service, chassisPath,
      "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
      requestContext,
      [asyncResp, jsonPtr, chassisPath, upstreamChassisPaths](
          const boost::system::error_code ec2,
          const std::string& locationCode) {
        if (ec2) {
          BMCWEB_LOG_DEBUG << "DBUS response error for Location, ec: "
                           << ec2.message();
          return;
        }

        updateOemPartLocationContext(asyncResp, jsonPtr, locationCode);

        chassis_utils::getAssociatedChassisSubtree(
            asyncResp, chassisPath + "/contained_by",
            std::bind_front(getOemPartLocationContextCallback,
                            upstreamChassisPaths, jsonPtr));
      });
}

/**
 * @brief Recursively gets LocationCode for upstream chassis to populate
 * Oem PartLocationContext.
 *
 * @param[in,out]   asyncResp       Async HTTP response
 * @param[in]       jsonPtr         Json location to fill PartLocationContext
 * @param[in]       associationPath Path used to associate with upstream chassis
 */
inline void getOemPartLocationContext(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json::json_pointer& jsonPtr,
    const std::string& associationPath) {
  // Oem.Google.LocationContext.PartLocationContext is PartLocationContext
  // inherited from parent replaceable resource.
  asyncResp->res
      .jsonValue[jsonPtr]["Google"]["LocationContext"]["PartLocationContext"] =
      "";
  std::unordered_set<std::string> upstreamChassisPaths;
  chassis_utils::getAssociatedChassisSubtree(
      asyncResp, associationPath,
      [jsonPtr, upstreamChassisPaths](
          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
          const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (!validateSubtree(asyncResp, subtree)) {
          BMCWEB_LOG_DEBUG << "Not a valid subree";
          return;
        }
        // Upstream chassis.
        const std::string& chassisPath = subtree.begin()->first;

        managedStore::ManagedObjectStoreContext requestContext(asyncResp);
        chassis_utils::getAssociatedChassisSubtree(
            asyncResp, chassisPath + "/contained_by",
            std::bind_front(getOemPartLocationContextCallback,
                            upstreamChassisPaths, jsonPtr));
      });
}

}  // namespace location_util
}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_LOCATION_UTILS_H_
