#pragma once

#include "async_resp.hpp"
#include "chassis_utils.hpp"
#include "dbus_utility.hpp"
#include "dbus_utils.hpp"
#include "error_messages.hpp"
#include "managed_store_types.hpp"

#include <sdbusplus/asio/property.hpp>

#include <string>
#include <unordered_set>

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 = "");
/**
 * @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 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 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](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) {
            updateLocationContext(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));
        });
}

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

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