#include "config.h"

#include "lg2_commit.hpp"

#include <sys/syslog.h>

#include <nlohmann/json.hpp>
#include <phosphor-logging/commit.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/async.hpp>
#include <sdbusplus/exception.hpp>
#include <xyz/openbmc_project/Logging/Create/client.hpp>
#include <xyz/openbmc_project/Logging/Entry/client.hpp>

namespace lg2
{
namespace details
{

using Create = sdbusplus::client::xyz::openbmc_project::logging::Create<>;
using Entry = sdbusplus::client::xyz::openbmc_project::logging::Entry<>;

/* Convert syslog severity to Entry::Level */
static auto severity_from_syslog(int s) -> Entry::Level
{
    switch (s)
    {
        case LOG_DEBUG:
            return Entry::Level::Debug;

        case LOG_INFO:
            return Entry::Level::Informational;

        case LOG_NOTICE:
            return Entry::Level::Notice;

        case LOG_WARNING:
            return Entry::Level::Warning;

        case LOG_ERR:
            return Entry::Level::Error;

        case LOG_CRIT:
            return Entry::Level::Critical;

        case LOG_ALERT:
            return Entry::Level::Alert;

        case LOG_EMERG:
            return Entry::Level::Emergency;
    }
    return Entry::Level::Emergency;
}

using AdditionalData_t = std::map<std::string, std::string>;

/* Create AdditionalData from the sdbusplus event json. */
static auto data_from_json(sdbusplus::exception::generated_event_base& t)
    -> AdditionalData_t
{
    AdditionalData_t result{};

    auto j = t.to_json()[t.name()];
    for (const auto& item : j.items())
    {
        // Special cases for the "_SOURCE" fields, which contain debug
        // information about the origin of the event.
        if (item.key() == "_SOURCE")
        {
            for (const auto& source_item : item.value().items())
            {
                if (source_item.key() == "PID")
                {
                    result.emplace("_PID", source_item.value().dump());
                    continue;
                }
                if (source_item.key() == "FILE")
                {
                    result.emplace("_CODE_FILE", source_item.value());
                    continue;
                }
                if (source_item.key() == "FUNCTION")
                {
                    result.emplace("_CODE_FUNC", source_item.value());
                    continue;
                }
                if (source_item.key() == "LINE")
                {
                    result.emplace("_CODE_LINE", source_item.value().dump());
                    continue;
                }
            }
            continue;
        }

        if (item.value().type() == nlohmann::json::value_t::string)
        {
            result.emplace(item.key(), item.value());
        }
        else
        {
            result.emplace(item.key(), item.value().dump());
        }
    }

    return result;
}

auto extractEvent(sdbusplus::exception::generated_event_base&& t)
    -> std::tuple<std::string, Entry::Level, std::map<std::string, std::string>>
{
    return {t.name(), severity_from_syslog(t.severity()), data_from_json(t)};
}

} // namespace details

auto commit(sdbusplus::exception::generated_event_base&& t)
    -> sdbusplus::message::object_path
{
    // Check event filters first.
    if ((t.severity() == LOG_INFO) && details::filterEvent(t.name()))
    {
        return {};
    }
    else if (details::filterError(t.name()))
    {
        return {};
    }

    if constexpr (LG2_COMMIT_JOURNAL)
    {
        lg2::error("OPENBMC_MESSAGE_ID={DATA}", "DATA", t.to_json().dump());
    }

    if constexpr (LG2_COMMIT_DBUS)
    {
        using details::Create;

        auto b = sdbusplus::bus::new_default();
        auto m =
            b.new_method_call(Create::default_service, Create::instance_path,
                              Create::interface, "Create");

        m.append(t.name(), details::severity_from_syslog(t.severity()),
                 details::data_from_json(t));

        auto reply = b.call(m);

        return reply.unpack<sdbusplus::message::object_path>();
    }

    return {};
}

void resolve(const sdbusplus::message::object_path& logPath)
{
    if constexpr (LG2_COMMIT_DBUS)
    {
        using details::Entry;

        auto b = sdbusplus::bus::new_default();
        auto m = b.new_method_call(Entry::default_service, logPath.str.c_str(),
                                   "org.freedesktop.DBus.Properties", "Set");
        m.append(Entry::interface, "Resolved", std::variant<bool>(true));
        auto reply = b.call(m);
    }
}

auto commit(sdbusplus::async::context& ctx,
            sdbusplus::exception::generated_event_base&& t)
    -> sdbusplus::async::task<sdbusplus::message::object_path>
{
    using details::Create;

    if constexpr (LG2_COMMIT_JOURNAL)
    {
        lg2::error("OPENBMC_MESSAGE_ID={DATA}", "DATA", t.to_json().dump());
    }

    if constexpr (LG2_COMMIT_DBUS)
    {
        co_return co_await Create(ctx)
            .service(Create::default_service)
            .path(Create::instance_path)
            .create(t.name(), details::severity_from_syslog(t.severity()),
                    details::data_from_json(t));
    }
    co_return {};
}

auto resolve(sdbusplus::async::context& ctx,
             const sdbusplus::message::object_path& logPath)
    -> sdbusplus::async::task<>
{
    using details::Entry;

    if constexpr (LG2_COMMIT_DBUS)
    {
        std::string path = logPath.str;
        co_await Entry(ctx)
            .service(Entry::default_service)
            .path(path)
            .resolved(true);
    }
    co_return;
}

} // namespace lg2
