#include "config.h"

#include <attn/attn_dbus.hpp>
#include <attn/attn_dump.hpp>
#include <attn/attn_logging.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/exception.hpp>
#include <util/dbus.hpp>
#include <util/trace.hpp>

constexpr uint64_t dumpTimeout = 3600000000; // microseconds

constexpr auto operationStatusInProgress =
    "xyz.openbmc_project.Common.Progress.OperationStatus.InProgress";

namespace attn
{

/**
 *  Callback for dump request properties change signal monitor
 *
 * @param[in] i_msg         Dbus message from the dbus match infrastructure
 * @param[out] o_dumpStatus Dump status dbus response string
 * @return Always non-zero indicating no error, no cascading callbacks
 */
uint dumpStatusChanged(sdbusplus::message_t& i_msg, std::string& o_dumpStatus)
{
    // reply (msg) will be a property change message
    std::string interface;
    std::map<std::string, std::variant<std::string, uint8_t>> property;
    i_msg.read(interface, property);

    // looking for property Status changes
    std::string propertyType = "Status";
    auto dumpStatus = property.find(propertyType);

    if (dumpStatus != property.end())
    {
        const std::string* status =
            std::get_if<std::string>(&(dumpStatus->second));

        if (nullptr != status)
        {
            o_dumpStatus = *status;
        }
    }

    return 1; // non-negative return code for successful callback
}

/**
 * Register a callback for dump progress status changes
 *
 * @param[in] i_path The object path of the dump to monitor
 */
void monitorDump(const std::string& i_path)
{
    // setup the signal match rules and callback
    std::string matchInterface = "xyz.openbmc_project.Common.Progress";
    auto bus = sdbusplus::bus::new_system();

    // monitor dump status change property, will update dumpStatus
    std::string dumpStatus = "requested";
    std::unique_ptr<sdbusplus::bus::match_t> match =
        std::make_unique<sdbusplus::bus::match_t>(
            bus,
            sdbusplus::bus::match::rules::propertiesChanged(
                i_path.c_str(), matchInterface.c_str()),
            [&](auto& msg) { return dumpStatusChanged(msg, dumpStatus); });

    // wait for dump status to be completed (complete == true)
    trace::inf("dump requested %s", i_path.c_str());

    // wait for dump status not InProgress or timeout
    uint64_t timeRemaining = dumpTimeout;

    std::chrono::steady_clock::time_point begin =
        std::chrono::steady_clock::now();

    while (("requested" == dumpStatus ||
            operationStatusInProgress == dumpStatus) &&
           0 != timeRemaining)
    {
        bus.wait(timeRemaining);
        uint64_t timeElapsed =
            std::chrono::duration_cast<std::chrono::microseconds>(
                std::chrono::steady_clock::now() - begin)
                .count();

        timeRemaining =
            timeElapsed > timeRemaining ? 0 : timeRemaining - timeElapsed;

        bus.process_discard();
    }

    if (0 == timeRemaining)
    {
        trace::err("dump request timed out after %" PRIu64 " microseconds",
                   dumpTimeout);
    }

    trace::inf("dump status: %s", dumpStatus.c_str());
}

/** Api used to enable or disable watchdog dbus property */
void enableWatchdog(bool enable)
{
    constexpr auto service = "xyz.openbmc_project.Watchdog";
    constexpr auto object = "/xyz/openbmc_project/watchdog/host0";
    constexpr auto interface = "xyz.openbmc_project.State.Watchdog";
    constexpr auto property = "Enabled";
    util::dbus::setProperty<bool>(service, object, interface, property, enable);
}

/** Request a dump from the dump manager */
void requestDump(uint32_t i_logId, const DumpParameters& i_dumpParameters)
{
    constexpr auto interface = "xyz.openbmc_project.Dump.Create";
    constexpr auto function = "CreateDump";

    sdbusplus::message_t method;
    bool watchdogDisabled = false;

    if (0 == dbusMethod(OP_DUMP_OBJ_PATH, interface, function, method))
    {
        try
        {
            // During a checkstop attention, the system is not functioning
            // normally. So a hardware or hostboot dump is collected and it
            // could take a while to get completed. So disable the watchdog when
            // the dump collection is in progress.
            if (DumpType::Hostboot == i_dumpParameters.dumpType ||
                DumpType::Hardware == i_dumpParameters.dumpType)
            {
                watchdogDisabled = true;
                enableWatchdog(false);
            }
            // dbus call arguments
            std::map<std::string, std::variant<std::string, uint64_t>>
                createParams;
            createParams["com.ibm.Dump.Create.CreateParameters.ErrorLogId"] =
                uint64_t(i_logId);
            if (DumpType::Hostboot == i_dumpParameters.dumpType)
            {
                createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
                    "com.ibm.Dump.Create.DumpType.Hostboot";
            }
            else if (DumpType::Hardware == i_dumpParameters.dumpType)
            {
                createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
                    "com.ibm.Dump.Create.DumpType.Hardware";
                createParams
                    ["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] =
                        i_dumpParameters.unitId;
            }
            else if (DumpType::SBE == i_dumpParameters.dumpType)
            {
                createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
                    "com.ibm.Dump.Create.DumpType.SBE";
                createParams
                    ["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] =
                        i_dumpParameters.unitId;
            }
            method.append(createParams);

            // using system dbus
            auto bus = sdbusplus::bus::new_system();
            auto response = bus.call(method);

            // reply will be type dbus::ObjectPath
            sdbusplus::message::object_path reply;
            response.read(reply);

            // monitor dump progress
            monitorDump(reply);
        }
        catch (const sdbusplus::exception::SdBusError& e)
        {
            trace::err("requestDump exception");
            trace::err(e.what());
        }

        if (watchdogDisabled)
        {
            // Dump collection is over, enable the watchdog
            enableWatchdog(true);
        }
    }
}

} // namespace attn
