#include "host_monitor_app.hpp"

#include "boot_manager.hpp"
#include "dbus_handler.hpp"
#include "utils.hpp"

#include <fmt/printf.h>

#include <boost/container/flat_map.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/bus/match.hpp>
#include <sdbusplus/message.hpp>

#include <memory>
#include <ranges>
#include <string>
#include <string_view>
#include <variant>

namespace 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>;

constexpr std::string_view kHostService = "xyz.openbmc_project.State.Host";
constexpr std::string_view kHostPath = "/xyz/openbmc_project/state/host0";
constexpr std::string_view kHostIface = "xyz.openbmc_project.State.Host";
constexpr std::string_view kHostProperty = "CurrentHostState";

constexpr std::string_view kHostStateRunning =
    "xyz.openbmc_project.State.Host.HostState.Running";
constexpr std::string_view kHostStateOff =
    "xyz.openbmc_project.State.Host.HostState.Off";

constexpr std::string_view kOSStatusService =
    "xyz.openbmc_project.State.OperatingSystem";
constexpr std::string_view kOSStatusPath = "/xyz/openbmc_project/state/os";
constexpr std::string_view kOSStatusIface =
    "xyz.openbmc_project.State.OperatingSystem.Status";
constexpr std::string_view kOSStatusProperty = "OperatingSystemState";

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));
}

HostMonitorApp::HostMonitorApp(sdbusplus::bus::bus& bus, uint32_t hostNum) :
    kNodeName(std::string{"host"} + std::to_string(hostNum)),
    kObjPath(std::string{"/xyz/openbmc_project/time/boot/"} + kNodeName),
    objManager(bus, kObjPath.c_str())
{
    util = std::make_shared<Util>();
    cpCSV = std::make_shared<FileUtil>(util->getCPPath(kNodeName, false));
    durCSV = std::make_shared<FileUtil>(util->getDurPath(kNodeName, false));
    bootManager = std::make_shared<BootManager>(util, cpCSV, durCSV);
    dbusHandler = std::make_shared<DbusHandler>(bus, kObjPath.data(),
                                                bootManager, util);
    // Initialize preHostState
    static std::string preHostState;
    auto method = bus.new_method_call(kHostService.data(), kHostPath.data(),
                                      "org.freedesktop.DBus.Properties", "Get");
    method.append(kHostIface.data(), kHostProperty.data());
    BasicVariantType result;
    try
    {
        bus.call(method).read(result);
        preHostState = std::get<std::string>(result);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        fmt::print(stderr, "[{}] Failed to get `CurrentHostState`. ERROR={}\n",
                   __FUNCTION__, e.what());
        fmt::print(
            stderr,
            "[{}] Initialized `preHostState` to empty string as default value\n",
            __FUNCTION__);
    }

    hostStateWatcher = std::make_unique<sdbusplus::bus::match::match>(
        bus,
        sdbusplus::bus::match::rules::propertiesChanged(kHostPath.data(),
                                                        kHostIface.data()),
        [this](sdbusplus::message::message& message) {
        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(kHostProperty.data());
        if (findState != values.end())
        {
            const std::string curHostState =
                std::get<std::string>(findState->second);
            fmt::print(
                stderr,
                "[hostStateWatcher] CurrentHostState has changed from {} to {}\n",
                preHostState, curHostState);
            bootManager->setCheckpoint(translateHostStateName(curHostState), 0,
                                       0);
            preHostState = curHostState;
        }
    });

    // Initialize preOSStatus
    static std::string preOSStatus;
    method = bus.new_method_call(kOSStatusService.data(), kOSStatusPath.data(),
                                 "org.freedesktop.DBus.Properties", "Get");
    method.append(kOSStatusIface.data(), kOSStatusProperty.data());
    try
    {
        bus.call(method).read(result);
        preOSStatus = std::get<std::string>(result);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        fmt::print(stderr,
                   "[{}] Failed to get `OperatingSystemState`. ERROR={}\n",
                   __FUNCTION__, e.what());
        fmt::print(
            stderr,
            "[{}] Initialized `preOSStatus` to empty string as default value\n",
            __FUNCTION__);
    }

    osStatusWatcher = std::make_unique<sdbusplus::bus::match::match>(
        bus,
        sdbusplus::bus::match::rules::propertiesChanged(kOSStatusPath.data(),
                                                        kOSStatusIface.data()),
        [this](sdbusplus::message::message& message) {
        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(kOSStatusProperty.data());
        if (findState != values.end())
        {
            const std::string curOSStatus =
                std::get<std::string>(findState->second);

            fmt::print(
                stderr,
                "[osStatusWatcher] curOSStatus has changed from {} to {}\n",
                preOSStatus, curOSStatus);
            bootManager->setCheckpoint(translateOSStatus(curOSStatus), 0, 0);
            preOSStatus = curOSStatus;
        }
    });
}

} // namespace boot_time_monitor
