#include "elog-errors.hpp"
#include "error-HostEvent.hpp"
#include "sensorhandler.hpp"
#include "storagehandler.hpp"
#include "types.hpp"

#include <host-ipmid/ipmid-api.h>
#include <mapper.h>
#include <systemd/sd-bus.h>

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <phosphor-logging/elog.hpp>
#include <vector>
#include <xyz/openbmc_project/Logging/Entry/server.hpp>

using namespace std;
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Logging::server;
extern const ipmi::sensor::InvObjectIDMap invSensors;

//////////////////////////
struct esel_section_headers_t
{
    uint8_t sectionid[2];
    uint8_t sectionlength[2];
    uint8_t version;
    uint8_t subsectiontype;
    uint8_t compid;
};

struct severity_values_t
{
    uint8_t type;
    Entry::Level level;
};

const std::vector<severity_values_t> g_sev_desc = {
    {0x10, Entry::Level::Warning}, // recoverable error
    {0x20, Entry::Level::Warning}, // predictive error
                                   // TODO via github issue 3066 : map level
                                   // below to Level::Unrecoverable
    {0x40, Entry::Level::Error},   // unrecoverable error
                                 // TODO via github issue 3066 : map level below
                                 // to Level::Critical
    {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 sev_lookup(uint8_t n)
{
    auto i =
        std::find_if(std::begin(g_sev_desc), std::end(g_sev_desc),
                     [n](auto p) { return p.type == n || p.type == 0xFF; });
    return i->level;
}

int find_sensor_type_string(uint8_t sensor_number, char** s)
{

    dbus_interface_t a;
    const char* p;
    int r;

    r = find_openbmc_path(sensor_number, &a);

    if ((r < 0) || (a.bus[0] == 0))
    {
        // Just make a generic message for errors that
        // occur on sensors that don't exist
        r = asprintf(s, "Unknown Sensor (0x%02x)", sensor_number);
    }
    else
    {

        if ((p = strrchr(a.path, '/')) == NULL)
        {
            p = "/Unknown Sensor";
        }

        *s = strdup(p + 1);
    }

    return 0;
}

size_t getfilestream(const char* fn, uint8_t** buffer)
{

    FILE* fp;
    ssize_t size = 0;
    int r;

    if ((fp = fopen(fn, "rb")) != NULL)
    {

        r = fseek(fp, 0, SEEK_END);
        if (r)
        {
            log<level::ERR>("Fseek failed");
            goto fclose_fp;
        }

        size = ftell(fp);
        if (size == -1L)
        {
            log<level::ERR>("Ftell failed", entry("ERROR=%s", strerror(errno)));
            size = 0;
            goto fclose_fp;
        }

        r = fseek(fp, 0, SEEK_SET);
        if (r)
        {
            log<level::ERR>("Fseek failed");
            size = 0;
            goto fclose_fp;
        }

        *buffer = new uint8_t[size];

        r = fread(*buffer, 1, size, fp);
        if (r != size)
        {
            size = 0;
            log<level::ERR>("Fread failed\n");
        }

    fclose_fp:
        fclose(fp);
    }

    return static_cast<size_t>(size);
}

Entry::Level create_esel_severity(const uint8_t* buffer)
{

    uint8_t severity;
    // Dive in to the IBM log to find the severity
    severity = (0xF0 & buffer[0x4A]);

    return sev_lookup(severity);
}

int create_esel_association(const uint8_t* buffer, std::string& inventoryPath)
{
    ipmi_add_sel_request_t* p;
    uint8_t sensor;

    p = (ipmi_add_sel_request_t*)buffer;

    sensor = p->sensornumber;

    inventoryPath = {};

    /*
     * Search the sensor number to inventory path mapping to figure out the
     * inventory associated with the ESEL.
     */
    for (auto const& iter : invSensors)
    {
        if (iter.second.sensorID == sensor)
        {
            inventoryPath = iter.first;
            break;
        }
    }

    return 0;
}

int create_esel_description(const uint8_t* buffer, Entry::Level level,
                            char** message)
{

    ipmi_add_sel_request_t* p;
    char* m;
    int r;

    p = (ipmi_add_sel_request_t*)buffer;

    find_sensor_type_string(p->sensornumber, &m);

    r = asprintf(message, "A %s has experienced an error of level %d", m,
                 static_cast<uint32_t>(level));
    if (r == -1)
    {
        log<level::ERR>("Failed to allocate memory for ESEL description");
    }

    free(m);

    return 0;
}

int send_esel_to_dbus(const char* desc, Entry::Level level,
                      const std::string& inventoryPath, uint8_t* debug,
                      size_t debuglen)
{

    // Allocate enough space to represent the data in hex separated by spaces,
    // to mimic how IPMI would display the data.
    unique_ptr<char[]> selData(new char[(debuglen * 3) + 1]());
    uint32_t i = 0;
    for (i = 0; i < debuglen; i++)
    {
        sprintf(&selData[i * 3], "%02x ", 0xFF & ((char*)debug)[i]);
    }
    selData[debuglen * 3] = '\0';

    using error = sdbusplus::org::open_power::Host::Error::Event;
    using metadata = org::open_power::Host::Event;

    report<error>(level, metadata::ESEL(selData.get()),
                  metadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));

    return 0;
}

void send_esel(uint16_t recordid)
{
    char* desc;
    uint8_t* buffer = NULL;
    const char* path = "/tmp/esel";
    ssize_t sz;
    int r;
    std::string inventoryPath;

    sz = getfilestream(path, &buffer);
    if (sz == 0)
    {
        log<level::ERR>("Error file does not exist",
                        entry("FILENAME=%s", path));
        return;
    }

    auto sev = create_esel_severity(buffer);
    create_esel_association(buffer, inventoryPath);
    create_esel_description(buffer, sev, &desc);

    r = send_esel_to_dbus(desc, sev, inventoryPath, buffer, sz);
    if (r < 0)
    {
        log<level::ERR>("Failed to send esel to dbus");
    }

    free(desc);
    delete[] buffer;

    return;
}

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 createProcedureLogEntry(uint8_t procedureNum)
{
    // Read the eSEL data from the file.
    static constexpr auto eSELFile = "/tmp/esel";
    auto eSELData = readESEL(eSELFile);

    // Each byte in eSEL is formatted as %02x with a space between bytes and
    // insert '/0' at the end of the character array.
    static constexpr auto byteSeparator = 3;
    std::unique_ptr<char[]> data(
        new char[(eSELData.size() * byteSeparator) + 1]());

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

    using error = sdbusplus::org::open_power::Host::Error::MaintenanceProcedure;
    using metadata = org::open_power::Host::MaintenanceProcedure;

    report<error>(metadata::ESEL(data.get()),
                  metadata::PROCEDURE(static_cast<uint32_t>(procedureNum)));
}
