/*
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#pragma once

#include "app.hpp"
#include "dbus_utility.hpp"
#include "generated/enums/pcie_device.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/collection.hpp"
#include "utils/dbus_utils.hpp"

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

#include "managed_store.hpp"

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

namespace redfish
{

static constexpr char const* pciePath = "/xyz/openbmc_project/inventory/pcie";
static constexpr char const* pcieDeviceInterface =
    "xyz.openbmc_project.Inventory.Item.PCIeDevice";
static constexpr std::array<std::string_view, 1> pcieInterfaces = {
    pcieDeviceInterface};

static inline void
    getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::string& name)
{
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        pciePath, 0, pcieInterfaces, requestContext,
        [asyncResp, name](const boost::system::error_code& ec,
                          const dbus::utility::MapperGetSubTreePathsResponse&
                              pcieDevicePaths) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "no PCIe device paths found ec: "
                             << ec.message();
            // Not an error, system just doesn't have PCIe info
            return;
        }
        nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name];
        pcieDeviceList = nlohmann::json::array();
        for (const std::string& pcieDevicePath : pcieDevicePaths)
        {
            size_t devStart = pcieDevicePath.rfind('/');
            if (devStart == std::string::npos)
            {
                continue;
            }

            std::string devName = pcieDevicePath.substr(devStart + 1);
            if (devName.empty())
            {
                continue;
            }
            nlohmann::json::object_t pcieDevice;
            pcieDevice["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", "system", "PCIeDevices", devName);
            pcieDeviceList.push_back(std::move(pcieDevice));
        }
        asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size();
    });
}

static inline void handlePCIeDeviceCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& systemName)
{
    if (!redfish::setUpRedfishRoute(app, req, aResp))
    {
        return;
    }
    if (systemName != "system")
    {
        messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
        return;
    }
    aResp->res.addHeader(boost::beast::http::field::link,
                         "</redfish/v1/JsonSchemas/PCIeDeviceCollection/"
                         "PCIeDeviceCollection.json>; rel=describedby");
    aResp->res.jsonValue["@odata.type"] =
        "#PCIeDeviceCollection.PCIeDeviceCollection";
    aResp->res.jsonValue["@odata.id"] =
        "/redfish/v1/Systems/system/PCIeDevices";
    aResp->res.jsonValue["Name"] = "PCIe Device Collection";
    aResp->res.jsonValue["Description"] = "Collection of PCIe Devices";
    aResp->res.jsonValue["Members"] = nlohmann::json::array();
    aResp->res.jsonValue["Members@odata.count"] = 0;

    getPCIeDeviceList(aResp, "Members");
}

inline void requestRoutesSystemPCIeDeviceCollection(App& app)
{
    /**
     * Functions triggers appropriate requests on DBus
     */
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/")
        .privileges(redfish::privileges::getPCIeDeviceCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handlePCIeDeviceCollectionGet, std::ref(app)));
}

inline std::optional<pcie_device::PCIeTypes>
    redfishPcieGenerationFromDbus(const std::string& generationInUse)
{
    if (generationInUse ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1")
    {
        return pcie_device::PCIeTypes::Gen1;
    }
    if (generationInUse ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2")
    {
        return pcie_device::PCIeTypes::Gen2;
    }
    if (generationInUse ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3")
    {
        return pcie_device::PCIeTypes::Gen3;
    }
    if (generationInUse ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4")
    {
        return pcie_device::PCIeTypes::Gen4;
    }
    if (generationInUse ==
        "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5")
    {
        return pcie_device::PCIeTypes::Gen5;
    }
    if (generationInUse.empty() ||
        generationInUse ==
            "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown")
    {
        return pcie_device::PCIeTypes::Invalid;
    }

    // The value is not unknown or Gen1-5, need return an internal error.
    return std::nullopt;
}

inline void getPCIeDevicePropertiesCallback(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& device, const boost::system::error_code& ec,
    const dbus::utility::DBusPropertiesMap& pcieDevProperties)
{
    if (ec)
    {
        BMCWEB_LOG_DEBUG << "failed to get PCIe Device properties ec: "
                         << ec.value() << ": " << ec.message();
        if (ec.value() == boost::system::linux_error::bad_request_descriptor)
        {
            messages::resourceNotFound(asyncResp->res, "PCIeDevice", device);
        }
        else
        {
            messages::internalError(asyncResp->res);
        }
        return;
    }

    const std::string* manufacturer = nullptr;
    const std::string* deviceType = nullptr;
    const std::string* generationInUse = nullptr;
    const size_t* lanesInUse = nullptr;
    const std::string* oemString = nullptr;

    const bool success = sdbusplus::unpackPropertiesNoThrow(
        dbus_utils::UnpackErrorPrinter(), pcieDevProperties, "Manufacturer",
        manufacturer, "DeviceType", deviceType, "LanesInUse", lanesInUse,
        "GenerationInUse", generationInUse, "OEM", oemString);

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

    // The default value of LanesInUse is 0, and the field will be
    // left as off if it is a default value.
    if (lanesInUse != nullptr && *lanesInUse != 0)
    {
        asyncResp->res.jsonValue["PCIeInterface"]["LanesInUse"] = *lanesInUse;
    }

    if (generationInUse != nullptr)
    {
        std::optional<pcie_device::PCIeTypes> redfishGenerationInUse =
            redfishPcieGenerationFromDbus(*generationInUse);
        if (!redfishGenerationInUse)
        {
            messages::internalError(asyncResp->res);
            return;
        }
        if (*redfishGenerationInUse != pcie_device::PCIeTypes::Invalid)
        {
            asyncResp->res.jsonValue["PCIeInterface"]["PCIeType"] =
                *redfishGenerationInUse;
        }
    }

    if (oemString != nullptr)
    {
        asyncResp->res
            .jsonValue["PCIeInterface"]["OEM"]["Google"]["LaneStatus"] =
            *oemString;
    }

    if (manufacturer != nullptr)
    {
        asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
    }

    if (deviceType != nullptr)
    {
        asyncResp->res.jsonValue["DeviceType"] = *deviceType;
    }

    asyncResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_4_0.PCIeDevice";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", "system", "PCIeDevices", device);
    asyncResp->res.jsonValue["Name"] = "PCIe Device";
    asyncResp->res.jsonValue["Id"] = device;

    asyncResp->res.jsonValue["PCIeFunctions"]["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Systems", "system",
                                     "PCIeDevices", device, "PCIeFunctions");
}

inline void
    getPCIeChassisCallback(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& device,
                           const boost::system::error_code& ec,
                           const dbus::utility::MapperEndPoints& chassisPaths)
{
    if (ec)
    {
        if (ec.value() != EBADR)
        {
            BMCWEB_LOG_ERROR << "DBUS response error " << ec;
            messages::internalError(asyncResp->res);
        }
        return;
    }
    if (chassisPaths.empty())
    {
        return;
    }
    if (chassisPaths.size() > 1)
    {
        BMCWEB_LOG_ERROR << device << " is contained by mutliple chassis";
        messages::internalError(asyncResp->res);
        return;
    }

    sdbusplus::message::object_path chassisPath(chassisPaths[0]);
    std::string chassis = chassisPath.filename();
    if (chassis.empty())
    {
        BMCWEB_LOG_WARNING << "Malformed Chassis path " << chassisPath.str
                           << " on " << device;
        return;
    }

    asyncResp->res.jsonValue["Links"]["Chassis"]["@odata.id"] =
        "/redfish/v1/Chassis/" + chassis;
}

using GetPCIeDeviceCallback = std::function<void(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& device, const boost::system::error_code&,
    const ::dbus::utility::DBusPropertiesMap&)>;

inline void getPCIeDevice(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const std::string& device, GetPCIeDeviceCallback&& cb)
{
    managedStore::ManagedObjectStoreContext context(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        std::string(pciePath), 0, pcieInterfaces, context,
        [asyncResp, context, device, cb = std::move(cb)](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "getPCIeDevice getSubTree error: "
                             << ec.message();
            messages::internalError(asyncResp->res);
            return;
        }

        bool found = false;

        // Iterate over all retrieved ObjectPaths.
        for (const auto& object : subtree)
        {
            const std::string& path = object.first;
            const dbus::utility::MapperServiceMap& connectionNames =
                object.second;

            sdbusplus::message::object_path objPath(path);
            if (objPath.filename() != device)
            {
                continue;
            }

            if (connectionNames.empty())
            {
                BMCWEB_LOG_ERROR << "Got 0 Connection names";
                continue;
            }

            found = true;

            managedStore::GetManagedObjectStore()->getAllProperties(
                connectionNames[0].first, objPath, pcieDeviceInterface, context,
                std::bind_front(cb, asyncResp, device));
        }

        if (!found)
        {
            // Pass error code for missing object
            cb(asyncResp, device,
               boost::system::linux_error::bad_request_descriptor,
               ::dbus::utility::DBusPropertiesMap());
        }
    });
}

inline void handleSystemPCIeDeviceGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& device)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    if (systemName != "system")
    {
        messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                   systemName);
        return;
    }

    getPCIeDevice(asyncResp, device, getPCIeDevicePropertiesCallback);

    std::string escapedPath = std::string(pciePath) + "/" + device;
    dbus::utility::escapePathForDbus(escapedPath);

    constexpr std::array<std::string_view, 2> chassisInterfaces = {
        "xyz.openbmc_project.Inventory.Item.Board",
        "xyz.openbmc_project.Inventory.Item.Chassis"};

    managedStore::ManagedObjectStoreContext context(asyncResp);
    managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
        escapedPath + "/contained_by", {"/xyz/openbmc_project/inventory"}, 0,
        chassisInterfaces, context,
        std::bind_front(getPCIeChassisCallback, asyncResp, device));
}

inline void requestRoutesSystemPCIeDevice(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/PCIeDevices/<str>/")
        .privileges(redfish::privileges::getPCIeDevice)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleSystemPCIeDeviceGet, std::ref(app)));
}

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

    asyncResp->res.jsonValue["@odata.type"] =
        "#PCIeFunctionCollection.PCIeFunctionCollection";
    asyncResp->res.jsonValue["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Systems", "system",
                                     "PCIeDevices", device, "PCIeFunctions");
    asyncResp->res.jsonValue["Name"] = "PCIe Function Collection";
    asyncResp->res.jsonValue["Description"] =
        "Collection of PCIe Functions for PCIe Device " + device;

    auto getPCIeDeviceCallback =
        [](const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
           const std::string& device, const boost::system::error_code& ec,
           const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG
                << "failed to get PCIe Device properties ec: " << ec.value()
                << ": " << ec.message();
            if (ec.value() ==
                boost::system::linux_error::bad_request_descriptor)
            {
                messages::resourceNotFound(asyncResp->res, "PCIeDevice",
                                           device);
            }
            else
            {
                messages::internalError(asyncResp->res);
            }
            return;
        }

        nlohmann::json& pcieFunctionList = asyncResp->res.jsonValue["Members"];
        pcieFunctionList = nlohmann::json::array();
        static constexpr const int maxPciFunctionNum = 8;
        for (int functionNum = 0; functionNum < maxPciFunctionNum;
             functionNum++)
        {
            // Check if this function exists by looking for a
            // device ID
            std::string devIDProperty =
                "Function" + std::to_string(functionNum) + "DeviceId";
            const std::string* property = nullptr;
            for (const auto& propEntry : pcieDevProperties)
            {
                if (propEntry.first == devIDProperty)
                {
                    property = std::get_if<std::string>(&propEntry.second);
                }
            }
            if (property == nullptr || property->empty())
            {
                continue;
            }
            nlohmann::json::object_t pcieFunction;
            pcieFunction["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", "system", "PCIeDevices", device,
                "PCIeFunctions", std::to_string(functionNum));
            pcieFunctionList.push_back(std::move(pcieFunction));
        }
        asyncResp->res.jsonValue["Members@odata.count"] =
            pcieFunctionList.size();
    };

    getPCIeDevice(asyncResp, device, getPCIeDeviceCallback);
}

inline void requestRoutesSystemPCIeFunctionCollection(App& app)
{
    /**
     * Functions triggers appropriate requests on DBus
     */
    BMCWEB_ROUTE(app,
                 "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/")
        .privileges(redfish::privileges::getPCIeFunctionCollection)
        .methods(boost::beast::http::verb::get)(std::bind_front(
            handleSystemPCIeFunctionCollectionGet, std::ref(app)));
}

inline void handleSystemPCIeFunctionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& device, const std::string& function)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    auto getPCIeDeviceCallback =
        [function](const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& device,
                   const boost::system::error_code& ec,
                   const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG
                << "failed to get PCIe Device properties ec: " << ec.value()
                << ": " << ec.message();
            if (ec.value() ==
                boost::system::linux_error::bad_request_descriptor)
            {
                messages::resourceNotFound(asyncResp->res, "PCIeDevice",
                                           device);
            }
            else
            {
                messages::internalError(asyncResp->res);
            }
            return;
        }

        // Check if this function exists by looking for a device
        // ID
        std::string functionName = "Function" + function;
        std::string devIDProperty = functionName + "DeviceId";

        const std::string* devIdProperty = nullptr;
        for (const auto& property : pcieDevProperties)
        {
            if (property.first == devIDProperty)
            {
                devIdProperty = std::get_if<std::string>(&property.second);
                continue;
            }
        }
        if (devIdProperty == nullptr || devIdProperty->empty())
        {
            messages::resourceNotFound(asyncResp->res, "PCIeFunction",
                                       function);
            return;
        }

        asyncResp->res.jsonValue["@odata.type"] =
            "#PCIeFunction.v1_2_0.PCIeFunction";
        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Systems", "system", "PCIeDevices", device,
            "PCIeFunctions", function);
        asyncResp->res.jsonValue["Name"] = "PCIe Function";
        asyncResp->res.jsonValue["Id"] = function;
        asyncResp->res.jsonValue["FunctionId"] = std::stoi(function);
        asyncResp->res.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems", "system",
                                         "PCIeDevices", device);

        for (const auto& property : pcieDevProperties)
        {
            const std::string* strProperty =
                std::get_if<std::string>(&property.second);
            if (property.first == functionName + "DeviceId")
            {
                asyncResp->res.jsonValue["DeviceId"] = *strProperty;
            }
            if (property.first == functionName + "VendorId")
            {
                asyncResp->res.jsonValue["VendorId"] = *strProperty;
            }
            if (property.first == functionName + "FunctionType")
            {
                asyncResp->res.jsonValue["FunctionType"] = *strProperty;
            }
            if (property.first == functionName + "DeviceClass")
            {
                asyncResp->res.jsonValue["DeviceClass"] = *strProperty;
            }
            if (property.first == functionName + "ClassCode")
            {
                asyncResp->res.jsonValue["ClassCode"] = *strProperty;
            }
            if (property.first == functionName + "RevisionId")
            {
                asyncResp->res.jsonValue["RevisionId"] = *strProperty;
            }
            if (property.first == functionName + "SubsystemId")
            {
                asyncResp->res.jsonValue["SubsystemId"] = *strProperty;
            }
            if (property.first == functionName + "SubsystemVendorId")
            {
                asyncResp->res.jsonValue["SubsystemVendorId"] = *strProperty;
            }
        }
    };

    getPCIeDevice(asyncResp, device, getPCIeDeviceCallback);
}

inline void requestRoutesSystemPCIeFunction(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/")
        .privileges(redfish::privileges::getPCIeFunction)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleSystemPCIeFunctionGet, std::ref(app)));
}

} // namespace redfish
