#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_DBUS_UTILS_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_DBUS_UTILS_H_

#include <algorithm>
#include <cstdint>
#include <functional>
#include <set>
#include <span>  // NOLINT
#include <string>
#include <string_view>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <variant>
#include <vector>

#include "logging.hpp"
#include "dbus_utility.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/exception.hpp"
#include "sdbusplus/message/native_types.hpp"
// Remove unpack_properties header. Have to have this header
// now since there are other files indirectly depending on this header and they
// haven't been ported to g3 yet.
#include "sdbusplus/unpack_properties.hpp"  // NOLINT

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

namespace redfish {
namespace dbus_utils {

struct UnpackErrorPrinter {
  void operator()(const sdbusplus::UnpackErrorReason reason,
                  const std::string& property) const noexcept {
    BMCWEB_LOG_ERROR
        << "DBUS property error in property: " << property << ", reason: "
        << static_cast<std::underlying_type_t<sdbusplus::UnpackErrorReason>>(
               reason);
  }
};

inline void getPropertiesFromManagedObjects(
    const dbus::utility::ManagedObjectType& managedObjects,
    const std::string& objPath, const std::string& interface,
    dbus::utility::DBusPropertiesMap& properties) {
  for (const auto& object : managedObjects) {
    if (object.first.str != objPath) {
      continue;
    }

    for (const auto& interface_map : object.second) {
      if (interface_map.first != interface) {
        continue;
      }
      properties = interface_map.second;
    }
  }
}

// Populates |serviceNames| list with unique services found in the given
// subtree.
inline std::vector<std::string> getServiceNamesFromSubtree(
    const dbus::utility::MapperGetSubTreeResponse& subtree) {
  std::set<std::string> unique_service_names;
  for (const auto& [_, serviceMap] : subtree) {
    for (const auto& service_pair : serviceMap) {
      unique_service_names.insert(service_pair.first);
    }
  }
  return {unique_service_names.begin(), unique_service_names.end()};
}

// Checks if any one of given interfaces is present in the service map.
inline bool findInterfacesInServiceMap(
    const dbus::utility::MapperServiceMap& serviceMap,
    std::span<const std::string_view> interfaces) {
  for (const auto& [service_name, interfaceList] : serviceMap) {  // NOLINT
    if (std::find_first_of(interfaceList.begin(), interfaceList.end(),
                           interfaces.begin(),
                           interfaces.end()) != interfaceList.end()) {
      return true;
    }
  }
  return false;
}

/**
 * Recursively gets managed objects under given object path from each service in
 * the given list of service names and maps objects to the service name they
 * originate from.
 *
 * @param[in] serviceList               Mutable list of unique service names.
 * @param[in] objPath                   Managed objects are requested relative
 *                                      to this path.
 * @param[in,out] managed_objects_by_service   Service name to managed objects
 * map.
 * @param[in] callback                  Callback to execute after getting
 *                                      managed objects from all service names
 *                                      in the list.
 */
template <typename Callback>
inline void getManagedObjectsInEachServiceCallback(
    std::vector<std::string>&& serviceList,
    const sdbusplus::message::object_path& objPath,
    std::unordered_map<std::string, dbus::utility::ManagedObjectType>&&
        managed_objects_by_service,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback) {
  BMCWEB_LOG_DEBUG << "GetManagedObjects from next service in list.";
  if (serviceList.empty()) {
    BMCWEB_LOG_DEBUG << "Recieved managed objects from all services.";
    callback(managed_objects_by_service);
    return;
  }
  std::string service_name = serviceList.back();
  serviceList.pop_back();

  managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
      service_name, objPath, context,
      [serviceList{std::move(serviceList)}, service_name, objPath,
       managed_objects_by_service{std::move(managed_objects_by_service)},
       context = context, callback{std::forward<Callback>(callback)}](
          const boost::system::error_code& ec,
          const dbus::utility::ManagedObjectType& managedObjects) mutable {
        if (!ec) {
          managed_objects_by_service[service_name] = managedObjects;
        }
        getManagedObjectsInEachServiceCallback(
            std::move(serviceList), objPath,
            std::move(managed_objects_by_service), context,
            std::forward<decltype(callback)>(callback));
      });
}

/**
 * Gets managed objects under given object path from each service in the given
 * list of service names.
 *
 * @param[in] serviceList               Mutable list of unique service names.
 * @param[in] objPath                   Managed objects are requested relative
 *                                      to this path.
 * @param[in] callback                  Callback to execute after getting
 *                                      managed objects from all service names
 *                                      in the list.
 */
template <typename Callback>
inline void getManagedObjectsInEachService(
    std::vector<std::string>&& serviceList,
    const sdbusplus::message::object_path& objPath,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback) {
  BMCWEB_LOG_DEBUG << "Requesting managed objects from given list of "
                   << "services ";
  std::unordered_map<std::string, dbus::utility::ManagedObjectType>
      managed_objects_by_service;
  if (serviceList.empty()) {
    BMCWEB_LOG_ERROR << "Service list is empty";
    callback(managed_objects_by_service);
    return;
  }
  std::string service_name = serviceList.back();
  serviceList.pop_back();

  managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
      service_name, objPath, context,
      [serviceList{std::move(serviceList)}, service_name, objPath,
       managed_objects_by_service{std::move(managed_objects_by_service)},
       context = context, callback{std::forward<Callback>(callback)}](
          const boost::system::error_code& ec,
          const dbus::utility::ManagedObjectType& managedObjects) mutable {
        if (!ec) {
          managed_objects_by_service[service_name] = managedObjects;
        }
        getManagedObjectsInEachServiceCallback(
            std::move(serviceList), objPath,
            std::move(managed_objects_by_service), context,
            std::forward<decltype(callback)>(callback));
      });
}

template <typename PropertyType>
void getProperty(const std::string& service, const std::string& path,
                 const std::string& interface, const std::string& property,
                 const managedStore::ManagedObjectStoreContext& requestContext,
                 std::function<void(const boost::system::error_code&,
                                    const PropertyType&)>&& callback) {
  managedStore::KeyType key_type(managedStore::ManagedType::kManagedProperty,
                                 service, {path}, interface, property);
  BMCWEB_LOG_STATEFUL_DEBUG << "getProperty: Key " << key_type.toString()
                            << " requestContext " << requestContext.toString();

  managedStore::GetManagedObjectStore()->getProperty(
      key_type, requestContext,
      [callback{std::move(callback)}](
          const boost::system::error_code& ec,
          const dbus::utility::DbusVariantType& managedProperty,
          [[maybe_unused]] uint64_t age_ms) {
        if (ec) {
          callback(ec, {});
          return;
        }
        const PropertyType* propertyValue =
            std::get_if<PropertyType>(&managedProperty);
        if (propertyValue) {
          callback(ec, *propertyValue);
          return;
        }
        callback(boost::system::errc::make_error_code(
                     boost::system::errc::invalid_argument),
                 {});
      });
}

template <typename PropertyType>
void getProperty(
    const std::string& service, const std::string& path,
    const std::string& interface, const std::string& property,
    const managedStore::ManagedObjectStoreContext& requestContext,
    std::function<void(const boost::system::error_code&, const PropertyType&,
                       uint64_t)>&& callback) {
  managedStore::KeyType key_type(managedStore::ManagedType::kManagedProperty,
                                 service, {path}, interface, property);
  BMCWEB_LOG_STATEFUL_DEBUG << "getProperty: Key " << key_type.toString()
                            << " requestContext " << requestContext.toString();

  managedStore::GetManagedObjectStore()->getProperty(
      key_type, requestContext,
      [callback{std::move(callback)}](
          const boost::system::error_code& ec,
          const dbus::utility::DbusVariantType& managedProperty,
          uint64_t age_ms) {
        if (ec) {
          callback(ec, {}, 0);
          return;
        }
        const PropertyType* propertyValue =
            std::get_if<PropertyType>(&managedProperty);
        if (propertyValue) {
          callback(ec, *propertyValue, age_ms);
          return;
        }
        callback(boost::system::errc::make_error_code(
                     boost::system::errc::invalid_argument),
                 {}, 0);
      });
}

inline void getAssociationEndPoints(
    const std::string& path,
    const managedStore::ManagedObjectStoreContext& requestContext,
    std::function<void(const boost::system::error_code&,
                       const dbus::utility::MapperEndPoints&)>&& callback) {
  getProperty<dbus::utility::MapperEndPoints>(
      "xyz.openbmc_project.ObjectMapper", {path},
      "xyz.openbmc_project.Association", "endpoints", requestContext,
      std::move(callback));
}

template <typename Callback>
inline void checkDbusPathExists(
    const std::string& path,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback) {
  managedStore::GetManagedObjectStore()->getDbusObject(
      path, {}, context,
      [callback{std::forward<Callback>(callback)}](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetObject& objectNames) {
        callback(!ec && !objectNames.empty());
      });
}

template <typename Callback>
inline void getAssociatedSubTree(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback) {
  managedStore::GetManagedObjectStore()->getAssociatedSubTree(
      associatedPath, path, depth, interfaces, context,
      std::forward<Callback>(callback));
}

template <typename Callback>
inline void getAssociatedSubTreePaths(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback) {
  managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
      associatedPath, path, depth, interfaces, context,
      std::forward<Callback>(callback));
}

template <typename Callback>
inline void getSubTree(const std::string& path, int32_t depth,
                       std::span<const std::string_view> interfaces,
                       const managedStore::ManagedObjectStoreContext& context,
                       Callback&& callback) {
  managedStore::GetManagedObjectStore()->getSubTree(
      path, depth, interfaces, context, std::forward<Callback>(callback));
}

// Overload to support span of strings for interface names.
template <typename Callback>
inline void getSubTree(const std::string& path, int32_t depth,
                       std::span<std::string> interfaces,
                       const managedStore::ManagedObjectStoreContext& context,
                       Callback&& callback) {
  managedStore::GetManagedObjectStore()->getSubTree(
      path, depth, interfaces, context, std::forward<Callback>(callback));
}

template <typename Callback>
inline void getSubTreePaths(
    const std::string& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback) {
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      path, depth, interfaces, context, std::forward<Callback>(callback));
}

template <typename Callback>
inline void getManagedObjects(
    const std::string& service, const sdbusplus::message::object_path& path,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback) {
  managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
      service, path, context, std::forward<Callback>(callback));
}

template <typename Callback>
inline void getDbusObject(
    const std::string& path, std::span<const std::string_view> interfaces,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback) {
  managedStore::GetManagedObjectStore()->getDbusObject(
      path, interfaces, context, std::forward<Callback>(callback));
}

}  // namespace dbus_utils
}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_DBUS_UTILS_H_
