#include "psm_handler.hpp"

#include "log.hpp"

#include <fmt/printf.h>

#include <variant>

namespace boot_time_monitor
{
namespace psm
{

namespace btm = boot_time_monitor;

using BasicVariantType =
    std::variant<std::vector<std::string>, std::string, int64_t, uint64_t,
                 double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>;

std::string inline translateHostStateName(std::string_view state)
{
    std::size_t found = state.find_last_of('.');
    return std::string("HostState:") + std::string(state.substr(found + 1));
}

std::string inline translateOSStatus(std::string_view status)
{
    std::size_t found = status.find_last_of('.');
    return std::string("OSStatus:") + std::string(status.substr(found + 1));
}

std::string inline queryHostState(sdbusplus::bus::bus& bus,
                                  const btm::psm::PSMConfig& psmConfig)
{
    std::string hostState;
    BasicVariantType result;
    auto method =
        bus.new_method_call(psmConfig.hostStateDbusService.c_str(), // Service
                            psmConfig.hostStateDbusObjPath.c_str(), // Path
                            "org.freedesktop.DBus.Properties",      // Iface
                            "Get");                                 // Function
    method.append("xyz.openbmc_project.State.Host", "CurrentHostState");
    try
    {
        bus.call(method).read(result);
        hostState = std::get<std::string>(result);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        fmt::print(
            stderr,
            "Failed to query `CurrentHostState` with busctl get-property {} {} "
            "xyz.openbmc_project.State.Host CurrentHostState"
            ". Got error: {}\n",
            psmConfig.hostStateDbusService, psmConfig.hostStateDbusObjPath,
            e.what());
    }
    return hostState;
}

std::string inline queryOSStatus(sdbusplus::bus::bus& bus,
                                 const btm::psm::PSMConfig& psmConfig)
{
    std::string oSState;
    BasicVariantType result;
    auto method =
        bus.new_method_call(psmConfig.osStateDbusService.c_str(), // Service
                            psmConfig.osStateDbusObjPath.c_str(), // Path
                            "org.freedesktop.DBus.Properties",    // Iface
                            "Get");                               // Function
    method.append("xyz.openbmc_project.State.OperatingSystem.Status",
                  "OperatingSystemState");
    try
    {
        bus.call(method).read(result);
        oSState = std::get<std::string>(result);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        fmt::print(
            stderr,
            "Failed to query OperatingSystemState with busctl get-property {} {} "
            "xyz.openbmc_project.State.OperatingSystem.Status OperatingSystemState."
            "Got error: {}\n",
            psmConfig.hostStateDbusService, psmConfig.hostStateDbusObjPath,
            e.what());
    }
    return oSState;
}

std::string inline queryNameOwner(sdbusplus::bus::bus& bus,
                                  const btm::psm::PSMConfig& psmConfig)
{
    std::string ownerUniqueName;
    try
    {
        auto method =
            bus.new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
                                "org.freedesktop.DBus", "GetNameOwner");
        method.append(std::string(psmConfig.osStateDbusService));
        bus.call(method).read(ownerUniqueName);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        // This name isn't owned by anyone right now, so we can ignore this
        // signal.
    }
    return ownerUniqueName;
}

Handler::Handler(sdbusplus::bus::bus& bus, const btm::NodeConfig& nodeConfig,
                 const btm::psm::PSMConfig& psmConfig,
                 std::shared_ptr<btm::api::IBoottimeApi> api) :
    mNodeConfig(nodeConfig), mApi(std::move(api))
{
    mPreHostState = queryHostState(bus, psmConfig);
    fmt::print("{} `CurrentHostState` is `{}`\n", mNodeConfig.node_name,
               mPreHostState);
    mHostStateWatcher = std::make_unique<sdbusplus::bus::match::match>(
        bus,
        sdbusplus::bus::match::rules::propertiesChanged(
            psmConfig.hostStateDbusObjPath, "xyz.openbmc_project.State.Host"),
        [this](sdbusplus::message::message& message) {
        hostStateWatcherCallback(message);
    });

    mPreOSStatus = queryOSStatus(bus, psmConfig);
    fmt::print("{} `OperatingSystemState` is `{}`\n", mNodeConfig.node_name,
               mPreOSStatus);
    mOSStatusWatcher = std::make_unique<sdbusplus::bus::match::match>(
        bus,
        sdbusplus::bus::match::rules::propertiesChanged(
            psmConfig.osStateDbusObjPath,
            "xyz.openbmc_project.State.OperatingSystem.Status"),
        [this, &bus, psmConfig](sdbusplus::message::message& message) {
        const std::string& signalSenderUniqueName = message.get_sender();
        std::string ownerUniqueName = queryNameOwner(bus, psmConfig);
        // Compare the signal's sender to the name's rightful owner.
        if (signalSenderUniqueName != ownerUniqueName)
        {
            return; // The signal came from a different process. Ignore it.
        }
        oSStatusWatcherCallback(message);
    });
}

void Handler::hostStateWatcherCallback(sdbusplus::message::message& message)
{
    fmt::print(stdout, "[mHostStateWatcher] Signal from {}\n",
               mNodeConfig.node_name);
    std::string objectName;
    boost::container::flat_map<
        std::string, std::variant<std::string, bool, int64_t, uint64_t, double>>
        values;
    message.read(objectName, values);

    auto findState = values.find("CurrentHostState");
    if (findState != values.end())
    {
        const std::string curHostState =
            std::get<std::string>(findState->second);
        if (curHostState == mPreHostState)
        {
            return;
        }

        fmt::print(
            stdout,
            "[mHostStateWatcher] {} `CurrentHostState` has changed from {} to {}\n",
            mNodeConfig.node_name, mPreHostState, curHostState);
        absl::Status status = mApi->SetNodeCheckpoint(
            mNodeConfig, translateHostStateName(curHostState), 0, 0);
        btm::log::LogIfError(status);
        mPreHostState = curHostState;
        fmt::print(
            stdout,
            "[mHostStateWatcher] {} `CurrentHostState` {} checkpoint has been recorded\n",
            mNodeConfig.node_name, curHostState);
    }
}

void Handler::oSStatusWatcherCallback(sdbusplus::message::message& message)
{
    fmt::print(stdout, "[mOSStatusWatcher] Signal from {}.\n",
               mNodeConfig.node_name);
    std::string objectName;
    boost::container::flat_map<
        std::string, std::variant<std::string, bool, int64_t, uint64_t, double>>
        values;
    message.read(objectName, values);

    auto findState = values.find("OperatingSystemState");
    if (findState != values.end())
    {
        const std::string curOSStatus =
            std::get<std::string>(findState->second);
        if (curOSStatus == mPreOSStatus)
        {
            return;
        }

        fmt::print(
            stdout,
            "[mOSStatusWatcher] {} `OperatingSystemState` has changed from {} to {}\n",
            mNodeConfig.node_name, mPreOSStatus, curOSStatus);
        absl::Status status = mApi->SetNodeCheckpoint(
            mNodeConfig, translateOSStatus(curOSStatus), 0, 0);
        btm::log::LogIfError(status);
        mPreOSStatus = curOSStatus;
        fmt::print(
            stdout,
            "[mOSStatusWatcher] {} `OperatingSystemState` {} checkpoint has been recorded\n",
            mNodeConfig.node_name, curOSStatus);
    }
}
} // namespace psm
} // namespace boot_time_monitor
