#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_CHASSIS_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_CHASSIS_H_

/*
// 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.
*/
#include <array>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include <regex>  // NOLINT
#include <vector>
#include <variant>
#include <filesystem>  // NOLINT
#include <cstddef>
#include <optional>
#include <string_view>
#include <algorithm>

#include "utility.hpp"
#include "boost/system/error_code.hpp"  // NOLINT
#include "bmcweb_config.h"
#include "app.hpp"
#include "logging.hpp"
#include "http_request.hpp"
#include "error_messages.hpp"
#include <nlohmann/json.hpp>
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "chassis_utils.hpp"
#include "collection.hpp"
#include "sdbusplus/message/native_types.hpp"
#include "dbus_utils.hpp"
#include "json_utils.hpp"
#include "location_utils.hpp"
#include "storage_utils.hpp"
#include "system_utils.hpp"
#include "assembly.hpp"
#include "health.hpp"
#include "led.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/unpack_properties.hpp"

#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) {  // NOLINT
            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

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_CHASSIS_H_
