#include "config.h"

#include "oemhandler.hpp"

#include "elog-errors.hpp"

#include <endian.h>
#include <ipmid/api.h>
#include <stdio.h>
#include <string.h>
#include <systemd/sd-bus.h>

#include <host-interface.hpp>
#include <ipmid-host/cmd.hpp>
#include <org/open_power/Host/error.hpp>
#include <org/open_power/OCC/Metrics/error.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/exception.hpp>

#include <fstream>
#include <functional>
#include <memory>

void register_netfn_ibm_oem_commands() __attribute__((constructor));

const char* g_esel_path = "/tmp/esel";
uint16_t g_record_id = 0x0001;
using namespace phosphor::logging;
constexpr auto occMetricsType = 0xDD;

extern const ObjectIDMap invSensors;
const std::map<uint8_t, Entry::Level> severityMap{
    {0x10, Entry::Level::Warning}, // Recoverable error
    {0x20, Entry::Level::Warning}, // Predictive error
    {0x40, Entry::Level::Error},   // Unrecoverable error
    {0x50, Entry::Level::Error},   // Critical error
    {0x60, Entry::Level::Error},   // Error from a diagnostic test
    {0x70, Entry::Level::Warning}, // Recoverable symptom
    {0xFF, Entry::Level::Error},   // Unknown error
};

Entry::Level mapSeverity(const std::string& eSELData)
{
    constexpr size_t severityOffset = 0x4A;

    if (eSELData.size() > severityOffset)
    {
        // Dive in to the IBM log to find the severity
        uint8_t sev = 0xF0 & eSELData[severityOffset];

        auto find = severityMap.find(sev);
        if (find != severityMap.end())
        {
            return find->second;
        }
    }

    // Default to Entry::Level::Error if a matching is not found.
    return Entry::Level::Error;
}

std::string mapCalloutAssociation(const std::string& eSELData)
{
    auto rec = reinterpret_cast<const SELEventRecord*>(&eSELData[0]);
    uint8_t sensor = rec->sensorNum;

    /*
     * Search the sensor number to inventory path mapping to figure out the
     * inventory associated with the ESEL.
     */
    auto found = std::find_if(invSensors.begin(), invSensors.end(),
                              [&sensor](const auto& iter) {
        return (iter.second.sensorID == sensor);
    });
    if (found != invSensors.end())
    {
        return found->first;
    }

    return {};
}

std::string getService(sdbusplus::bus_t& bus, const std::string& path,
                       const std::string& interface)
{
    auto method = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_IFACE,
                                      "GetObject");

    method.append(path);
    method.append(std::vector<std::string>({interface}));

    std::map<std::string, std::vector<std::string>> response;

    try
    {
        auto reply = bus.call(method);

        reply.read(response);
        if (response.empty())
        {
            log<level::ERR>("Error in mapper response for getting service name",
                            entry("PATH=%s", path.c_str()),
                            entry("INTERFACE=%s", interface.c_str()));
            return std::string{};
        }
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>("Error in mapper method call",
                        entry("ERROR=%s", e.what()));
        return std::string{};
    }

    return response.begin()->first;
}

std::string readESEL(const char* fileName)
{
    std::string content{};

    std::ifstream handle(fileName);

    if (handle.fail())
    {
        log<level::ERR>("Failed to open eSEL", entry("FILENAME=%s", fileName));
        return content;
    }

    handle.seekg(0, std::ios::end);
    content.resize(handle.tellg());
    handle.seekg(0, std::ios::beg);
    handle.read(&content[0], content.size());
    handle.close();

    return content;
}

void createOCCLogEntry(const std::string& eSELData)
{
    // Each byte in eSEL is formatted as %02x with a space between bytes and
    // insert '/0' at the end of the character array.
    constexpr auto byteSeperator = 3;

    std::unique_ptr<char[]> data(
        new char[(eSELData.size() * byteSeperator) + 1]());

    for (size_t i = 0; i < eSELData.size(); i++)
    {
        sprintf(&data[i * byteSeperator], "%02x ", eSELData[i]);
    }
    data[eSELData.size() * byteSeperator] = '\0';

    using error = sdbusplus::org::open_power::OCC::Metrics::Error::Event;
    using metadata = org::open_power::OCC::Metrics::Event;

    report<error>(metadata::ESEL(data.get()));
}

void createHostEntry(const std::string& eSELData)
{
    // Each byte in eSEL is formatted as %02x with a space between bytes and
    // insert '/0' at the end of the character array.
    constexpr auto byteSeperator = 3;

    auto sev = mapSeverity(eSELData);
    auto inventoryPath = mapCalloutAssociation(eSELData);

    if (!inventoryPath.empty())
    {
        std::unique_ptr<char[]> data(
            new char[(eSELData.size() * byteSeperator) + 1]());

        for (size_t i = 0; i < eSELData.size(); i++)
        {
            sprintf(&data[i * byteSeperator], "%02x ", eSELData[i]);
        }
        data[eSELData.size() * byteSeperator] = '\0';

        using hosterror = sdbusplus::org::open_power::Host::Error::Event;
        using hostmetadata = org::open_power::Host::Event;

        report<hosterror>(
            sev, hostmetadata::ESEL(data.get()),
            hostmetadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));
    }
}

/** @brief Helper function to do a graceful restart (reboot) of the BMC.
    @return 0 on success, -1 on error
 */
int rebootBMC()
{
    sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
    auto service = getService(bus, stateBmcPath, stateBmcIntf);
    if (service.empty())
    {
        log<level::ERR>("Error getting the service name to reboot the BMC.");
        return -1;
    }
    std::variant<std::string> reboot =
        "xyz.openbmc_project.State.BMC.Transition.Reboot";
    auto method = bus.new_method_call(service.c_str(), stateBmcPath,
                                      propertiesIntf, "Set");
    method.append(stateBmcIntf, "RequestedBMCTransition", reboot);
    try
    {
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>("Error calling to reboot the BMC.",
                        entry("ERROR=%s", e.what()));
        return -1;
    }
    return 0;
}

///////////////////////////////////////////////////////////////////////////////
// For the First partial add eSEL the SEL Record ID and offset
// value should be 0x0000. The extended data needs to be in
// the form of an IPMI SEL Event Record, with Event sensor type
// of 0xDF and Event Message format of 0x04. The returned
// Record ID should be used for all partial eSEL adds.
//
// This function creates a /tmp/esel file to store the
// incoming partial esel.  It is the role of some other
// function to commit the error log in to long term
// storage.  Likely via the ipmi add_sel command.
///////////////////////////////////////////////////////////////////////////////
ipmi_ret_t ipmi_ibm_oem_partial_esel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                                     ipmi_request_t request,
                                     ipmi_response_t response,
                                     ipmi_data_len_t data_len,
                                     ipmi_context_t context)
{
    uint8_t* reqptr = (uint8_t*)request;
    esel_request_t esel_req;
    FILE* fp;
    int r = 0;
    uint8_t rlen;
    ipmi_ret_t rc = IPMI_CC_OK;
    const char* pio;

    esel_req.resid = le16toh((((uint16_t)reqptr[1]) << 8) + reqptr[0]);
    esel_req.selrecord = le16toh((((uint16_t)reqptr[3]) << 8) + reqptr[2]);
    esel_req.offset = le16toh((((uint16_t)reqptr[5]) << 8) + reqptr[4]);
    esel_req.progress = reqptr[6];

    // According to IPMI spec, Reservation ID must be checked.
    if (!checkSELReservation(esel_req.resid))
    {
        // 0xc5 means Reservation Cancelled or Invalid Reservation ID.
        printf("Used Reservation ID = %d\n", esel_req.resid);
        rc = IPMI_CC_INVALID_RESERVATION_ID;

        // clean g_esel_path.
        r = remove(g_esel_path);
        if (r < 0)
            fprintf(stderr, "Error deleting %s\n", g_esel_path);

        return rc;
    }

    // OpenPOWER Host Interface spec says if RecordID and Offset are
    // 0 then then this is a new request
    if (!esel_req.selrecord && !esel_req.offset)
        pio = "wb";
    else
        pio = "rb+";

    rlen = (*data_len) - (uint8_t)(sizeof(esel_request_t));

    if ((fp = fopen(g_esel_path, pio)) != NULL)
    {
        fseek(fp, esel_req.offset, SEEK_SET);
        fwrite(reqptr + (uint8_t)(sizeof(esel_request_t)), rlen, 1, fp);
        fclose(fp);

        *data_len = sizeof(g_record_id);
        memcpy(response, &g_record_id, *data_len);
    }
    else
    {
        fprintf(stderr, "Error trying to perform %s for esel%s\n", pio,
                g_esel_path);
        rc = IPMI_CC_INVALID;
        *data_len = 0;
    }

    // The first bit presents that this is the last partial packet
    // coming down.  If that is the case advance the record id so we
    // don't overlap logs.  This allows anyone to establish a log
    // directory system.
    if (esel_req.progress & 1)
    {
        g_record_id++;

        auto eSELData = readESEL(g_esel_path);

        if (eSELData.empty())
        {
            return IPMI_CC_UNSPECIFIED_ERROR;
        }

        // If the eSEL record type is OCC metrics, then create the OCC log
        // entry.
        if (eSELData[2] == occMetricsType)
        {
            createOCCLogEntry(eSELData);
        }
        else
        {
            createHostEntry(eSELData);
        }
    }

    return rc;
}

// Prepare for FW Update.
// Execute needed commands to prepare the system for a fw update from the host.
ipmi_ret_t ipmi_ibm_oem_prep_fw_update(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                                       ipmi_request_t request,
                                       ipmi_response_t response,
                                       ipmi_data_len_t data_len,
                                       ipmi_context_t context)
{
    ipmi_ret_t ipmi_rc = IPMI_CC_OK;
    *data_len = 0;

    int rc = 0;
    std::ofstream rwfs_file;

    // Set one time flag
    rc = system(
        "fw_setenv openbmconce copy-files-to-ram copy-base-filesystem-to-ram");
    rc = WEXITSTATUS(rc);
    if (rc != 0)
    {
        fprintf(stderr, "fw_setenv openbmconce failed with rc=%d\n", rc);
        return IPMI_CC_UNSPECIFIED_ERROR;
    }

    // Touch the image-rwfs file to perform an empty update to force the save
    // in case we're already in ram and the flash is the same causing the ram
    // files to not be copied back to flash
    rwfs_file.open("/run/initramfs/image-rwfs",
                   std::ofstream::out | std::ofstream::app);
    rwfs_file.close();

    // Reboot the BMC for settings to take effect
    rc = rebootBMC();
    if (rc < 0)
    {
        fprintf(stderr, "Failed to reset BMC: %s\n", strerror(-rc));
        return -1;
    }
    printf("Warning: BMC is going down for reboot!\n");

    return ipmi_rc;
}

ipmi_ret_t ipmi_ibm_oem_bmc_factory_reset(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                                          ipmi_request_t request,
                                          ipmi_response_t response,
                                          ipmi_data_len_t data_len,
                                          ipmi_context_t context)
{
    sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};

    // Since this is a one way command (i.e. the host is requesting a power
    // off of itself and a reboot of the BMC) we can exceed the 5 second
    // IPMI timeout. Testing has shown that the power off can take up to
    // 10 seconds so give it at least 15
    constexpr auto powerOffWait = std::chrono::seconds(15);
    constexpr auto setFactoryWait = std::chrono::seconds(3);

    // Power Off Chassis
    auto service = getService(bus, stateChassisPath, stateChassisIntf);
    if (service.empty())
    {
        return IPMI_CC_UNSPECIFIED_ERROR;
    }
    std::variant<std::string> off =
        "xyz.openbmc_project.State.Chassis.Transition.Off";
    auto method = bus.new_method_call(service.c_str(), stateChassisPath,
                                      propertiesIntf, "Set");
    method.append(stateChassisIntf, "RequestedPowerTransition", off);
    try
    {
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>("Error powering off the chassis",
                        entry("ERROR=%s", e.what()));
        return IPMI_CC_UNSPECIFIED_ERROR;
    }

    // Wait a few seconds for the chassis to power off
    std::this_thread::sleep_for(powerOffWait);

    // Set Factory Reset
    method = bus.new_method_call(bmcUpdaterServiceName, softwarePath,
                                 factoryResetIntf, "Reset");
    try
    {
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>("Error setting factory reset",
                        entry("ERROR=%s", e.what()));
        return IPMI_CC_UNSPECIFIED_ERROR;
    }

    // Wait a few seconds for service that sets the reset env variable to
    // complete before the BMC is rebooted
    std::this_thread::sleep_for(setFactoryWait);

    // Reboot BMC
    auto rc = rebootBMC();
    if (rc < 0)
    {
        log<level::ALERT>("The BMC needs to be manually rebooted to complete "
                          "the factory reset.");
        return IPMI_CC_UNSPECIFIED_ERROR;
    }

    return IPMI_CC_OK;
}

namespace
{
// Storage to keep the object alive during process life
std::unique_ptr<open_power::host::command::Host> opHost
    __attribute__((init_priority(101)));
std::unique_ptr<sdbusplus::server::manager_t> objManager
    __attribute__((init_priority(101)));
} // namespace

void register_netfn_ibm_oem_commands()
{
    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_IBM_OEM,
           IPMI_CMD_PESEL);
    ipmi_register_callback(NETFUN_IBM_OEM, IPMI_CMD_PESEL, NULL,
                           ipmi_ibm_oem_partial_esel, SYSTEM_INTERFACE);

    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_OEM,
           IPMI_CMD_PREP_FW_UPDATE);
    ipmi_register_callback(NETFUN_OEM, IPMI_CMD_PREP_FW_UPDATE, NULL,
                           ipmi_ibm_oem_prep_fw_update, SYSTEM_INTERFACE);

    ipmi_register_callback(NETFUN_IBM_OEM, IPMI_CMD_BMC_FACTORY_RESET, NULL,
                           ipmi_ibm_oem_bmc_factory_reset, SYSTEM_INTERFACE);

    // Create new object on the bus
    auto objPath = std::string{CONTROL_HOST_OBJ_MGR} + '/' + HOST_NAME + '0';

    // Add sdbusplus ObjectManager.
    auto& sdbusPlusHandler = ipmid_get_sdbus_plus_handler();
    objManager = std::make_unique<sdbusplus::server::manager_t>(
        *sdbusPlusHandler, CONTROL_HOST_OBJ_MGR);

    opHost = std::make_unique<open_power::host::command::Host>(
        *sdbusPlusHandler, objPath.c_str());

    // Service for this is provided by phosphor layer systemcmdintf
    // and this will be as part of that.
    return;
}
