#include "config.h"

#include "ecc_manager.hpp"

#include <phosphor-logging/elog-errors.hpp>

#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>

using namespace phosphor::logging;

namespace phosphor
{
namespace memory
{
static constexpr const char ECC_FILE[] = "/etc/ecc/maxlog.conf";
static constexpr const auto RESET_COUNT = "1";
static constexpr const char CLOSE_EDAC_REPORT[] = "off";

auto retries = 3;
static constexpr auto delay = std::chrono::milliseconds{100};
static constexpr auto interval = 1000000;
static constexpr uint16_t selBMCGenID = 0x0020;
void ECC::init()
{
    namespace fs = std::filesystem;

    if (fs::exists(sysfsRootPath))
    {
        try
        {
            resetCounter();
            getMaxLogValue();
        }
        catch (const std::system_error& e)
        {
            log<level::INFO>(
                "Logging failing sysfs file",
                phosphor::logging::entry("FILE=%s", sysfsRootPath));
        }
    }
    _bus.request_name(BUSNAME);
}

std::string ECC::getValue(std::string fullPath)
{
    std::string val;
    std::ifstream ifs;

    while (true)
    {
        try
        {
            if (!ifs.is_open())
                ifs.open(fullPath);
            ifs.clear();
            ifs.seekg(0);
            ifs >> val;
        }
        catch (const std::exception& e)
        {
            --retries;
            std::this_thread::sleep_for(delay);
            continue;
        }
        break;
    }

    ifs.close();
    return val;
}

void ECC::writeValue(std::string fullPath, std::string value)
{
    std::ofstream ofs;
    while (true)
    {
        try
        {
            if (!ofs.is_open())
                ofs.open(fullPath);
            ofs.clear();
            ofs.seekp(0);
            ofs << value;
            ofs.flush();
        }
        catch (const std::exception& e)
        {
            --retries;
            std::this_thread::sleep_for(delay);
            continue;
        }
        break;
    }
    ofs.close();
}

void ECC::run()
{
    init();
    std::function<void()> callback(std::bind(&ECC::read, this));
    try
    {
        _timer.restart(std::chrono::microseconds(interval));

        _bus.attach_event(_event.get(), SD_EVENT_PRIORITY_IMPORTANT);
        _event.loop();
    }
    catch (const std::exception& e)
    {
        log<level::ERR>("Error in sysfs polling loop",
                        entry("ERROR=%s", e.what()));
        throw;
    }
}

void ECC::checkEccLogFull(int64_t ceCount, int64_t ueCount)
{
    std::string errorMsg = "ECC error(memory error logging limit reached)";
    std::vector<uint8_t> eccLogFullEventData{0x05, 0xff, 0xfe};
    bool assert = true;

    auto total = ceCount + ueCount;
    bool isReached = false;
    if (total == 0)
    {
        // someone reset edac report from driver
        // so clear all parameter
        EccInterface::ceCount(ceCount);
        EccInterface::ueCount(ueCount);
        previousCeCounter = 0;
        previousUeCounter = 0;
        EccInterface::isLoggingLimitReached(isReached);
    }
    else if (total >= maxECCLog)
    {
        // add SEL log
        addSELLog(errorMsg, OBJPATH, eccLogFullEventData, assert, selBMCGenID);
        isReached = true;
        EccInterface::isLoggingLimitReached(isReached);
        controlEDACReport(CLOSE_EDAC_REPORT);
        // set ECC state
        EccInterface::state(MemoryECC::ECCStatus::LogFull);
    }
}

int ECC::checkCeCount()
{
    std::string item = "ce_count";
    std::string errorMsg = "ECC error(correctable)";
    int64_t value = 0;
    std::string fullPath = sysfsRootPath;
    fullPath.append(item);
    value = std::stoi(getValue(fullPath));
    std::vector<uint8_t> eccCeEventData{0x00, 0xff, 0xfe};
    bool assert = true;

    while (previousCeCounter < value)
    {
        previousCeCounter++;
        // add phosphor-logging log
        EccInterface::ceCount(previousCeCounter);
        // add SEL log
        addSELLog(errorMsg, OBJPATH, eccCeEventData, assert, selBMCGenID);
        // set ECC state
        EccInterface::state(MemoryECC::ECCStatus::CE);
    }
    return value;
}

int ECC::checkUeCount()
{
    std::string item = "ue_count";
    std::string errorMsg = "ECC error(uncorrectable)";
    int64_t value = 0;
    std::string fullPath = sysfsRootPath;
    fullPath.append(item);
    value = std::stoi(getValue(fullPath));
    std::vector<uint8_t> eccUeEventData{0x01, 0xff, 0xfe};
    bool assert = true;

    while (previousUeCounter < value)
    {
        previousUeCounter++;
        // add phosphor-logging log
        EccInterface::ueCount(previousUeCounter);
        // add SEL log
        addSELLog(errorMsg, OBJPATH, eccUeEventData, assert, selBMCGenID);
        // set ECC state
        EccInterface::state(MemoryECC::ECCStatus::UE);
    }
    return value;
}

void ECC::resetCounter()
{
    std::string item = "reset_counters";
    std::string fullPath = sysfsRootPath;
    fullPath.append(item);
    writeValue(fullPath, RESET_COUNT);
}

void ECC::read()
{
    int64_t ceCount = 0;
    int64_t ueCount = 0;
    ceCount = checkCeCount();
    ueCount = checkUeCount();
    checkEccLogFull(ceCount, ueCount);
}

void ECC::controlEDACReport(std::string op)
{
    writeValue(sysfsEDACReportPath, op);
}

// get max log from file
void ECC::getMaxLogValue()
{
    maxECCLog = std::stoi(getValue(ECC_FILE));
}

void ECC::addSELLog(std::string message, std::string path,
                    std::vector<uint8_t> selData, bool assert, uint16_t genId)
{
    // sdbusplus::bus_t bus = sdbusplus::bus::new_default();

    auto selCall = _bus.new_method_call(
        "xyz.openbmc_project.Logging.IPMI", "/xyz/openbmc_project/Logging/IPMI",
        "xyz.openbmc_project.Logging.IPMI", "IpmiSelAdd");
    selCall.append(message, path, selData, assert, genId);

    auto selReply = _bus.call(selCall);
    if (selReply.is_method_error())
    {
        log<level::ERR>("add SEL log error\n");
    }
}

} // namespace memory
} // namespace phosphor
