/*
// 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 "bmcweb_config.h"

#include "app.hpp"
#include "assembly.hpp"
#include "dbus_utility.hpp"
#include "health.hpp"
#include "led.hpp"
#include "managed_store.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/chassis_utils.hpp"
#include "utils/collection.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/json_utils.hpp"
#include "utils/storage_utils.hpp"
#include "utils/system_utils.hpp"

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

#include <array>
#include <functional>
#include <string_view>

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

namespace redfish
{

constexpr int KMAX_RESET_DELAY_SEC = 3600;

/**
 * @brief Retrieves resources over dbus to link to the chassis
 *
 * @param[in] asyncResp  - Shared pointer for completing asynchronous
 * calls
 * @param[in] path       - Chassis dbus path to look for the storage.
 *
 * Calls the Association endpoints on the path + "/storage" and add the link of
 * json["Links"]["Storage@odata.count"] =
 *    {"@odata.id", "/redfish/v1/Storage/" + resourceId}
 *
 * @return None.
 */
inline void getStorageLinkFromChassis(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const sdbusplus::message::object_path& path)
{
    managedStore::ManagedObjectStoreContext context(asyncResp);
    dbus_utils::getProperty<std::vector<std::string>>(
        "xyz.openbmc_project.ObjectMapper", (path / "storage").str,
        "xyz.openbmc_project.Association", "endpoints", context,
        [asyncResp](const boost::system::error_code ec,
                    const std::vector<std::string>& storageList) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "getStorageLink got DBUS response error";
            return;
        }

        nlohmann::json::array_t storages;
        asyncResp->res.jsonValue["Links"]["Storage@odata.count"] =
            storages.size();
        asyncResp->res.jsonValue["Links"]["Storage"] = std::move(storages);

        for (const std::string& storagePath : storageList)
        {
            std::string id =
                sdbusplus::message::object_path(storagePath).filename();
            if (id.empty())
            {
                continue;
            }
            storage_utils::getSystemPathFromStorage(
                asyncResp, storagePath,
                [asyncResp, id](std::optional<std::string_view> systemPath) {
                std::string systemName =
                    systemPath ? std::filesystem::path(*systemPath).filename()
                               : "system";

                asyncResp->res.jsonValue["Links"]["Storage@odata.count"] =
                    asyncResp->res.jsonValue["Links"]["Storage@odata.count"]
                        .get<std::size_t>() +
                    1;

                nlohmann::json::object_t storage;
                storage["@odata.id"] = crow::utility::urlFromPieces(
                    "redfish", "v1", "Systems", systemName, "Storage", id);
                asyncResp->res.jsonValue["Links"]["Storage"].emplace_back(
                    std::move(storage));
            });
        }
        });
}

/**
 * @brief Retrieves chassis state properties over dbus
 *
 * @param[in] aResp - Shared pointer for completing asynchronous calls.
 *
 * @return None.
 */
inline void getChassisState(std::shared_ptr<bmcweb::AsyncResp> aResp)
{
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.State.Chassis"};

    // Use mapper to get subtree paths.
    managedStore::ManagedObjectStoreContext requestContext(aResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/", 0, interfaces, requestContext,
        [aResp{std::move(aResp)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreePathsResponse& chassisList) mutable {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
            messages::internalError(aResp->res);
            return;
        }

        std::string objectPath = "/xyz/openbmc_project/state/chassis0";

        /* Look for system reset chassis path */
        if ((std::find(chassisList.begin(), chassisList.end(), objectPath)) ==
            chassisList.end())
        {
            /*
             * The default on systems is chassis0 for the power state.
             * On systems that dont have chassis0, we can use chassis_system0
             */
            objectPath = "/xyz/openbmc_project/state/chassis_system0";
        }

        managedStore::ManagedObjectStoreContext context(aResp);
        dbus_utils::getProperty<std::string>(
            "xyz.openbmc_project.State.Chassis", objectPath,
            "xyz.openbmc_project.State.Chassis", "CurrentPowerState", context,
            [aResp{std::move(aResp)}](const boost::system::error_code& ec2,
                                      const std::string& chassisState) {
            if (ec2)
            {
                if (ec2 == boost::system::errc::host_unreachable)
                {
                    // Service not available, no error, just don't return
                    // chassis state info
                    BMCWEB_LOG_DEBUG << "Service not available " << ec2;
                    return;
                }
                BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
                messages::internalError(aResp->res);
                return;
            }

            BMCWEB_LOG_DEBUG << "Chassis state: " << chassisState;
            // Verify Chassis State
            if (chassisState ==
                "xyz.openbmc_project.State.Chassis.PowerState.On")
            {
                aResp->res.jsonValue["PowerState"] = "On";
                aResp->res.jsonValue["Status"]["State"] = "Enabled";
            }
            else if (chassisState ==
                     "xyz.openbmc_project.State.Chassis.PowerState.Off")
            {
                aResp->res.jsonValue["PowerState"] = "Off";
                aResp->res.jsonValue["Status"]["State"] = "StandbyOffline";
            }
            });
        });
}

inline void getIntrusionByService(std::shared_ptr<bmcweb::AsyncResp> aResp,
                                  const std::string& service,
                                  const std::string& objPath)
{
    BMCWEB_LOG_DEBUG << "Get intrusion status by service \n";

    managedStore::ManagedObjectStoreContext context(aResp);
    dbus_utils::getProperty<std::string>(
        service, objPath, "xyz.openbmc_project.Chassis.Intrusion", "Status",
        context,
        [aResp{std::move(aResp)}](const boost::system::error_code& ec,
                                  const std::string& value) {
        if (ec)
        {
            // do not add err msg in redfish response, because this is not
            //     mandatory property
            BMCWEB_LOG_ERROR << "DBUS response error " << ec << "\n";
            return;
        }

        aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensorNumber"] = 1;
        aResp->res.jsonValue["PhysicalSecurity"]["IntrusionSensor"] = value;
        });
}

/**
 * Retrieves physical security properties over dbus
 */
inline void getPhysicalSecurityData(std::shared_ptr<bmcweb::AsyncResp> aResp)
{
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Chassis.Intrusion"};
    managedStore::ManagedObjectStoreContext requestContext(aResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/Intrusion", 1, interfaces, requestContext,
        [aResp{std::move(aResp)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            // do not add err msg in redfish response, because this is not
            //     mandatory property
            BMCWEB_LOG_INFO << "DBUS error: no matched iface " << ec << "\n";
            return;
        }
        // Iterate over all retrieved ObjectPaths.
        for (const auto& object : subtree)
        {
            for (const auto& service : object.second)
            {
                getIntrusionByService(aResp, service.first, object.first);
                return;
            }
        }
        });
}

inline void handleChassisCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    asyncResp->res.jsonValue["@odata.type"] =
        "#ChassisCollection.ChassisCollection";
    asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Chassis";
    asyncResp->res.jsonValue["Name"] = "Chassis Collection";

    constexpr std::array<std::string_view, 2> interfaces{
        "xyz.openbmc_project.Inventory.Item.Board",
        "xyz.openbmc_project.Inventory.Item.Chassis"};
    collection_util::getCollectionMembers(
        asyncResp, boost::urls::url("/redfish/v1/Chassis"), interfaces);
}

inline nlohmann::json&
    getChassisContainsArray(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    nlohmann::json& jValue = asyncResp->res.jsonValue["Links"]["Contains"];
    if (!jValue.is_array())
    {
        jValue = nlohmann::json::array();
        asyncResp->res.jsonValue["Links"]["Contains@odata.count"] =
            jValue.size();
    }
    return jValue;
}

// Hack in the Contains relationships
inline void addHardcodedRelationships(
    const std::string& chassisId,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    if constexpr (bmcwebEnableRdeDevice)
    {
        if (chassisId == platform6Chassis0)
        {
            nlohmann::json& jValue = getChassisContainsArray(asyncResp);
            const std::vector<std::string> backplaneTrays = {
                "2HMMCS_Tray",
            };
            for (const std::string& tray : backplaneTrays)
            {
                jValue.emplace_back(
                    nlohmann::json({{"@odata.id", "/redfish/v1/Chassis/" + tray}}));
            }
            asyncResp->res.jsonValue["Links"]["Contains@odata.count"] =
                jValue.size();
        }
    }
}
// End Hack

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

    sdbusplus::message::object_path upstreamChassisPath(
        upstreamChassisPaths[0]);
    std::string upstreamChassis = upstreamChassisPath.filename();
    if (upstreamChassis.empty())
    {
        BMCWEB_LOG_WARNING << "Malformed upstream Chassis path "
                           << upstreamChassisPath.str << " on " << chassisId;
        return;
    }

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

inline void getChassisContains(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const boost::system::error_code& ec,
    const dbus::utility::MapperEndPoints& downstreamChassisPaths)
{
    if (ec)
    {
        if (ec.value() != EBADR)
        {
            BMCWEB_LOG_ERROR << "DBUS response error " << ec;
            messages::internalError(asyncResp->res);
        }
        return;
    }
    if (downstreamChassisPaths.empty())
    {
        return;
    }

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    for (const auto& chassisPath : downstreamChassisPaths)
    {
        sdbusplus::message::object_path downstreamChassisPath(chassisPath);
        const std::string downstreamChassis = downstreamChassisPath.filename();
        if (downstreamChassis.empty())
        {
            BMCWEB_LOG_WARNING << "Malformed downstream Chassis path "
                               << downstreamChassisPath.str << " on "
                               << chassisId;
            continue;
        }
        managedStore::GetManagedObjectStore()->getDbusObject(
            chassisPath, {}, requestContext,
            [asyncResp,
             downstreamChassis](const boost::system::error_code& ec2,
                                const dbus::utility::MapperGetObject& object) {
            if (ec2)
            {
                BMCWEB_LOG_DEBUG << "DBUS response error";
                messages::internalError(asyncResp->res);
                return;
            }

            // Link must be a Chassis or Board
            constexpr std::array<std::string_view, 2> chassisInterfaces = {
                "xyz.openbmc_project.Inventory.Item.Chassis",
                "xyz.openbmc_project.Inventory.Item.Board",
            };

            if (!redfish::dbus_utils::findInterfacesInServiceMap(
                    object, chassisInterfaces))
            {
                return;
            }

            nlohmann::json& jValue =
                asyncResp->res.jsonValue["Links"]["Contains"];
            if (!jValue.is_array())
            {
                // Create the array if it was empty
                jValue = nlohmann::json::array();
            }
            nlohmann::json link;
            link["@odata.id"] = "/redfish/v1/Chassis/" + downstreamChassis;
            jValue.emplace_back(std::move(link));
            asyncResp->res.jsonValue["Links"]["Contains@odata.count"] =
                jValue.size();
        });
    }
}

inline void
    getChassisConnectivity(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& chassisId,
                           const std::string& chassisPath)
{
    BMCWEB_LOG_DEBUG << "Get chassis connectivity";

    if constexpr (bmcwebEnableRdeDevice)
    {
        // Hack in Chassis links
        addHardcodedRelationships(chassisId, asyncResp);
        // End Hack
    }
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);

    // Chassis Dbus interfaces. They are the same types when we enumerate the
    // Chassis Collection.
    constexpr std::array<std::string_view, 2> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Board",
        "xyz.openbmc_project.Inventory.Item.Chassis"};

    managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
        chassisPath + "/contained_by", {"/xyz/openbmc_project/inventory"}, 0,
        interfaces, requestContext,
        std::bind_front(getChassisContainedBy, asyncResp, chassisId));

    managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
        chassisPath + "/containing", {"/xyz/openbmc_project/inventory"}, 0,
        interfaces, requestContext,
        std::bind_front(getChassisContains, asyncResp, chassisId));
}

inline void getChassisCableAssociation(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisPath)
{
    BMCWEB_LOG_DEBUG << "Get chassis -- cable association";

    managedStore::ManagedObjectStoreContext context(asyncResp);
    dbus_utils::getProperty<std::vector<std::string>>(
        "xyz.openbmc_project.ObjectMapper", chassisPath + "/attached_cables",
        "xyz.openbmc_project.Association", "endpoints", context,
        [asyncResp](const boost::system::error_code ec,
                    const std::vector<std::string>& cableList) {
        if (ec)
        {
            return;
        }

        if (cableList.empty())
        {
            return;
        }
        nlohmann::json& jValue = asyncResp->res.jsonValue["Links"]["Cables"];
        jValue = nlohmann::json::array();
        for (const std::string& cable : cableList)
        {
            sdbusplus::message::object_path cablePath(cable);
            std::string cableName = cablePath.filename();
            if (cable.empty())
            {
                BMCWEB_LOG_ERROR << "filename() is empty in " << cable;
                continue;
            }
            jValue.emplace_back(
                nlohmann::json({{"@odata.id", "/redfish/v1/Cables/" + cableName}}));
        }
        asyncResp->res.jsonValue["Links"]["Cables@odata.count"] =
            cableList.size();
        });
}

inline void getChassisProcessorAssociation(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisPath, bool multiHost)
{

    BMCWEB_LOG_DEBUG << "Get chassis -- processor association";

    managedStore::ManagedObjectStoreContext context(asyncResp);
    dbus_utils::getProperty<std::vector<std::string>>(
        "xyz.openbmc_project.ObjectMapper", chassisPath + "/processors",
        "xyz.openbmc_project.Association", "endpoints", context,
        [asyncResp, multiHost](const boost::system::error_code ec,
                    const std::vector<std::string>& processors) {
        if (ec)
        {
            return;
        }
        nlohmann::json& jValue =
            asyncResp->res.jsonValue["Links"]["Processors"];
        jValue = nlohmann::json::array();
        for (const std::string& processor : processors)
        {
            sdbusplus::message::object_path processorPath(processor);
            std::string processorName = processorPath.filename();
            if (processorName.empty())
            {
                BMCWEB_LOG_ERROR << "filename() is empty in " << processor;
                continue;
            }

            // Special way of determining processor path for single vs multihost
            if(!multiHost){
                jValue.emplace_back(
                    nlohmann::json({{"@odata.id",
                    "/redfish/v1/Systems/system/Processors/" + processorName}}));
                continue;
            }
            // The 3rd parent is the systemId for processor in multihost machines
            std::string systemId = processorPath.parent_path().parent_path().parent_path().filename();
                jValue.emplace_back(
                    nlohmann::json({{"@odata.id",
                    crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                                systemId, "Processors", processorName)}}));
        }

        std::sort(jValue.begin(), jValue.end());

        asyncResp->res.jsonValue["Links"]["Processors@odata.count"] =
            processors.size();
        });
}

inline void getChassisMemoryAssociationSingleSystem(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisPath)
{

    BMCWEB_LOG_DEBUG << "Get chassis -- memory association";

    managedStore::ManagedObjectStoreContext context(asyncResp);
    dbus_utils::getProperty<std::vector<std::string>>(
        "xyz.openbmc_project.ObjectMapper", chassisPath + "/memories",
        "xyz.openbmc_project.Association", "endpoints", context,
        [asyncResp](const boost::system::error_code ec,
                    const std::vector<std::string>& memories) {
        if (ec)
        {
            return;
        }

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

        /* Redfish Chassis schema uses memory collection here. Only
         * motherboard would have such association. Hardcode the system
         * memory collection odata.id
         */
        asyncResp->res.jsonValue["Memory"] = {
            {"@odata.id", "/redfish/v1/Systems/system/Memory"}};
        });
}

/**
 * Handles System related properties
 *
 * * On single-system system, a chassis will be default to the
 * only system w/ or w/o dedicated association.
 *
 * * On multi-system system, a chassis requires an association to
 * the target system or otherwise the chassis will be linked to all
 * systems on the system
 */
inline void
    getChassisSystem(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                     const std::string& chassisPath)
{
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/", 0, redfish::system_utils::systemInterfaces, requestContext,
        [asyncResp, chassisPath](const boost::system::error_code& ec,
                                 const std::vector<std::string>& objects) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error";
            messages::internalError(asyncResp->res);
            return;
        }
        // If there are less than 2 Item.Systems assume singlehost
        if (objects.size() < 2)
        {
            // Perform SingleSystem Only Actions
            getChassisMemoryAssociationSingleSystem(asyncResp, chassisPath);
            getChassisProcessorAssociation(asyncResp, chassisPath, false);
            asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                             "system", "PCIeDevices");

            nlohmann::json::object_t system;
            system["@odata.id"] = "/redfish/v1/Systems/system";
            asyncResp->res.jsonValue["Links"]["ComputerSystems"].emplace_back(
                system);
            return;
        }
        // Otherwise find chassis -> system association
        managedStore::ManagedObjectStoreContext requestContext(asyncResp);
        managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
            chassisPath + "/contained_by", {"/xyz/openbmc_project/inventory"},
            0, system_utils::systemInterfaces, requestContext,
            [asyncResp, systemPaths{objects}
             // default the systemPath to all systems
        ](const boost::system::error_code& ec,
            const std::vector<std::string>& assocPaths) mutable {
            if (ec)
            {
                BMCWEB_LOG_DEBUG
                    << "DBUS response error on getting association for system/chassis";
                messages::internalError(asyncResp->res);
                return;
            }

            // override the default w/ associated systems
            if (!assocPaths.empty())
            {
                systemPaths = assocPaths;
            }

            for_each(systemPaths.begin(), systemPaths.end(),
                     [asyncResp](const std::string& path) {
                nlohmann::json::object_t system;
                system["@odata.id"] =
                    std::filesystem::path("/redfish/v1/Systems") /
                    std::filesystem::path(path).filename();
                asyncResp->res.jsonValue["Links"]["ComputerSystems"]
                    .emplace_back(system);
            });
        });

        // Perform mulithost only actions
        getChassisProcessorAssociation(asyncResp, chassisPath, true);
    });
}
/**
 * ChassisCollection derived class for delivering Chassis Collection Schema
 *  Functions triggers appropriate requests on DBus
 */
inline void requestRoutesChassisCollection(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/")
        .privileges(redfish::privileges::getChassisCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleChassisCollectionGet, std::ref(app)));
}

inline std::optional<std::string>
    getChassisTypeProperty(const std::variant<std::string>& property)
{
    const std::string* value = std::get_if<std::string>(&property);
    if (value == nullptr)
    {
        return std::nullopt;
    }

    if (*value ==
        "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Component")
    {
        return "Component";
    }
    if (*value ==
        "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Enclosure")
    {
        return "Enclosure";
    }
    if (*value ==
        "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Module")
    {
        return "Module";
    }
    if (*value ==
        "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.RackMount")
    {
        return "RackMount";
    }
    if (*value == "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType."
                  "StandAlone")
    {
        return "StandAlone";
    }
    if (*value == "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType."
                  "StorageEnclosure")
    {
        return "StorageEnclosure";
    }
    if (*value == "xyz.openbmc_project.Inventory.Item.Chassis.ChassisType.Zone")
    {
        return "Zone";
    }

    return std::nullopt;
}

inline void addChassisReset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                            const std::string& chassisId,
                            const std::optional<std::string>& chassisType)
{
    // If chassisType is nullopt, then use the deault type of RackMount.
    if (chassisType)
    {
        asyncResp->res.jsonValue["ChassisType"] = *chassisType;
    }

    // Only Default, RackMount, or StandAlone will have Reset Action.
    if (chassisType && *chassisType != "RackMount" &&
        *chassisType != "StandAlone")
    {
        BMCWEB_LOG_INFO
            << "Chassis Type is not supported. Only support Chassis Reset on RackMount or StandAlone.";
        return;
    }

    asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] =
        crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId,
                                     "Actions", "Chassis.Reset");
    asyncResp->res
        .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] =
        crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId,
                                     "ResetActionInfo");
}

inline void getChassisType(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& connectionName, const std::string& path,
    std::function<void(const boost::system::error_code ec,
                             const std::variant<std::string>&)>&& callback)
{
    managedStore::ManagedObjectStoreContext context(asyncResp);
    dbus_utils::getProperty<std::string>(
        connectionName, path,
        "xyz.openbmc_project.Inventory.Item.Chassis", "Type",
        context,
        [callback{std::move(callback)}](boost::system::error_code ec,
                   const std::string& val) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG
                << "Failed to get Chassis Type. Set ec to 0 in callback.";

            callback(boost::system::error_code(),
                     std::variant<std::string>{""});
            return;
        }
        callback(ec, val);
        });
}

inline void
    getChassisLocationCode(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& connectionName,
                           const std::string& path)
{
    managedStore::ManagedObjectStoreContext context(asyncResp);
    dbus_utils::getProperty<std::string>(
        connectionName, path,
        "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
        context,
        [asyncResp](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;
        });
}

inline void getChassisUUID(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& connectionName,
                           const std::string& path)
{
    managedStore::ManagedObjectStoreContext context(asyncResp);
    dbus_utils::getProperty<std::string>(
        connectionName, path, "xyz.openbmc_project.Common.UUID", "UUID",
        context,
        [asyncResp](const boost::system::error_code& ec,
                    const std::string& chassisUUID) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error for UUID";
            messages::internalError(asyncResp->res);
            return;
        }
        asyncResp->res.jsonValue["UUID"] = chassisUUID;
        });
}

inline void
    handleChassisGet(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, 2> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Board",
        "xyz.openbmc_project.Inventory.Item.Chassis"};

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, chassisId(std::string(chassisId)), requestContext](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            messages::internalError(asyncResp->res);
            return;
        }
        // Iterate over all retrieved ObjectPaths.
        for (const std::pair<
                 std::string,
                 std::vector<std::pair<std::string, std::vector<std::string>>>>&
                 object : subtree)
        {
            const std::string& path = object.first;
            const std::vector<std::pair<std::string, std::vector<std::string>>>&
                connectionNames = object.second;

            sdbusplus::message::object_path objPath(path);
            if (objPath.filename() != chassisId)
            {
                continue;
            }
            getChassisConnectivity(asyncResp, chassisId, path);
            getChassisCableAssociation(asyncResp, path);
            getChassisSystem(asyncResp, path);

            auto health = std::make_shared<HealthPopulate>(asyncResp);

#ifdef HEALTH_POPULATE
            dbus_utils::getAssociationEndPoints(
                path + "/all_sensors", requestContext,
                [health](const boost::system::error_code& ec2,
                         const dbus::utility::MapperEndPoints& resp) {
                if (ec2)
                {
                    return; // no sensors = no failures
                }
                health->inventory = resp;
            });

            health->populate();
#endif

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

            asyncResp->res.jsonValue["@odata.type"] =
                "#Chassis.v1_17_0.Chassis";
            asyncResp->res.jsonValue["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                             chassisId);
            asyncResp->res.jsonValue["Name"] = "Chassis Collection";
            asyncResp->res.jsonValue["ChassisType"] = "RackMount";

            asyncResp->res.jsonValue["Certificates"]["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                             chassisId, "Certificates");
            asyncResp->res.jsonValue["TrustedComponents"]["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                             chassisId, "TrustedComponents");

            dbus_utils::getAssociationEndPoints(
                path + "/drive", requestContext,
                [asyncResp,
                 chassisId](const boost::system::error_code& ec3,
                            const dbus::utility::MapperEndPoints& resp) {
                if (ec3 || resp.empty())
                {
                    return; // no drives = no failures
                }

                nlohmann::json reference;
                reference["@odata.id"] = crow::utility::urlFromPieces(
                    "redfish", "v1", "Chassis", chassisId, "Drives");
                asyncResp->res.jsonValue["Drives"] = std::move(reference);
            });

            dbus_utils::getProperty<std::string>(
                "xyz.openbmc_project.EntityManager",
                "/xyz/openbmc_project/inventory/system/board/" + chassisId +
                    "/BmcNet",
                "xyz.openbmc_project.Configuration.BmcNet", "Name",
                requestContext,
                [asyncResp, path,
                 chassisId](const boost::system::error_code& ec3,
                            const std::string& bmcNetName) {
                if (ec3 || bmcNetName != "BmcNet")
                {
                    managedStore::ManagedObjectStoreContext requestContextInner(
                        asyncResp);
                    // non-bmc chassis
                    dbus_utils::getAssociationEndPoints(
                        path + "/network_adapter", requestContextInner,
                        [asyncResp, chassisId](
                            const boost::system::error_code& ec4,
                            const dbus::utility::MapperEndPoints& resp) {
                        if (ec4 || resp.empty())
                        {
                            return; // no networkadapters = no failures
                        }

                        nlohmann::json reference;
                        reference["@odata.id"] = crow::utility::urlFromPieces(
                            "redfish", "v1", "Chassis", chassisId,
                            "NetworkAdapters");
                        asyncResp->res.jsonValue["NetworkAdapters"] =
                            std::move(reference);
                    });
                    return;
                }
                // bmc chassis
                nlohmann::json reference;
                reference["@odata.id"] = crow::utility::urlFromPieces(
                    "redfish", "v1", "Chassis", chassisId, "NetworkAdapters");
                asyncResp->res.jsonValue["NetworkAdapters"] =
                    std::move(reference);
            });

            managedStore::ManagedObjectStoreContext context(asyncResp);
            const std::string& connectionName = connectionNames[0].first;

            const std::vector<std::string>& interfaces2 =
                connectionNames[0].second;
            const std::array<const char*, 2> hasIndicatorLed = {
                "xyz.openbmc_project.Inventory.Item.Panel",
                "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};

            const std::string assetTagInterface =
                "xyz.openbmc_project.Inventory.Decorator.AssetTag";
            const std::string revisionInterface =
                "xyz.openbmc_project.Inventory.Decorator.Revision";
            for (const auto& interface : interfaces2)
            {
                if (interface == assetTagInterface)
                {
                    dbus_utils::getProperty<std::string>(
                        connectionName, path, assetTagInterface, "AssetTag",
                        context,
                        [asyncResp, chassisId(std::string(chassisId))](
                            const boost::system::error_code& ec2,
                            const std::string& property) {
                        if (ec2)
                        {
                            BMCWEB_LOG_DEBUG <<
                                "DBus response error for AssetTag";
                            messages::internalError(asyncResp->res);
                            return;
                        }
                        asyncResp->res.jsonValue["AssetTag"] = property;
                    });
                }
                else if (interface == revisionInterface)
                {
                    dbus_utils::getProperty<std::string>(
                        connectionName, path, revisionInterface, "Version",
                        context,
                        [asyncResp, chassisId](
                            const boost::system::error_code& ec2,
                            const std::string& property) {
                        if (ec2)
                        {
                            BMCWEB_LOG_ERROR <<
                                "DBus response error for Version: " << ec2;
                            messages::internalError(asyncResp->res);
                            return;
                        }
                        asyncResp->res.jsonValue["Version"] = property;
                    });
                }
            }

            for (const char* interface : hasIndicatorLed)
            {
                if (std::find(interfaces2.begin(), interfaces2.end(),
                              interface) != interfaces2.end())
                {
                    getIndicatorLedState(asyncResp);
                    getLocationIndicatorActive(asyncResp);
                    break;
                }
            }

            managedStore::GetManagedObjectStore()->getAllProperties(
                connectionName, path,
                "xyz.openbmc_project.Inventory.Decorator.Asset", context,
                [asyncResp, chassisId(std::string(chassisId)),
                 path](const boost::system::error_code& /*ec2*/,
                       const dbus::utility::DBusPropertiesMap& propertiesList) {
                const std::string* partNumber = nullptr;
                const std::string* serialNumber = nullptr;
                const std::string* manufacturer = nullptr;
                const std::string* model = nullptr;
                const std::string* sparePartNumber = nullptr;

                const bool success = sdbusplus::unpackPropertiesNoThrow(
                    dbus_utils::UnpackErrorPrinter(), propertiesList,
                    "PartNumber", partNumber, "SerialNumber", serialNumber,
                    "Manufacturer", manufacturer, "Model", model,
                    "SparePartNumber", sparePartNumber);

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

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

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

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

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

                // SparePartNumber is optional on D-Bus
                // so skip if it is empty
                if (sparePartNumber != nullptr && !sparePartNumber->empty())
                {
                    asyncResp->res.jsonValue["SparePartNumber"] =
                        *sparePartNumber;
                }

                if constexpr (bmcwebEnableRdeDevice)
                {
                    // Hack in the ContainedBy fields
                    const std::regex rdeTrayRegex(".*Tray");
                    if (std::regex_match(chassisId, rdeTrayRegex))
                    {
                        // TODO(b/273682625): platform6Chassis1 Trays are cabled
                        // instead of contained
                        asyncResp->res.jsonValue["Links"]["ContainedBy"] = {
                            {"@odata.id", "/redfish/v1/Chassis/" +
                                              std::string(platform6Chassis0)}};
                    }
                    // End Hack
                }

                if constexpr (enablePlatform9)
                {
                    // Hack in the Cables
                    if (chassisId == platform9Chassis2)
                    {
                        nlohmann::json::array_t attachedCables;
                        nlohmann::json::object_t cab;
                        cab["@odata.id"] = "/redfish/v1/Cables/" +
                                           std::string(platform9Cable4);
                        attachedCables.emplace_back(std::move(cab));
                        asyncResp->res.jsonValue["Links"]["Cables"] =
                            std::move(attachedCables);
                    }
                    if (chassisId == platform9Chassis0)
                    {
                        nlohmann::json::array_t attachedCables;
                        nlohmann::json::object_t cab;
                        nlohmann::json::object_t cat;
                        cat["@odata.id"] = "/redfish/v1/Cables/cat5_cable";
                        attachedCables.emplace_back(std::move(cat));
                        cab["@odata.id"] = "/redfish/v1/Cables/" +
                                           std::string(platform9Cable0);
                        attachedCables.emplace_back(std::move(cab));
                        asyncResp->res.jsonValue["Links"]["Cables"] =
                            std::move(attachedCables);
                    }
                    if (chassisId == platform9Chassis3)
                    {
                        nlohmann::json::array_t attachedCables;
                        nlohmann::json::object_t cab;
                        nlohmann::json::object_t cab1;
                        cab["@odata.id"] = "/redfish/v1/Cables/" +
                                           std::string(platform9Cable2);
                        cab1["@odata.id"] = "/redfish/v1/Cables/" +
                                            std::string(platform9Cable3);
                        attachedCables.emplace_back(std::move(cab));
                        attachedCables.emplace_back(std::move(cab1));
                        asyncResp->res.jsonValue["Links"]["Cables"] =
                            std::move(attachedCables);
                    }
                    // Hack in containing satellite Chassis
                    if (chassisId == platform9Chassis4)
                    {
                        nlohmann::json& jValue =
                            asyncResp->res.jsonValue["Links"]["Contains"];
                        jValue = nlohmann::json::array();
                        jValue.emplace_back(
                            nlohmann::json({{"@odata.id",
                              "/redfish/v1/Chassis/5B247A_" +
                                  std::string(platform9Chassis5)}}));
                        asyncResp->res
                            .jsonValue["Links"]["Contains@odata.count"] =
                            jValue.size();
                    }
                    // End of workarounds
                }

                asyncResp->res.jsonValue["Name"] = chassisId;
                asyncResp->res.jsonValue["Id"] = chassisId;
#ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
                asyncResp->res.jsonValue["Thermal"]["@odata.id"] =
                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                                 chassisId, "Thermal");
                // Power object
                asyncResp->res.jsonValue["Power"]["@odata.id"] =
                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                                 chassisId, "Power");
#endif
                asyncResp->res.jsonValue["Assembly"] = {
                    {"@odata.id",
                     crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                                  chassisId, "Assembly")
                         .buffer()}};

#ifdef BMCWEB_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM
                asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] =
                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                                 chassisId, "ThermalSubsystem");
                asyncResp->res.jsonValue["PowerSubsystem"]["@odata.id"] =
                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                                 chassisId, "PowerSubsystem");
                asyncResp->res.jsonValue["EnvironmentMetrics"]["@odata.id"] =
                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                                 chassisId,
                                                 "EnvironmentMetrics");
#endif
                // SensorCollection
                asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                                 chassisId, "Sensors");
                asyncResp->res.jsonValue["Status"]["State"] = "Enabled";

                asyncResp->res.jsonValue["PCIeSlots"]["@odata.id"] =
                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                                 chassisId, "PCIeSlots");

                nlohmann::json::array_t managedBy;
                nlohmann::json::object_t manager;
                manager["@odata.id"] = "/redfish/v1/Managers/bmc";
                managedBy.emplace_back(std::move(manager));
                asyncResp->res.jsonValue["Links"]["ManagedBy"] =
                    std::move(managedBy);
                getChassisState(asyncResp);
                getStorageLinkFromChassis(asyncResp, path);
                });

            bool hasChassisInterface = false;
            for (const auto& interface : interfaces2)
            {
                if (interface == "xyz.openbmc_project.Common.UUID")
                {
                    getChassisUUID(asyncResp, connectionName, path);
                }
                else if (interface ==
                         "xyz.openbmc_project.Inventory.Decorator.LocationCode")
                {
                    location_util::getLocationCode(asyncResp, connectionName,
                                                   path,
                                                   "/Location"_json_pointer);
                }
                else if (location_util::isConnector(interface))
                {
                    std::optional<std::string> locationType =
                        location_util::getLocationType(interface);
                    if (!locationType)
                    {
                        BMCWEB_LOG_DEBUG
                            << "getLocationType for Chassis failed for "
                            << interface;
                        continue;
                    }
                    asyncResp->res
                        .jsonValue["Location"]["PartLocation"]["LocationType"] =
                        *locationType;
                }
                else if (interface ==
                             "xyz.openbmc_project.Inventory.Item.Chassis" ||
                         interface ==
                             "xyz.openbmc_project.Inventory.Item.Board")
                {
                    hasChassisInterface = true;
                    getChassisType(
                        asyncResp, connectionName, path,
                        [asyncResp,
                         chassisId](const boost::system::error_code ec2,
                                    const std::variant<std::string>& property) {
                        if (ec2)
                        {
                            messages::internalError(asyncResp->res);
                            return;
                        }
                        addChassisReset(asyncResp, chassisId,
                                        getChassisTypeProperty(property));
                        });
                }
            }

            if (hasChassisInterface)
            {
                location_util::getPartLocationContext(asyncResp,
                                                      "/Location"_json_pointer,
                                                      path + "/contained_by");
            }
            else
            {
                location_util::getPartLocationContext(
                    asyncResp, "/Location"_json_pointer, path + "/chassis");
                // Item.Chassis interface is not available
                // Enable Reset Action by default.
                addChassisReset(asyncResp, chassisId, std::nullopt);
            }
            return;
        }

        // Couldn't find an object with that name.  return an error
        messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
        });

    getPhysicalSecurityData(asyncResp);
}

inline void
    handleChassisPatch(App& app, const crow::Request& req,
                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::string& param)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    std::optional<bool> locationIndicatorActive;
    std::optional<std::string> indicatorLed;

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

    if (!json_util::readJsonPatch(
            req, asyncResp->res, "LocationIndicatorActive",
            locationIndicatorActive, "IndicatorLED", indicatorLed))
    {
        return;
    }

    // TODO (Gunnar): Remove IndicatorLED after enough time has passed
    if (!locationIndicatorActive && !indicatorLed)
    {
        return; // delete this when we support more patch properties
    }
    if (indicatorLed)
    {
        asyncResp->res.addHeader(
            boost::beast::http::field::warning,
            "299 - \"IndicatorLED is deprecated. Use LocationIndicatorActive instead.\"");
    }

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

    const std::string& chassisId = param;

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, chassisId, locationIndicatorActive,
         indicatorLed](const boost::system::error_code& ec,
                       const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            messages::internalError(asyncResp->res);
            return;
        }

        // Iterate over all retrieved ObjectPaths.
        for (const std::pair<
                 std::string,
                 std::vector<std::pair<std::string, std::vector<std::string>>>>&
                 object : subtree)
        {
            const std::string& path = object.first;
            const std::vector<std::pair<std::string, std::vector<std::string>>>&
                connectionNames = object.second;

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

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

            const std::vector<std::string>& interfaces3 =
                connectionNames[0].second;

            const std::array<const char*, 2> hasIndicatorLed = {
                "xyz.openbmc_project.Inventory.Item.Panel",
                "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
            bool indicatorChassis = false;
            for (const char* interface : hasIndicatorLed)
            {
                if (std::find(interfaces3.begin(), interfaces3.end(),
                              interface) != interfaces3.end())
                {
                    indicatorChassis = true;
                    break;
                }
            }
            if (locationIndicatorActive)
            {
                if (indicatorChassis)
                {
                    setLocationIndicatorActive(asyncResp,
                                               *locationIndicatorActive);
                }
                else
                {
                    messages::propertyUnknown(asyncResp->res,
                                              "LocationIndicatorActive");
                }
            }
            if (indicatorLed)
            {
                if (indicatorChassis)
                {
                    setIndicatorLedState(asyncResp, *indicatorLed);
                }
                else
                {
                    messages::propertyUnknown(asyncResp->res, "IndicatorLED");
                }
            }
            return;
        }

        messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
        });
}

/**
 * Chassis override class for delivering Chassis Schema
 * Functions triggers appropriate requests on DBus
 */
inline void requestRoutesChassis(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
        .privileges(redfish::privileges::getChassis)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleChassisGet, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/")
        .privileges(redfish::privileges::patchChassis)
        .methods(boost::beast::http::verb::patch)(
            std::bind_front(handleChassisPatch, std::ref(app)));
}

void delayResetCN(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       int delayTimeSecs);

inline void
    doChassisPowerCycle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        std::optional<int> delayTimeSecs)
{
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.State.Chassis"};

    // Use mapper to get subtree paths.
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/", 0, interfaces, requestContext,
        [asyncResp, delayTimeSecs](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreePathsResponse& chassisList) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "[mapper] Bad D-Bus request error: " << ec;
            messages::internalError(asyncResp->res);
            return;
        }

        const char* processName = "xyz.openbmc_project.State.Chassis";
        const char* interfaceName = "xyz.openbmc_project.State.Chassis";
        const char* destProperty = "RequestedPowerTransition";
        const std::string propertyValue =
            "xyz.openbmc_project.State.Chassis.Transition.PowerCycle";
        std::string objectPath = "/xyz/openbmc_project/state/chassis_system0";

        /* Look for system reset chassis path */
        if ((std::find(chassisList.begin(), chassisList.end(), objectPath)) ==
            chassisList.end())
        {
            /* We prefer to reset the full chassis_system, but if it doesn't
             * exist on some platforms, fall back to a host-only power reset
             */
            objectPath = "/xyz/openbmc_project/state/chassis0";
        }

        if (delayTimeSecs.has_value())
        {
            if (delayTimeSecs.value() > KMAX_RESET_DELAY_SEC)
            {
                BMCWEB_LOG_ERROR
                    << "chassis reset delay out of range, request: "
                    << delayTimeSecs.value() << " expect: 0-"
                    << KMAX_RESET_DELAY_SEC << " seconds";
                messages::propertyValueOutOfRange(
                    asyncResp->res, "delay",
                    std::to_string(KMAX_RESET_DELAY_SEC));
                return;
            }
            delayResetCN(asyncResp, delayTimeSecs.value());
            return;
        }
        managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
            asyncResp->strand_,
            [asyncResp](const boost::system::error_code& ec2) {
            // Use "Set" method to set the property value.
            if (ec2)
            {
                BMCWEB_LOG_DEBUG << "[Set] Bad D-Bus request error: " << ec2;
                messages::internalError(asyncResp->res);
                return;
            }

            messages::success(asyncResp->res);
            },
            processName, objectPath, "org.freedesktop.DBus.Properties", "Set",
            interfaceName, destProperty,
            dbus::utility::DbusVariantType{propertyValue});
    });
}

/**
 * validateChassisResetAction checks the Chassis type to ensure the Chassis
 * supports Chassis Reset.
 *
 * Checks the Chassis type for `RackMount` or `StandAlone` for Chassis Reset.
 * Otherwise, reset is not supported.
 */
inline void validateChassisResetAction(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId,
    std::function<void(const boost::system::error_code ec,
                             const std::variant<std::string>&)>&& callback)
{
    std::array<std::string_view, 2> interfaces{
        "xyz.openbmc_project.Inventory.Item.Board",
        "xyz.openbmc_project.Inventory.Item.Chassis"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, chassisId,
         callback(std::move(callback))](const boost::system::error_code ec,
                   const dbus::utility::MapperGetSubTreeResponse& subtree) mutable {
        if (ec)
        {
            callback(ec, std::variant<std::string>{""});
            return;
        }

        for (const std::pair<
                 std::string,
                 std::vector<std::pair<std::string, std::vector<std::string>>>>&
                 object : subtree)
        {
            sdbusplus::message::object_path path(object.first);
            if (path.filename() != chassisId)
            {
                continue;
            }

            const std::vector<std::pair<std::string, std::vector<std::string>>>&
                connectionNames = object.second;

            if (connectionNames.empty())
            {
                BMCWEB_LOG_ERROR << "Got 0 Connection names";
                continue;
            }
            getChassisType(asyncResp, connectionNames[0].first, path.str, std::move(callback));
            return;
        }
        messages::resourceNotFound(asyncResp->res, "#Chassis.v1_14_0.Chassis",
                                   chassisId);
        });
}

inline void validateChassisResetActionHandler(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    std::optional<std::string> resetType,
    const std::optional<int> delayTimeSecs, const boost::system::error_code ec,
    const std::variant<std::string>& property)
{
    if (ec)
    {
        messages::internalError(asyncResp->res);
        return;
    }

    std::optional<std::string> chassisType = getChassisTypeProperty(property);

    if (chassisType && *chassisType != "RackMount" &&
        *chassisType != "StandAlone")
    {
        messages::actionNotSupported(
            asyncResp->res, "Only RackMount or StandAlone support Chassis "
                            "Reset. Got Chassis type of " +
                                *chassisType);

        return;
    }

    if (resetType && *resetType != "PowerCycle")
    {
        BMCWEB_LOG_DEBUG << "Invalid property value for "
                            "ResetType: "
                         << *resetType;
        messages::actionParameterNotSupported(asyncResp->res, *resetType,
                                              "ResetType");

        return;
    }
    doChassisPowerCycle(asyncResp, delayTimeSecs);
}

inline void handleChassisResetActionInfoPost(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    BMCWEB_LOG_DEBUG << "Post Chassis Reset.";

    std::optional<std::string> resetType;
    std::optional<int> delayTimeSecs;
    if(!json_util::readJsonAction(req, asyncResp->res, "ResetType", resetType,
                              "Delay", delayTimeSecs))
    {
        return;
    }
    validateChassisResetAction(
        asyncResp, chassisId,
        std::bind_front(validateChassisResetActionHandler, asyncResp, resetType,
                        delayTimeSecs));
}

/**
 * ChassisResetAction class supports the POST method for the Reset
 * action.
 * Function handles POST method request.
 * Analyzes POST body before sending Reset request data to D-Bus.
 */

inline void requestRoutesChassisResetAction(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Actions/Chassis.Reset/")
        .privileges(redfish::privileges::postChassis)
        .methods(boost::beast::http::verb::post)(
            std::bind_front(handleChassisResetActionInfoPost, std::ref(app)));
}

inline void validateChassisResetActionInfoHandler(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const boost::system::error_code ec,
    const std::variant<std::string>& property)
{
    asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "ResetActionInfo");
    asyncResp->res.jsonValue["Name"] = "Reset Action Info";
    asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
    nlohmann::json::array_t parameters;
    nlohmann::json::object_t parameter;
    parameter["Name"] = "ResetType";
    parameter["Required"] = true;
    parameter["DataType"] = "String";
    nlohmann::json::array_t allowed;
    allowed.emplace_back("PowerCycle");

    nlohmann::json::object_t delaySecsParameter;
    // argument names are consistent with system delay
    delaySecsParameter["Name"] = "Delay";
    delaySecsParameter["Required"] = false;
    delaySecsParameter["DataType"] = "Number";

    // xyz.openbmc_project.Inventory.Item.Chassis not found on the Chassis
    // Default to PowerCycle
    if (ec)
    {
        parameter["AllowableValues"] = std::move(allowed);
        parameters.emplace_back(std::move(parameter));
        parameters.emplace_back(std::move(delaySecsParameter));
        asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
        return;
    }

    std::optional<std::string> chassisType = getChassisTypeProperty(property);
    if (chassisType && *chassisType != "RackMount" &&
        *chassisType != "StandAlone")
    {
        BMCWEB_LOG_DEBUG << "Only RackMount support Chassis Reset. Got "
                            "Chassis type of "
                         << *chassisType;

        // Remove PowerCycle as allowed value.
        allowed.pop_back();
    }

    parameter["AllowableValues"] = std::move(allowed);
    parameters.emplace_back(std::move(parameter));
    parameters.emplace_back(std::move(delaySecsParameter));
    asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
}

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

/**
 * ChassisResetActionInfo derived class for delivering Chassis
 * ResetType AllowableValues using ResetInfo schema.
 */
inline void requestRoutesChassisResetActionInfo(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ResetActionInfo/")
        .privileges(redfish::privileges::getActionInfo)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleChassisResetActionInfoGet, std::ref(app)));
}

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

    chassis_utils::getValidChassisPath(
        asyncResp, chassisId,
        [asyncResp, chassisId](const std::optional<std::string>& path) {
        if (!path)
        {
            messages::resourceNotFound(asyncResp->res,
                                       "#Chassis.v1_16_0.Chassis", chassisId);
            return;
        }
        boost::urls::url assemblyId = crow::utility::urlFromPieces(
            "redfish", "v1", "Chassis", chassisId, "Assembly");
        getAssembly(asyncResp, assemblyId, *path);
        });
}

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

} // namespace redfish
