#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_LOCATION_UTILS_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_LOCATION_UTILS_H_

#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <unordered_set>
#include <utility>

#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 {

/**
 * @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 getOemDevpathLocation(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 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 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,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, const bool isOemDevpath,
    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";
    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, isOemDevpath](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) {
          if (!isOemDevpath) {
            updateLocationContext(asyncResp, jsonPtr, locationCode);
          } else {
            updateLocationOemDevpath(asyncResp, jsonPtr, locationCode);
          }
        } 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,
                            isOemDevpath));
      });
}

/**
 * @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,
                      false));
}

/**
 * @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 getOemDevpathLocation(
    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 oem devpath";
  // 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,
                      true));
}

/**
 * @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 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 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_
