#pragma once

#include "constants.hpp"
#include "exceptions.hpp"
#include "logger.hpp"
#include "types.hpp"

#include <chrono>

namespace vpd
{
/**
 * @brief The namespace defines utlity methods for generic D-Bus operations.
 */
namespace dbusUtility
{

/**
 * @brief An API to get Map of service and interfaces for an object path.
 *
 * The API returns a Map of service name and interfaces for a given pair of
 * object path and interface list. It can be used to determine service name
 * which implemets a particular object path and interface.
 *
 * Note: It will be caller's responsibility to check for empty map returned and
 * generate appropriate error.
 *
 * @param [in] objectPath - Object path under the service.
 * @param [in] interfaces - Array of interface(s).
 * @return - A Map of service name to object to interface(s), if success.
 *           If failed,  empty map.
 */
inline types::MapperGetObject getObjectMap(const std::string& objectPath,
                                           std::span<const char*> interfaces)
{
    types::MapperGetObject getObjectMap;

    // interface list is optional argument, hence no check required.
    if (objectPath.empty())
    {
        logging::logMessage("Path value is empty, invalid call to GetObject");
        return getObjectMap;
    }

    try
    {
        auto bus = sdbusplus::bus::new_default();
        auto method = bus.new_method_call(
            "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetObject");

        method.append(objectPath, interfaces);
        auto result = bus.call(method);
        result.read(getObjectMap);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        // logging::logMessage(e.what());
        return getObjectMap;
    }

    return getObjectMap;
}

/**
 * @brief An API to get property map for an interface.
 *
 * This API returns a map of property and its value with respect to a particular
 * interface.
 *
 * Note: It will be caller's responsibility to check for empty map returned and
 * generate appropriate error.
 *
 * @param[in] i_service - Service name.
 * @param[in] i_objectPath - object path.
 * @param[in] i_interface - Interface, for the properties to be listed.
 *
 * @return - A map of property and value of an interface, if success.
 *           if failed, empty map.
 */
inline types::PropertyMap getPropertyMap(const std::string& i_service,
                                         const std::string& i_objectPath,
                                         const std::string& i_interface)
{
    types::PropertyMap l_propertyValueMap;
    if (i_service.empty() || i_objectPath.empty() || i_interface.empty())
    {
        logging::logMessage("Invalid parameters to get property map");
        return l_propertyValueMap;
    }

    try
    {
        auto l_bus = sdbusplus::bus::new_default();
        auto l_method =
            l_bus.new_method_call(i_service.c_str(), i_objectPath.c_str(),
                                  "org.freedesktop.DBus.Properties", "GetAll");
        l_method.append(i_interface);
        auto l_result = l_bus.call(l_method);
        l_result.read(l_propertyValueMap);
    }
    catch (const sdbusplus::exception::SdBusError& l_ex)
    {
        logging::logMessage(l_ex.what());
    }

    return l_propertyValueMap;
}

/**
 * @brief API to get object subtree from D-bus.
 *
 * The API returns the map of object, services and interfaces in the
 * subtree that implement a certain interface. If no interfaces are provided
 * then all the objects, services and interfaces under the subtree will
 * be returned.
 *
 * Note: Depth can be 0 and interfaces can be null.
 * It will be caller's responsibility to check for empty vector returned
 * and generate appropriate error.
 *
 * @param[in] i_objectPath - Path to search for an interface.
 * @param[in] i_depth - Maximum depth of the tree to search.
 * @param[in] i_interfaces - List of interfaces to search.
 *
 * @return - A map of object and its related services and interfaces, if
 *           success. If failed, empty map.
 */

inline types::MapperGetSubTree getObjectSubTree(
    const std::string& i_objectPath, const int& i_depth,
    const std::vector<std::string>& i_interfaces)
{
    types::MapperGetSubTree l_subTreeMap;

    if (i_objectPath.empty())
    {
        logging::logMessage("Object path is empty.");
        return l_subTreeMap;
    }

    try
    {
        auto l_bus = sdbusplus::bus::new_default();
        auto l_method = l_bus.new_method_call(
            constants::objectMapperService, constants::objectMapperPath,
            constants::objectMapperInf, "GetSubTree");
        l_method.append(i_objectPath, i_depth, i_interfaces);
        auto l_result = l_bus.call(l_method);
        l_result.read(l_subTreeMap);
    }
    catch (const sdbusplus::exception::SdBusError& l_ex)
    {
        logging::logMessage(l_ex.what());
    }

    return l_subTreeMap;
}

/**
 * @brief An API to read property from Dbus.
 *
 * The caller of the API needs to validate the validatity and correctness of the
 * type and value of data returned. The API will just fetch and retun the data
 * without any data validation.
 *
 * Note: It will be caller's responsibility to check for empty value returned
 * and generate appropriate error if required.
 *
 * @param [in] serviceName - Name of the Dbus service.
 * @param [in] objectPath - Object path under the service.
 * @param [in] interface - Interface under which property exist.
 * @param [in] property - Property whose value is to be read.
 * @return - Value read from Dbus, if success.
 *           If failed, empty variant.
 */
inline types::DbusVariantType readDbusProperty(
    const std::string& serviceName, const std::string& objectPath,
    const std::string& interface, const std::string& property)
{
    types::DbusVariantType propertyValue;

    // Mandatory fields to make a read dbus call.
    if (serviceName.empty() || objectPath.empty() || interface.empty() ||
        property.empty())
    {
        logging::logMessage(
            "One of the parameter to make Dbus read call is empty.");
        return propertyValue;
    }

    try
    {
        auto bus = sdbusplus::bus::new_default();
        auto method =
            bus.new_method_call(serviceName.c_str(), objectPath.c_str(),
                                "org.freedesktop.DBus.Properties", "Get");
        method.append(interface, property);

        auto result = bus.call(method);
        result.read(propertyValue);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        return propertyValue;
    }
    return propertyValue;
}

/**
 * @brief An API to write property on Dbus.
 *
 * The caller of this API needs to handle exception thrown by this method to
 * identify any write failure. The API in no other way indicate write  failure
 * to the caller.
 *
 * @param [in] serviceName - Name of the Dbus service.
 * @param [in] objectPath - Object path under the service.
 * @param [in] interface - Interface under which property exist.
 * @param [in] property - Property whose value is to be written.
 * @param [in] propertyValue - The value to be written.
 * @return True if write on DBus is success, false otherwise.
 */
inline bool writeDbusProperty(
    const std::string& serviceName, const std::string& objectPath,
    const std::string& interface, const std::string& property,
    const types::DbusVariantType& propertyValue)
{
    try
    {
        // Mandatory fields to make a write dbus call.
        if (serviceName.empty() || objectPath.empty() || interface.empty() ||
            property.empty())
        {
            throw std::runtime_error("Dbus write failed, Parameter empty");
        }

        auto bus = sdbusplus::bus::new_default();
        auto method =
            bus.new_method_call(serviceName.c_str(), objectPath.c_str(),
                                "org.freedesktop.DBus.Properties", "Set");
        method.append(interface, property, propertyValue);
        bus.call(method);

        return true;
    }
    catch (const std::exception& l_ex)
    {
        logging::logMessage(
            "DBus write failed, error: " + std::string(l_ex.what()));
        return false;
    }
}

/**
 * @brief API to publish data on PIM
 *
 * The API calls notify on PIM object to publlish VPD.
 *
 * @param[in] objectMap - Object, its interface and data.
 * @return bool - Status of call to PIM notify.
 */
inline bool callPIM(types::ObjectMap&& objectMap)
{
    try
    {
        for (const auto& l_objectKeyValue : objectMap)
        {
            auto l_nodeHandle = objectMap.extract(l_objectKeyValue.first);

            if (l_nodeHandle.key().str.find(constants::pimPath, 0) !=
                std::string::npos)
            {
                l_nodeHandle.key() = l_nodeHandle.key().str.replace(
                    0, std::strlen(constants::pimPath), "");
                objectMap.insert(std::move(l_nodeHandle));
            }
        }

        auto bus = sdbusplus::bus::new_default();
        auto pimMsg =
            bus.new_method_call(constants::pimServiceName, constants::pimPath,
                                constants::pimIntf, "Notify");
        pimMsg.append(std::move(objectMap));
        bus.call(pimMsg);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        return false;
    }
    return true;
}

/**
 * @brief API to check if a D-Bus service is running or not.
 *
 * Any failure in calling the method "NameHasOwner" implies that the service is
 * not in a running state. Hence the API returns false in case of any exception
 * as well.
 *
 * @param[in] i_serviceName - D-Bus service name whose status is to be checked.
 * @return bool - True if the service is running, false otherwise.
 */
inline bool isServiceRunning(const std::string& i_serviceName)
{
    bool l_retVal = false;

    try
    {
        auto l_bus = sdbusplus::bus::new_default();
        auto l_method = l_bus.new_method_call(
            "org.freedesktop.DBus", "/org/freedesktop/DBus",
            "org.freedesktop.DBus", "NameHasOwner");
        l_method.append(i_serviceName);

        l_bus.call(l_method).read(l_retVal);
    }
    catch (const sdbusplus::exception::SdBusError& l_ex)
    {
        logging::logMessage(
            "Call to check service status failed with exception: " +
            std::string(l_ex.what()));
    }

    return l_retVal;
}

/**
 * @brief API to call "GetAttribute" method uner BIOS manager.
 *
 * The API reads the given attribuute from BIOS and returns a tuple of both
 * current as well as pending value for that attribute.
 * The API return only the current attribute value if found.
 * API returns an empty variant of type BiosAttributeCurrentValue in case of any
 * error.
 *
 * @param[in] i_attributeName - Attribute to be read.
 * @return Tuple of PLDM attribute Type, current attribute value and pending
 * attribute value.
 */
inline types::BiosAttributeCurrentValue biosGetAttributeMethodCall(
    const std::string& i_attributeName)
{
    auto l_bus = sdbusplus::bus::new_default();
    auto l_method = l_bus.new_method_call(
        constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
        constants::biosConfigMgrInterface, "GetAttribute");
    l_method.append(i_attributeName);

    types::BiosGetAttrRetType l_attributeVal;
    try
    {
        auto l_result = l_bus.call(l_method);
        l_result.read(std::get<0>(l_attributeVal), std::get<1>(l_attributeVal),
                      std::get<2>(l_attributeVal));
    }
    catch (const sdbusplus::exception::SdBusError& l_ex)
    {
        logging::logMessage(
            "Failed to read BIOS Attribute: " + i_attributeName +
            " due to error " + std::string(l_ex.what()));

        // TODO: Log an informational PEL here.
    }

    return std::get<1>(l_attributeVal);
}

/**
 * @brief API to check if Chassis is powered on.
 *
 * This API queries Phosphor Chassis State Manager to know whether
 * Chassis is powered on.
 *
 * @return true if chassis is powered on, false otherwise
 */
inline bool isChassisPowerOn()
{
    auto powerState = dbusUtility::readDbusProperty(
        "xyz.openbmc_project.State.Chassis",
        "/xyz/openbmc_project/state/chassis0",
        "xyz.openbmc_project.State.Chassis", "CurrentPowerState");

    if (auto curPowerState = std::get_if<std::string>(&powerState))
    {
        if ("xyz.openbmc_project.State.Chassis.PowerState.On" == *curPowerState)
        {
            return true;
        }
        return false;
    }

    /*
        TODO: Add PEL.
        Callout: Firmware callout
        Type: Informational
        Description: Chassis state can't be determined, defaulting to chassis
        off. : e.what()
    */
    return false;
}

/**
 * @brief API to check if host is in running state.
 *
 * This API reads the current host state from D-bus and returns true if the host
 * is running.
 *
 * @return true if host is in running state. false otherwise.
 */
inline bool isHostRunning()
{
    const auto l_hostState = dbusUtility::readDbusProperty(
        constants::hostService, constants::hostObjectPath,
        constants::hostInterface, "CurrentHostState");

    if (const auto l_currHostState = std::get_if<std::string>(&l_hostState))
    {
        if (*l_currHostState == constants::hostRunningState)
        {
            return true;
        }
    }

    return false;
}

/**
 * @brief API to check if BMC is in ready state.
 *
 * This API reads the current state of BMC from D-bus and returns true if BMC is
 * in ready state.
 *
 * @return true if BMC is ready, false otherwise.
 */
inline bool isBMCReady()
{
    const auto l_bmcState = dbusUtility::readDbusProperty(
        constants::bmcStateService, constants::bmcZeroStateObject,
        constants::bmcStateInterface, constants::currentBMCStateProperty);

    if (const auto l_currBMCState = std::get_if<std::string>(&l_bmcState))
    {
        if (*l_currBMCState == constants::bmcReadyState)
        {
            return true;
        }
    }

    return false;
}

/**
 * @brief An API to enable BMC reboot guard
 *
 * This API does a D-Bus method call to enable BMC reboot guard.
 *
 * @return On success, returns 0, otherwise returns -1.
 */
inline int EnableRebootGuard() noexcept
{
    int l_rc{constants::FAILURE};
    try
    {
        auto l_bus = sdbusplus::bus::new_default();
        auto l_method = l_bus.new_method_call(
            constants::systemdService, constants::systemdObjectPath,
            constants::systemdManagerInterface, "StartUnit");
        l_method.append("reboot-guard-enable.service", "replace");
        l_bus.call_noreply(l_method);
        l_rc = constants::SUCCESS;
    }
    catch (const sdbusplus::exception::SdBusError& l_ex)
    {
        std::string l_errMsg =
            "D-Bus call to enable BMC reboot guard failed for reason: ";
        l_errMsg += l_ex.what();

        logging::logMessage(l_errMsg);
    }
    return l_rc;
}

/**
 * @brief An API to disable BMC reboot guard
 *
 * This API disables BMC reboot guard. This API has an inbuilt re-try mechanism.
 * If Disable Reboot Guard fails, this API attempts to Disable Reboot Guard for
 * 3 more times at an interval of 333ms.
 *
 * @return On success, returns 0, otherwise returns -1.
 */
inline int DisableRebootGuard() noexcept
{
    int l_rc{constants::FAILURE};

    // A lambda which executes the DBus call to disable BMC reboot guard.
    auto l_executeDisableRebootGuard = []() -> int {
        int l_dBusCallRc{constants::FAILURE};
        try
        {
            auto l_bus = sdbusplus::bus::new_default();
            auto l_method = l_bus.new_method_call(
                constants::systemdService, constants::systemdObjectPath,
                constants::systemdManagerInterface, "StartUnit");
            l_method.append("reboot-guard-disable.service", "replace");
            l_bus.call_noreply(l_method);
            l_dBusCallRc = constants::SUCCESS;
        }
        catch (const sdbusplus::exception::SdBusError& l_ex)
        {}
        return l_dBusCallRc;
    };

    if (constants::FAILURE == l_executeDisableRebootGuard())
    {
        std::function<void()> l_retryDisableRebootGuard;

        // A lambda which tries to disable BMC reboot guard for 3 times at an
        // interval of 333 ms.
        l_retryDisableRebootGuard = [&]() {
            constexpr int MAX_RETRIES{3};
            static int l_numRetries{0};

            if (l_numRetries < MAX_RETRIES)
            {
                l_numRetries++;
                if (constants::FAILURE == l_executeDisableRebootGuard())
                {
                    // sleep for 333ms before next retry. This is just a random
                    // value so that 3 re-tries * 333ms takes ~1 second in the
                    // worst case.
                    const std::chrono::milliseconds l_sleepTime{333};
                    std::this_thread::sleep_for(l_sleepTime);
                    l_retryDisableRebootGuard();
                }
                else
                {
                    l_numRetries = 0;
                    l_rc = constants::SUCCESS;
                }
            }
            else
            {
                // Failed to Disable Reboot Guard even after 3 retries.
                logging::logMessage("Failed to Disable Reboot Guard after " +
                                    std::to_string(MAX_RETRIES) + " re-tries");
                l_numRetries = 0;
            }
        };

        l_retryDisableRebootGuard();
    }
    else
    {
        l_rc = constants::SUCCESS;
    }
    return l_rc;
}

/**
 * @brief API to notify FRU VPD Collection status.
 *
 * This API uses PIM's Notify method to update the given FRU VPD collection
 * status on D-bus.
 *
 * @param[in] i_inventoryPath - D-bus inventory path
 * @param[in] i_fruCollectionStatus - FRU VPD collection status.
 *
 * @return true if update succeeds, false otherwise.
 */
inline bool notifyFRUCollectionStatus(const std::string& i_inventoryPath,
                                      const std::string& i_fruCollectionStatus)
{
    types::ObjectMap l_objectMap;
    types::InterfaceMap l_interfaceMap;
    types::PropertyMap l_propertyMap;

    l_propertyMap.emplace("CollectionStatus", i_fruCollectionStatus);
    l_interfaceMap.emplace(constants::vpdCollectionInterface, l_propertyMap);
    l_objectMap.emplace(i_inventoryPath, l_interfaceMap);

    if (!dbusUtility::callPIM(std::move(l_objectMap)))
    {
        return false;
    }

    return true;
}

/**
 * @brief API to read IM keyword from Dbus.
 *
 * @return IM value read from Dbus, Empty in case of any error.
 */
inline types::BinaryVector getImFromDbus()
{
    const auto& l_retValue = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::vsbpInf, constants::kwdIM);

    auto l_imValue = std::get_if<types::BinaryVector>(&l_retValue);
    if (!l_imValue || (*l_imValue).size() != constants::VALUE_4)
    {
        return types::BinaryVector{};
    }

    return *l_imValue;
}

/**
 * @brief API to return prefix of functional firmware image.
 *
 * Every functional image belongs to a series which is denoted by the first two
 * characters of the image name. The API extracts that and returns it to the
 * caller.
 *
 * @return Two character string, empty string in case of any error.
 */
inline std::string getImagePrefix()
{
    try
    {
        types::DbusVariantType l_retVal = readDbusProperty(
            constants::objectMapperService, constants::functionalImageObjPath,
            constants::associationInterface, "endpoints");

        auto l_listOfFunctionalPath =
            std::get_if<std::vector<std::string>>(&l_retVal);

        if (!l_listOfFunctionalPath || (*l_listOfFunctionalPath).empty())
        {
            throw DbusException("failed to get functional image path.");
        }

        for (const auto& l_imagePath : *l_listOfFunctionalPath)
        {
            types::DbusVariantType l_retValPriority =
                readDbusProperty(constants::imageUpdateService, l_imagePath,
                                 constants::imagePrirotyInf, "Priority");

            auto l_imagePriority = std::get_if<uint8_t>(&l_retValPriority);
            if (!l_imagePriority)
            {
                throw DbusException(
                    "failed to read functional image priority for path [" +
                    l_imagePath + "]");
            }

            // only interested in running image.
            if (*l_imagePriority != constants::VALUE_0)
            {
                continue;
            }

            types::DbusVariantType l_retExVer = readDbusProperty(
                constants::imageUpdateService, l_imagePath,
                constants::imageExtendedVerInf, "ExtendedVersion");

            auto l_imageExtendedVersion = std::get_if<std::string>(&l_retExVer);
            if (!l_imageExtendedVersion)
            {
                throw DbusException(
                    "Unable to read extended version for the functional image [" +
                    l_imagePath + "]");
            }

            if ((*l_imageExtendedVersion).empty() ||
                (*l_imageExtendedVersion).length() <= constants::VALUE_2)
            {
                throw DbusException("Invalid extended version read for path [" +
                                    l_imagePath + "]");
            }

            // return first two character from image name.
            return (*l_imageExtendedVersion)
                .substr(constants::VALUE_0, constants::VALUE_2);
        }
        throw std::runtime_error("No Image found with required priority.");
    }
    catch (const std::exception& l_ex)
    {
        logging::logMessage(l_ex.what());
        return std::string{};
    }
}
} // namespace dbusUtility
} // namespace vpd
