#pragma once

#include "app.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "generated/enums/pcie_slots.hpp"
#include "managed_store.hpp"
#include "pcie.hpp"
#include "registries/privilege_registry.hpp"
#include "utility.hpp"
#include "dbus_utils.hpp"
#include "json_utils.hpp"
#include "location_utils.hpp"

#include <boost/system/error_code.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/unpack_properties.hpp>

#include <array>
#include <string_view>

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace redfish
{

inline void
    addPresenceStatus(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::string& connectionName,
                      const std::string& pcieSlotPath,
                      const std::string& presenceInterface, size_t index)
{
    managedStore::ManagedObjectStoreContext context(asyncResp);
    redfish::dbus_utils::getProperty<bool>(
        connectionName, pcieSlotPath, presenceInterface, "Present", context,
        [asyncResp, pcieSlotPath, index](boost::system::error_code ec,
                                         bool value) {
        if (ec)
        {
            messages::internalError(asyncResp->res);
            return;
        }
        asyncResp->res.jsonValue["Slots"][index]["Status"]["State"] =
            value ? "Enabled" : "Absent";
    });
}

inline void addLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& connectionName,
                        const std::string& pcieSlotPath, size_t index)
{
    location_util::getPartLocationContext(
        asyncResp, "/Slots"_json_pointer / index / "Location",
        pcieSlotPath + "/chassis");

    managedStore::ManagedObjectStoreContext context(asyncResp);
    redfish::dbus_utils::getProperty<std::string>(
        connectionName, pcieSlotPath,
        "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
        context,
        [asyncResp, index](const boost::system::error_code ec,
                           const std::string& value) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error";
            messages::internalError(asyncResp->res);
            return;
        }
        asyncResp->res.jsonValue["Slots"][index]["Location"]["PartLocation"]
                                ["ServiceLabel"] = value;
    });
}

inline pcie_slots::SlotTypes dbusSlotTypeToRf(const std::string& slotType)
{
    if (slotType ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.FullLength")
    {
        return pcie_slots::SlotTypes::FullLength;
    }
    if (slotType ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.HalfLength")
    {
        return pcie_slots::SlotTypes::HalfLength;
    }
    if (slotType ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.LowProfile")
    {
        return pcie_slots::SlotTypes::LowProfile;
    }
    if (slotType ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.Mini")
    {
        return pcie_slots::SlotTypes::Mini;
    }
    if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.M_2")
    {
        return pcie_slots::SlotTypes::M2;
    }
    if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OEM")
    {
        return pcie_slots::SlotTypes::OEM;
    }
    if (slotType ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OCP3Small")
    {
        return pcie_slots::SlotTypes::OCP3Small;
    }
    if (slotType ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OCP3Large")
    {
        return pcie_slots::SlotTypes::OCP3Large;
    }
    if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.U_2")
    {
        return pcie_slots::SlotTypes::U2;
    }

    // Unknown or others
    return pcie_slots::SlotTypes::Invalid;
}

inline void
    onPcieSlotGetAllDone(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const boost::system::error_code& ec,
                         const dbus::utility::DBusPropertiesMap& propertiesList,
                         const std::function<void(size_t)>& callback)
{
    if (ec)
    {
        BMCWEB_LOG_ERROR << "Can't get PCIeSlot properties!";
        messages::internalError(asyncResp->res);
        return;
    }

    nlohmann::json& slots = asyncResp->res.jsonValue["Slots"];

    nlohmann::json::array_t* slotsPtr =
        slots.get_ptr<nlohmann::json::array_t*>();
    if (slotsPtr == nullptr)
    {
        BMCWEB_LOG_ERROR << "Slots key isn't an array???";
        messages::internalError(asyncResp->res);
        return;
    }

    nlohmann::json::object_t slot;

    const std::string* generation = nullptr;
    const size_t* lanes = nullptr;
    const std::string* slotType = nullptr;
    const bool* hotPluggable = nullptr;

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), propertiesList, "Generation",
        generation, "Lanes", lanes, "SlotType", slotType, "HotPluggable",
        hotPluggable);

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

    if (generation != nullptr)
    {
        std::optional<pcie_device::PCIeTypes> pcieType =
            redfishPcieGenerationFromDbus(*generation);
        if (!pcieType)
        {
            messages::internalError(asyncResp->res);
            return;
        }
        slot["PCIeType"] = *pcieType;
    }

    if (lanes != nullptr && *lanes != 0)
    {

        slot["Lanes"] = *lanes;
    }

    if (slotType != nullptr)
    {
        pcie_slots::SlotTypes redfishSlotType = dbusSlotTypeToRf(*slotType);
        if (redfishSlotType == pcie_slots::SlotTypes::Invalid)
        {
            return;
        }
        slot["SlotType"] = redfishSlotType;
    }

    if (hotPluggable != nullptr)
    {
        slot["HotPluggable"] = *hotPluggable;
    }

    // Pass the slot index to the callback.
    size_t slotIndex = slots.size();
    slots.emplace_back(std::move(slot));
    callback(slotIndex);
}

inline void onMapperAssociationDone(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisID, const std::string& pcieSlotPath,
    const std::string& connectionName, const boost::system::error_code& ec,
    const dbus::utility::MapperEndPoints& pcieSlotChassis, bool findLocation,
    bool findPresence)
{
    if (ec)
    {
        if (ec.value() == EBADR)
        {
            // This PCIeSlot have no chassis association.
            return;
        }
        BMCWEB_LOG_ERROR << "DBUS response error";
        messages::internalError(asyncResp->res);
        return;
    }

    if (pcieSlotChassis.size() != 1)
    {
        BMCWEB_LOG_ERROR << "PCIe Slot association error! ";
        messages::internalError(asyncResp->res);
        return;
    }

    sdbusplus::message::object_path path(pcieSlotChassis[0]);
    std::string chassisName = path.filename();
    if (chassisName != chassisID)
    {
        // The pcie slot doesn't belong to the chassisID
        return;
    }

    managedStore::ManagedObjectStoreContext context(asyncResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        connectionName, pcieSlotPath,
        "xyz.openbmc_project.Inventory.Item.PCIeSlot", context,
        [asyncResp, connectionName, pcieSlotPath, findLocation,
         findPresence](const boost::system::error_code& ec2,
                       const dbus::utility::DBusPropertiesMap& propertiesList) {
        onPcieSlotGetAllDone(asyncResp, ec2, propertiesList,
                             [asyncResp, connectionName, pcieSlotPath,
                              findLocation, findPresence](size_t index) {
            if (findLocation)
            {
                addLocation(asyncResp, connectionName, pcieSlotPath, index);
            }
            if (findPresence)
            {
                managedStore::ManagedObjectStoreContext requestContext(
                    asyncResp);
                // Find the presence status of the Slot
                dbus_utils::getAssociationEndPoints(
                    pcieSlotPath + "/presence_status", requestContext,
                    [asyncResp, connectionName, pcieSlotPath,
                     index](const boost::system::error_code& ec3,
                            const dbus::utility::MapperEndPoints& resp) {
                    if (ec3 || resp.empty())
                    {
                        // No presence status = no failures
                        addPresenceStatus(
                            asyncResp, connectionName, pcieSlotPath,
                            "xyz.openbmc_project.Inventory.Item", index);
                        return;
                    }
                    std::string presencePath = resp[0];
                    addPresenceStatus(
                        asyncResp, "xyz.openbmc_project.GPIOStatus",
                        presencePath, "xyz.openbmc_project.GPIOStatus", index);
                });
            }
        });
    });
}

inline void
    onMapperSubtreeDone(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& chassisID,
                        const boost::system::error_code& ec,
                        const dbus::utility::MapperGetSubTreeResponse& subtree)
{
    if (ec)
    {
        BMCWEB_LOG_ERROR << "D-Bus response error on GetSubTree " << ec;
        messages::internalError(asyncResp->res);
        return;
    }

    BMCWEB_LOG_DEBUG << "Get properties for PCIeSlots associated to chassis = "
                     << chassisID;

    asyncResp->res.jsonValue["@odata.type"] = "#PCIeSlots.v1_4_1.PCIeSlots";
    asyncResp->res.jsonValue["Name"] = "PCIe Slot Information";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisID, "PCIeSlots");
    asyncResp->res.jsonValue["Id"] = "1";
    asyncResp->res.jsonValue["Slots"] = nlohmann::json::array();
    if (subtree.empty())
    {
        return;
    }
    const std::string locationInterface =
        "xyz.openbmc_project.Inventory.Decorator."
        "LocationCode";
    const std::string itemInterface = "xyz.openbmc_project.Inventory.Item";

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);

    for (const auto& pathServicePair : subtree)
    {
        const std::string& pcieSlotPath = pathServicePair.first;
        for (const auto& connectionInterfacePair : pathServicePair.second)
        {
            const std::string& connectionName = connectionInterfacePair.first;
            const std::vector<std::string>& interfaceList =
                connectionInterfacePair.second;
            sdbusplus::message::object_path pcieSlotAssociationPath(
                pcieSlotPath);
            pcieSlotAssociationPath /= "chassis";

            // The association of this PCIeSlot is used to determine whether
            // it belongs to this ChassisID
            dbus_utils::getAssociationEndPoints(
                std::string{pcieSlotAssociationPath}, requestContext,
                [asyncResp, chassisID, pcieSlotPath, connectionName,
                 interfaceList, locationInterface, itemInterface](
                    const boost::system::error_code& ec2,
                    const dbus::utility::MapperEndPoints& endpoints) {
                bool findPresence =
                    std::find(interfaceList.begin(), interfaceList.end(),
                              itemInterface) != interfaceList.end();
                bool findLocation =
                    std::find(interfaceList.begin(), interfaceList.end(),
                              locationInterface) != interfaceList.end();
                onMapperAssociationDone(asyncResp, chassisID, pcieSlotPath,
                                        connectionName, ec2, endpoints,
                                        findLocation, findPresence);
            });
        }
    }
}

inline void handlePCIeSlotCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisID)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.PCIeSlot"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp,
         chassisID](const boost::system::error_code& ec,
                    const dbus::utility::MapperGetSubTreeResponse& subtree) {
        onMapperSubtreeDone(asyncResp, chassisID, ec, subtree);
    });
}

inline void requestRoutesPCIeSlots(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PCIeSlots/")
        .privileges(redfish::privileges::getPCIeSlots)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handlePCIeSlotCollectionGet, std::ref(app)));
}

} // namespace redfish
