#include "create_pel.hpp"

#include "attributes_info.H"

#include "util.hpp"

#include <fcntl.h>
#include <libekb.H>
#include <libphal.H>
#include <unistd.h>

#include <phosphor-logging/elog.hpp>
#include <xyz/openbmc_project/Logging/Create/server.hpp>
#include <xyz/openbmc_project/Logging/Entry/server.hpp>

#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <format>
#include <map>
#include <stdexcept>
#include <string>
#include <tuple>
#include <vector>

namespace openpower
{
using namespace phosphor::logging;

namespace pel
{

constexpr auto loggingObjectPath = "/xyz/openbmc_project/logging";
constexpr auto loggingInterface = "xyz.openbmc_project.Logging.Create";
constexpr auto opLoggingInterface = "org.open_power.Logging.PEL";

/**
 * @brief get SBE special callout information
 *
 *        This function add the special sbe callout in the user provided
 *        json callout list. includes BMC0002 procedure callout with
 *        high priority and processor callout with medium priority.
 *
 * @param[in] procTarget - pdbg processor target
 * @param[out] jsonCalloutDataList - reference to json callout list
 */
static void getSBECallout(struct pdbg_target* procTarget,
                          json& jsonCalloutDataList)
{
    using namespace openpower::phal::pdbg;

    json jsonProcedCallout;

    // Add procedure callout
    jsonProcedCallout["Procedure"] = "BMC0002";
    jsonProcedCallout["Priority"] = "H";
    jsonCalloutDataList.emplace_back(std::move(jsonProcedCallout));
    try
    {
        ATTR_LOCATION_CODE_Type locationCode;
        // Initialize with default data.
        memset(&locationCode, '\0', sizeof(locationCode));
        // Get location code information
        openpower::phal::pdbg::getLocationCode(procTarget, locationCode);
        json jsonProcCallout;
        jsonProcCallout["LocationCode"] = locationCode;
        jsonProcCallout["Deconfigured"] = false;
        jsonProcCallout["Guarded"] = false;
        jsonProcCallout["Priority"] = "M";
        jsonCalloutDataList.emplace_back(std::move(jsonProcCallout));
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(std::format("getLocationCode({}): Exception({})",
                                    pdbg_target_path(procTarget), e.what())
                            .c_str());
    }
}

void createErrorPEL(const std::string& event, const json& calloutData,
                    const FFDCData& ffdcData, const Severity severity)
{
    std::map<std::string, std::string> additionalData;
    auto bus = sdbusplus::bus::new_default();
    additionalData.emplace("_PID", std::to_string(getpid()));
    for (auto& data : ffdcData)
    {
        additionalData.emplace(data);
    }

    try
    {
        FFDCFile ffdcFile(calloutData);

        std::vector<std::tuple<sdbusplus::xyz::openbmc_project::Logging::
                                   server::Create::FFDCFormat,
                               uint8_t, uint8_t, sdbusplus::message::unix_fd>>
            pelCalloutInfo;

        pelCalloutInfo.push_back(
            std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
                                Create::FFDCFormat::JSON,
                            static_cast<uint8_t>(0xCA),
                            static_cast<uint8_t>(0x01), ffdcFile.getFileFD()));

        std::string service =
            util::getService(bus, loggingObjectPath, loggingInterface);
        auto method =
            bus.new_method_call(service.c_str(), loggingObjectPath,
                                loggingInterface, "CreateWithFFDCFiles");
        auto level =
            sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
                severity);
        method.append(event, level, additionalData, pelCalloutInfo);
        auto resp = bus.call(method);
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>(
            std::format("D-Bus call exception",
                        "OBJPATH={}, INTERFACE={}, event={}, EXCEPTION={}",
                        loggingObjectPath, loggingInterface, event, e.what())
                .c_str());
        throw std::runtime_error(
            "Error in invoking D-Bus logging create interface");
    }
    catch (const std::exception& e)
    {
        throw e;
    }
}

uint32_t createSbeErrorPEL(const std::string& event, const sbeError_t& sbeError,
                           const FFDCData& ffdcData,
                           struct pdbg_target* procTarget,
                           const Severity severity)
{
    uint32_t plid = 0;
    std::map<std::string, std::string> additionalData;
    auto bus = sdbusplus::bus::new_default();

    additionalData.emplace("_PID", std::to_string(getpid()));
    additionalData.emplace("SBE_ERR_MSG", sbeError.what());

    for (auto& data : ffdcData)
    {
        additionalData.emplace(data);
    }

    std::vector<std::tuple<
        sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat,
        uint8_t, uint8_t, sdbusplus::message::unix_fd>>
        pelFFDCInfo;

    // get SBE ffdc file descriptor
    auto fd = sbeError.getFd();

    // Negative fd value indicates error case or invalid file
    // No need of special processing , just log error with additional ffdc.
    if (fd > 0)
    {
        // Refer phosphor-logging/extensions/openpower-pels/README.md section
        // "Self Boot Engine(SBE) First Failure Data Capture(FFDC) Support"
        // for details of related to createPEL with SBE FFDC information
        // usin g CreateWithFFDCFiles api.
        pelFFDCInfo.push_back(
            std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
                                Create::FFDCFormat::Custom,
                            static_cast<uint8_t>(0xCB),
                            static_cast<uint8_t>(0x01), sbeError.getFd()));
    }

    // Workaround : currently sbe_extract_rc hwp procedure based callout
    // handling is not available. openbmc issue #2917
    // As per discussion with RAS team adding additional callout for
    // SBE timeout error case, till this hwp based error handling in place.
    // Note: PEL needs ffdcFile file till pel creation. This is forced to
    // define ffdcFile function level scope.
    std::unique_ptr<FFDCFile> FFDCFilePtr;
    try
    {
        if ((event == "org.open_power.Processor.Error.SbeBootTimeout") &&
            (severity == Severity::Error))
        {
            json jsonCalloutDataList;
            jsonCalloutDataList = json::array();
            getSBECallout(procTarget, jsonCalloutDataList);
            FFDCFilePtr = std::make_unique<FFDCFile>(jsonCalloutDataList);
            pelFFDCInfo.push_back(std::make_tuple(
                sdbusplus::xyz::openbmc_project::Logging::server::Create::
                    FFDCFormat::JSON,
                static_cast<uint8_t>(0xCA), static_cast<uint8_t>(0x01),
                FFDCFilePtr->getFileFD()));
        }
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(
            std::format("Skipping SBE special callout due to Exception({})",
                        e.what())
                .c_str());
    }

    try
    {
        std::string service =
            util::getService(bus, loggingObjectPath, opLoggingInterface);
        auto method =
            bus.new_method_call(service.c_str(), loggingObjectPath,
                                opLoggingInterface, "CreatePELWithFFDCFiles");
        auto level =
            sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
                severity);
        method.append(event, level, additionalData, pelFFDCInfo);
        auto response = bus.call(method);

        // reply will be tuple containing bmc log id, platform log id
        std::tuple<uint32_t, uint32_t> reply = {0, 0};

        // parse dbus response into reply
        response.read(reply);
        plid = std::get<1>(reply); // platform log id is tuple "second"
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>(
            std::format("D-Bus call exception",
                        "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
                        loggingObjectPath, loggingInterface, e.what())
                .c_str());
        throw std::runtime_error(
            "Error in invoking D-Bus logging create interface");
    }
    catch (const std::exception& e)
    {
        throw e;
    }
    return plid;
}

void createPEL(const std::string& event, const FFDCData& ffdcData,
               const Severity severity)
{
    std::map<std::string, std::string> additionalData;
    auto bus = sdbusplus::bus::new_default();

    additionalData.emplace("_PID", std::to_string(getpid()));
    for (auto& data : ffdcData)
    {
        additionalData.emplace(data);
    }

    try
    {
        std::string service =
            util::getService(bus, loggingObjectPath, loggingInterface);
        auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
                                          loggingInterface, "Create");
        auto level =
            sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
                severity);
        method.append(event, level, additionalData);
        auto resp = bus.call(method);
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>(
            std::format("sdbusplus D-Bus call exception",
                        "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
                        loggingObjectPath, loggingInterface, e.what())
                .c_str());
        ;

        throw std::runtime_error(
            "Error in invoking D-Bus logging create interface");
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(
            std::format("D-bus call exception", "EXCEPTION={}", e.what())
                .c_str());
        throw e;
    }
}

FFDCFile::FFDCFile(const json& pHALCalloutData) :
    calloutData(pHALCalloutData.dump()),
    calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
{
    prepareFFDCFile();
}

FFDCFile::~FFDCFile()
{
    removeCalloutFile();
}

int FFDCFile::getFileFD() const
{
    return fileFD;
}

void FFDCFile::prepareFFDCFile()
{
    createCalloutFile();
    writeCalloutData();
    setCalloutFileSeekPos();
}

void FFDCFile::createCalloutFile()
{
    fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);

    if (fileFD == -1)
    {
        log<level::ERR>(std::format("Failed to create phalPELCallouts "
                                    "file({}), errorno({}) and errormsg({})",
                                    calloutFile, errno, strerror(errno))
                            .c_str());
        throw std::runtime_error("Failed to create phalPELCallouts file");
    }
}

void FFDCFile::writeCalloutData()
{
    ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());

    if (rc == -1)
    {
        log<level::ERR>(std::format("Failed to write phaPELCallout info "
                                    "in file({}), errorno({}), errormsg({})",
                                    calloutFile, errno, strerror(errno))
                            .c_str());
        throw std::runtime_error("Failed to write phalPELCallouts info");
    }
    else if (rc != static_cast<ssize_t>(calloutData.size()))
    {
        log<level::WARNING>(std::format("Could not write all phal callout "
                                        "info in file({}), written byte({}) "
                                        "and total byte({})",
                                        calloutFile, rc, calloutData.size())
                                .c_str());
    }
}

void FFDCFile::setCalloutFileSeekPos()
{
    int rc = lseek(fileFD, 0, SEEK_SET);

    if (rc == -1)
    {
        log<level::ERR>(std::format("Failed to set SEEK_SET for "
                                    "phalPELCallouts in file({}), errorno({}) "
                                    "and errormsg({})",
                                    calloutFile, errno, strerror(errno))
                            .c_str());
        throw std::runtime_error(
            "Failed to set SEEK_SET for phalPELCallouts file");
    }
}

void FFDCFile::removeCalloutFile()
{
    close(fileFD);
    std::remove(calloutFile.c_str());
}

} // namespace pel
} // namespace openpower
