/**
 * Copyright © 2019 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "repository.hpp"

#include <sys/stat.h>

#include <fstream>
#include <phosphor-logging/log.hpp>
#include <xyz/openbmc_project/Common/File/error.hpp>

namespace openpower
{
namespace pels
{

namespace fs = std::filesystem;
using namespace phosphor::logging;
namespace file_error = sdbusplus::xyz::openbmc_project::Common::File::Error;

constexpr size_t warningPercentage = 95;

/**
 * @brief Returns the amount of space the file uses on disk.
 *
 * This is different than just the regular size of the file.
 *
 * @param[in] file - The file to get the size of
 *
 * @return size_t The disk space the file uses
 */
size_t getFileDiskSize(const std::filesystem::path& file)
{
    constexpr size_t statBlockSize = 512;
    struct stat statData;
    auto rc = stat(file.c_str(), &statData);
    if (rc != 0)
    {
        auto e = errno;
        std::string msg = "call to stat() failed on " + file.native() +
                          " with errno " + std::to_string(e);
        log<level::ERR>(msg.c_str());
        abort();
    }

    return statData.st_blocks * statBlockSize;
}

Repository::Repository(const std::filesystem::path& basePath, size_t repoSize,
                       size_t maxNumPELs) :
    _logPath(basePath / "logs"),
    _maxRepoSize(repoSize), _maxNumPELs(maxNumPELs),
    _archivePath(basePath / "logs" / "archive")
{
    if (!fs::exists(_logPath))
    {
        fs::create_directories(_logPath);
    }

    if (!fs::exists(_archivePath))
    {
        fs::create_directories(_archivePath);
    }

    restore();
}

void Repository::restore()
{
    for (auto& dirEntry : fs::directory_iterator(_logPath))
    {
        try
        {
            if (!fs::is_regular_file(dirEntry.path()))
            {
                continue;
            }

            std::ifstream file{dirEntry.path()};
            std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
                                      std::istreambuf_iterator<char>()};
            file.close();

            PEL pel{data};
            if (pel.valid())
            {
                // If the host hasn't acked it, reset the host state so
                // it will get sent up again.
                if (pel.hostTransmissionState() == TransmissionState::sent)
                {
                    pel.setHostTransmissionState(TransmissionState::newPEL);
                    try
                    {
                        write(pel, dirEntry.path());
                    }
                    catch (const std::exception& e)
                    {
                        log<level::ERR>(
                            "Failed to save PEL after updating host state",
                            entry("PELID=0x%X", pel.id()));
                    }
                }

                PELAttributes attributes{dirEntry.path(),
                                         getFileDiskSize(dirEntry.path()),
                                         pel.privateHeader().creatorID(),
                                         pel.userHeader().subsystem(),
                                         pel.userHeader().severity(),
                                         pel.userHeader().actionFlags(),
                                         pel.hostTransmissionState(),
                                         pel.hmcTransmissionState()};

                using pelID = LogID::Pel;
                using obmcID = LogID::Obmc;
                _pelAttributes.emplace(
                    LogID(pelID(pel.id()), obmcID(pel.obmcLogID())),
                    attributes);

                updateRepoStats(attributes, true);
            }
            else
            {
                log<level::ERR>(
                    "Found invalid PEL file while restoring.  Removing.",
                    entry("FILENAME=%s", dirEntry.path().c_str()));
                fs::remove(dirEntry.path());
            }
        }
        catch (const std::exception& e)
        {
            log<level::ERR>("Hit exception while restoring PEL File",
                            entry("FILENAME=%s", dirEntry.path().c_str()),
                            entry("ERROR=%s", e.what()));
        }
    }

    // Get size of archive folder
    for (auto& dirEntry : fs::directory_iterator(_archivePath))
    {
        _archiveSize += getFileDiskSize(dirEntry);
    }
}

std::string Repository::getPELFilename(uint32_t pelID, const BCDTime& time)
{
    char name[50];
    sprintf(name, "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X_%.8X", time.yearMSB,
            time.yearLSB, time.month, time.day, time.hour, time.minutes,
            time.seconds, time.hundredths, pelID);
    return std::string{name};
}

void Repository::add(std::unique_ptr<PEL>& pel)
{
    pel->setHostTransmissionState(TransmissionState::newPEL);
    pel->setHMCTransmissionState(TransmissionState::newPEL);

    auto path = _logPath / getPELFilename(pel->id(), pel->commitTime());

    write(*(pel.get()), path);

    PELAttributes attributes{path,
                             getFileDiskSize(path),
                             pel->privateHeader().creatorID(),
                             pel->userHeader().subsystem(),
                             pel->userHeader().severity(),
                             pel->userHeader().actionFlags(),
                             pel->hostTransmissionState(),
                             pel->hmcTransmissionState()};

    using pelID = LogID::Pel;
    using obmcID = LogID::Obmc;
    _pelAttributes.emplace(LogID(pelID(pel->id()), obmcID(pel->obmcLogID())),
                           attributes);

    _lastPelID = pel->id();

    updateRepoStats(attributes, true);

    processAddCallbacks(*pel);
}

void Repository::write(const PEL& pel, const fs::path& path)
{
    std::ofstream file{path, std::ios::binary};

    if (!file.good())
    {
        // If this fails, the filesystem is probably full so it isn't like
        // we could successfully create yet another error log here.
        auto e = errno;
        fs::remove(path);
        log<level::ERR>("Unable to open PEL file for writing",
                        entry("ERRNO=%d", e), entry("PATH=%s", path.c_str()));
        throw file_error::Open();
    }

    auto data = pel.data();
    file.write(reinterpret_cast<const char*>(data.data()), data.size());

    if (file.fail())
    {
        // Same note as above about not being able to create an error log
        // for this case even if we wanted.
        auto e = errno;
        file.close();
        fs::remove(path);
        log<level::ERR>("Unable to write PEL file", entry("ERRNO=%d", e),
                        entry("PATH=%s", path.c_str()));
        throw file_error::Write();
    }
}

std::optional<Repository::LogID> Repository::remove(const LogID& id)
{
    auto pel = findPEL(id);
    if (pel == _pelAttributes.end())
    {
        return std::nullopt;
    }

    LogID actualID = pel->first;
    updateRepoStats(pel->second, false);

    log<level::DEBUG>("Removing PEL from repository",
                      entry("PEL_ID=0x%X", actualID.pelID.id),
                      entry("OBMC_LOG_ID=%d", actualID.obmcID.id));

    if (fs::exists(pel->second.path))
    {
        // Check for existense of new archive folder
        if (!fs::exists(_archivePath))
        {
            fs::create_directories(_archivePath);
        }

        // Move log file to archive folder
        auto fileName = _archivePath / pel->second.path.filename();
        fs::rename(pel->second.path, fileName);

        // Update size of file
        _archiveSize += getFileDiskSize(fileName);
    }

    _pelAttributes.erase(pel);

    processDeleteCallbacks(actualID.pelID.id);

    return actualID;
}

std::optional<std::vector<uint8_t>> Repository::getPELData(const LogID& id)
{
    auto pel = findPEL(id);
    if (pel != _pelAttributes.end())
    {
        std::ifstream file{pel->second.path.c_str()};
        if (!file.good())
        {
            auto e = errno;
            log<level::ERR>("Unable to open PEL file", entry("ERRNO=%d", e),
                            entry("PATH=%s", pel->second.path.c_str()));
            throw file_error::Open();
        }

        std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
                                  std::istreambuf_iterator<char>()};
        return data;
    }

    return std::nullopt;
}

std::optional<sdbusplus::message::unix_fd> Repository::getPELFD(const LogID& id)
{
    auto pel = findPEL(id);
    if (pel != _pelAttributes.end())
    {
        FILE* fp = fopen(pel->second.path.c_str(), "rb");

        if (fp == nullptr)
        {
            auto e = errno;
            log<level::ERR>("Unable to open PEL File", entry("ERRNO=%d", e),
                            entry("PATH=%s", pel->second.path.c_str()));
            throw file_error::Open();
        }

        // Must leave the file open here.  It will be closed by sdbusplus
        // when it sends it back over D-Bus.

        return fileno(fp);
    }
    return std::nullopt;
}

void Repository::for_each(ForEachFunc func) const
{
    for (const auto& [id, attributes] : _pelAttributes)
    {
        std::ifstream file{attributes.path};

        if (!file.good())
        {
            auto e = errno;
            log<level::ERR>("Repository::for_each: Unable to open PEL file",
                            entry("ERRNO=%d", e),
                            entry("PATH=%s", attributes.path.c_str()));
            continue;
        }

        std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
                                  std::istreambuf_iterator<char>()};
        file.close();

        PEL pel{data};

        try
        {
            if (func(pel))
            {
                break;
            }
        }
        catch (const std::exception& e)
        {
            log<level::ERR>("Repository::for_each function exception",
                            entry("ERROR=%s", e.what()));
        }
    }
}

void Repository::processAddCallbacks(const PEL& pel) const
{
    for (auto& [name, func] : _addSubscriptions)
    {
        try
        {
            func(pel);
        }
        catch (const std::exception& e)
        {
            log<level::ERR>("PEL Repository add callback exception",
                            entry("NAME=%s", name.c_str()),
                            entry("ERROR=%s", e.what()));
        }
    }
}

void Repository::processDeleteCallbacks(uint32_t id) const
{
    for (auto& [name, func] : _deleteSubscriptions)
    {
        try
        {
            func(id);
        }
        catch (const std::exception& e)
        {
            log<level::ERR>("PEL Repository delete callback exception",
                            entry("NAME=%s", name.c_str()),
                            entry("ERROR=%s", e.what()));
        }
    }
}

std::optional<std::reference_wrapper<const Repository::PELAttributes>>
    Repository::getPELAttributes(const LogID& id) const
{
    auto pel = findPEL(id);
    if (pel != _pelAttributes.end())
    {
        return pel->second;
    }

    return std::nullopt;
}

void Repository::setPELHostTransState(uint32_t pelID, TransmissionState state)
{
    LogID id{LogID::Pel{pelID}};
    auto attr = std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
                             [&id](const auto& a) { return a.first == id; });

    if ((attr != _pelAttributes.end()) && (attr->second.hostState != state))
    {
        PELUpdateFunc func = [state](PEL& pel) {
            pel.setHostTransmissionState(state);
        };

        try
        {
            updatePEL(attr->second.path, func);

            attr->second.hostState = state;
        }
        catch (const std::exception& e)
        {
            log<level::ERR>("Unable to update PEL host transmission state",
                            entry("PATH=%s", attr->second.path.c_str()),
                            entry("ERROR=%s", e.what()));
        }
    }
}

void Repository::setPELHMCTransState(uint32_t pelID, TransmissionState state)
{
    LogID id{LogID::Pel{pelID}};
    auto attr = std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
                             [&id](const auto& a) { return a.first == id; });

    if ((attr != _pelAttributes.end()) && (attr->second.hmcState != state))
    {
        PELUpdateFunc func = [state](PEL& pel) {
            pel.setHMCTransmissionState(state);
        };

        try
        {
            updatePEL(attr->second.path, func);

            attr->second.hmcState = state;
        }
        catch (const std::exception& e)
        {
            log<level::ERR>("Unable to update PEL HMC transmission state",
                            entry("PATH=%s", attr->second.path.c_str()),
                            entry("ERROR=%s", e.what()));
        }
    }
}

void Repository::updatePEL(const fs::path& path, PELUpdateFunc updateFunc)
{
    std::ifstream file{path};
    std::vector<uint8_t> data{std::istreambuf_iterator<char>(file),
                              std::istreambuf_iterator<char>()};
    file.close();

    PEL pel{data};

    if (pel.valid())
    {
        updateFunc(pel);

        write(pel, path);
    }
    else
    {
        throw std::runtime_error(
            "Unable to read a valid PEL when trying to update it");
    }
}

bool Repository::isServiceableSev(const PELAttributes& pel)
{
    auto sevType = static_cast<SeverityType>(pel.severity & 0xF0);
    auto sevPVEntry =
        pel_values::findByValue(pel.severity, pel_values::severityValues);
    std::string sevName = std::get<pel_values::registryNamePos>(*sevPVEntry);

    bool check1 = (sevType == SeverityType::predictive) ||
                  (sevType == SeverityType::unrecoverable) ||
                  (sevType == SeverityType::critical);

    bool check2 = ((sevType == SeverityType::recovered) ||
                   (sevName == "symptom_recovered")) &&
                  !pel.actionFlags.test(hiddenFlagBit);

    bool check3 = (sevName == "symptom_predictive") ||
                  (sevName == "symptom_unrecoverable") ||
                  (sevName == "symptom_critical");

    return check1 || check2 || check3;
}

void Repository::updateRepoStats(const PELAttributes& pel, bool pelAdded)
{
    auto isServiceable = Repository::isServiceableSev(pel);
    auto bmcPEL = CreatorID::openBMC == static_cast<CreatorID>(pel.creator);

    auto adjustSize = [pelAdded, &pel](auto& runningSize) {
        if (pelAdded)
        {
            runningSize += pel.sizeOnDisk;
        }
        else
        {
            runningSize = std::max(static_cast<int64_t>(runningSize) -
                                       static_cast<int64_t>(pel.sizeOnDisk),
                                   static_cast<int64_t>(0));
        }
    };

    adjustSize(_sizes.total);

    if (bmcPEL)
    {
        adjustSize(_sizes.bmc);
        if (isServiceable)
        {
            adjustSize(_sizes.bmcServiceable);
        }
        else
        {
            adjustSize(_sizes.bmcInfo);
        }
    }
    else
    {
        adjustSize(_sizes.nonBMC);
        if (isServiceable)
        {
            adjustSize(_sizes.nonBMCServiceable);
        }
        else
        {
            adjustSize(_sizes.nonBMCInfo);
        }
    }
}

bool Repository::sizeWarning()
{
    std::error_code ec;

    if ((_archiveSize > 0) && ((_sizes.total + _archiveSize) >
                               ((_maxRepoSize * warningPercentage) / 100)))
    {
        log<level::INFO>(
            "Repository::sizeWarning function:Deleting the files in archive");

        for (const auto& dirEntry : fs::directory_iterator(_archivePath))
        {
            fs::remove(dirEntry.path(), ec);
            if (ec)
            {
                log<level::INFO>(
                    "Repository::sizeWarning function:Could not delete "
                    "a file in PEL archive",
                    entry("FILENAME=%s", dirEntry.path().c_str()));
            }
        }

        _archiveSize = 0;
    }

    return (_sizes.total > (_maxRepoSize * warningPercentage / 100)) ||
           (_pelAttributes.size() > _maxNumPELs);
}

std::vector<Repository::AttributesReference>
    Repository::getAllPELAttributes(SortOrder order) const
{
    std::vector<Repository::AttributesReference> attributes;

    std::for_each(
        _pelAttributes.begin(), _pelAttributes.end(),
        [&attributes](auto& pelEntry) { attributes.push_back(pelEntry); });

    std::sort(attributes.begin(), attributes.end(),
              [order](const auto& left, const auto& right) {
                  if (order == SortOrder::ascending)
                  {
                      return left.get().second.path < right.get().second.path;
                  }
                  return left.get().second.path > right.get().second.path;
              });

    return attributes;
}

std::vector<uint32_t>
    Repository::prune(const std::vector<uint32_t>& idsWithHwIsoEntry)
{
    std::vector<uint32_t> obmcLogIDs;
    std::string msg = "Pruning PEL repository that takes up " +
                      std::to_string(_sizes.total) + " bytes and has " +
                      std::to_string(_pelAttributes.size()) + " PELs";
    log<level::INFO>(msg.c_str());

    // Set up the 5 functions to check if the PEL category
    // is still over its limits.

    // BMC informational PELs should only take up 15%
    IsOverLimitFunc overBMCInfoLimit = [this]() {
        return _sizes.bmcInfo > _maxRepoSize * 15 / 100;
    };

    // BMC non informational PELs should only take up 30%
    IsOverLimitFunc overBMCNonInfoLimit = [this]() {
        return _sizes.bmcServiceable > _maxRepoSize * 30 / 100;
    };

    // Non BMC informational PELs should only take up 15%
    IsOverLimitFunc overNonBMCInfoLimit = [this]() {
        return _sizes.nonBMCInfo > _maxRepoSize * 15 / 100;
    };

    // Non BMC non informational PELs should only take up 15%
    IsOverLimitFunc overNonBMCNonInfoLimit = [this]() {
        return _sizes.nonBMCServiceable > _maxRepoSize * 30 / 100;
    };

    // Bring the total number of PELs down to 80% of the max
    IsOverLimitFunc tooManyPELsLimit = [this]() {
        return _pelAttributes.size() > _maxNumPELs * 80 / 100;
    };

    // Set up the functions to determine which category a PEL is in.
    // TODO: Return false in these functions if a PEL caused a guard record.

    // A BMC informational PEL
    IsPELTypeFunc isBMCInfo = [](const PELAttributes& pel) {
        return (CreatorID::openBMC == static_cast<CreatorID>(pel.creator)) &&
               !Repository::isServiceableSev(pel);
    };

    // A BMC non informational PEL
    IsPELTypeFunc isBMCNonInfo = [](const PELAttributes& pel) {
        return (CreatorID::openBMC == static_cast<CreatorID>(pel.creator)) &&
               Repository::isServiceableSev(pel);
    };

    // A non BMC informational PEL
    IsPELTypeFunc isNonBMCInfo = [](const PELAttributes& pel) {
        return (CreatorID::openBMC != static_cast<CreatorID>(pel.creator)) &&
               !Repository::isServiceableSev(pel);
    };

    // A non BMC non informational PEL
    IsPELTypeFunc isNonBMCNonInfo = [](const PELAttributes& pel) {
        return (CreatorID::openBMC != static_cast<CreatorID>(pel.creator)) &&
               Repository::isServiceableSev(pel);
    };

    // When counting PELs, count every PEL
    IsPELTypeFunc isAnyPEL = [](const PELAttributes& /*pel*/) { return true; };

    // Check all 4 categories, which will result in at most 90%
    // usage (15 + 30 + 15 + 30).
    removePELs(overBMCInfoLimit, isBMCInfo, idsWithHwIsoEntry, obmcLogIDs);
    removePELs(overBMCNonInfoLimit, isBMCNonInfo, idsWithHwIsoEntry,
               obmcLogIDs);
    removePELs(overNonBMCInfoLimit, isNonBMCInfo, idsWithHwIsoEntry,
               obmcLogIDs);
    removePELs(overNonBMCNonInfoLimit, isNonBMCNonInfo, idsWithHwIsoEntry,
               obmcLogIDs);

    // After the above pruning check if there are still too many PELs,
    // which can happen depending on PEL sizes.
    if (_pelAttributes.size() > _maxNumPELs)
    {
        removePELs(tooManyPELsLimit, isAnyPEL, idsWithHwIsoEntry, obmcLogIDs);
    }

    if (!obmcLogIDs.empty())
    {
        std::string msg = "Number of PELs removed to save space: " +
                          std::to_string(obmcLogIDs.size());
        log<level::INFO>(msg.c_str());
    }

    return obmcLogIDs;
}

void Repository::removePELs(IsOverLimitFunc& isOverLimit,
                            IsPELTypeFunc& isPELType,
                            const std::vector<uint32_t>& idsWithHwIsoEntry,
                            std::vector<uint32_t>& removedBMCLogIDs)
{
    if (!isOverLimit())
    {
        return;
    }

    auto attributes = getAllPELAttributes(SortOrder::ascending);

    // Make 4 passes on the PELs, stopping as soon as isOverLimit
    // returns false.
    //   Pass 1: only delete HMC acked PELs
    //   Pass 2: only delete OS acked PELs
    //   Pass 3: only delete PHYP sent PELs
    //   Pass 4: delete all PELs
    static const std::vector<std::function<bool(const PELAttributes& pel)>>
        stateChecks{[](const auto& pel) {
                        return pel.hmcState == TransmissionState::acked;
                    },

                    [](const auto& pel) {
                        return pel.hostState == TransmissionState::acked;
                    },

                    [](const auto& pel) {
                        return pel.hostState == TransmissionState::sent;
                    },

                    [](const auto& /*pel*/) { return true; }};

    for (const auto& stateCheck : stateChecks)
    {
        for (auto it = attributes.begin(); it != attributes.end();)
        {
            const auto& pel = it->get();
            if (isPELType(pel.second) && stateCheck(pel.second))
            {
                auto removedID = pel.first.obmcID.id;

                auto idFound = std::find(idsWithHwIsoEntry.begin(),
                                         idsWithHwIsoEntry.end(), removedID);
                if (idFound != idsWithHwIsoEntry.end())
                {
                    ++it;
                    continue;
                }

                remove(pel.first);

                removedBMCLogIDs.push_back(removedID);

                attributes.erase(it);

                if (!isOverLimit())
                {
                    break;
                }
            }
            else
            {
                ++it;
            }
        }

        if (!isOverLimit())
        {
            break;
        }
    }
}

void Repository::archivePEL(const PEL& pel)
{
    if (pel.valid())
    {
        auto path = _archivePath / getPELFilename(pel.id(), pel.commitTime());

        write(pel, path);

        _archiveSize += getFileDiskSize(path);
    }
}

} // namespace pels
} // namespace openpower
