/**
 * 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 <fcntl.h>
#include <sys/stat.h>

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

#include <fstream>

namespace openpower
{
namespace pels
{

namespace fs = std::filesystem;
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;
        lg2::error("Call to stat() failed on {FILE} with errno {ERRNO}", "FILE",
                   file.native(), "ERRNO", e);
        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)
                    {
                        lg2::error(
                            "Failed to save PEL after updating host state, PEL ID = {ID}",
                            "ID", lg2::hex, 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(),
                    pel.plid(),
                    pel.getDeconfigFlag(),
                    pel.getGuardFlag(),
                    getMillisecondsSinceEpoch(
                        pel.privateHeader().createTimestamp())};

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

                updateRepoStats(attributes, true);
            }
            else
            {
                lg2::error(
                    "Found invalid PEL file {FILE} while restoring.  Removing.",
                    "FILE", dirEntry.path());
                fs::remove(dirEntry.path());
            }
        }
        catch (const std::exception& e)
        {
            lg2::error("Hit exception while restoring PEL file {FILE}: {ERROR}",
                       "FILE", dirEntry.path(), "ERROR", e);
        }
    }

    // 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(),
        pel->plid(),
        pel->getDeconfigFlag(),
        pel->getGuardFlag(),
        getMillisecondsSinceEpoch(pel->privateHeader().createTimestamp())};

    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);
        lg2::error(
            "Unable to open PEL file {FILE} for writing, errno = {ERRNO}",
            "FILE", path, "ERRNO", e);
        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);
        lg2::error("Unable to write PEL file {FILE}, errno = {ERRNO}", "FILE",
                   path, "ERRNO", e);
        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);

    lg2::debug(
        "Removing PEL from repository, PEL ID = {PEL_ID}, BMC log ID = {BMC_ID}",
        "PEL_ID", lg2::hex, actualID.pelID.id, "BMC_ID", 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;
            lg2::error("Unable to open PEL file {FILE}, errno = {ERRNO}",
                       "FILE", pel->second.path, "ERRNO", e);
            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())
    {
        int fd = open(pel->second.path.c_str(), O_RDONLY | O_NONBLOCK);
        if (fd == -1)
        {
            auto e = errno;
            lg2::error("Unable to open PEL file {FILE}, errno = {ERRNO}",
                       "FILE", pel->second.path, "ERRNO", e);
            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 fd;
    }
    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;
            lg2::error(
                "Repository::for_each: Unable to open PEL file {FILE}, errno = {ERRNO}",
                "FILE", attributes.path, "ERRNO", e);
            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)
        {
            lg2::error("Repository::for_each function exception: {ERROR}",
                       "ERROR", e);
        }
    }
}

void Repository::processAddCallbacks(const PEL& pel) const
{
    for (auto& [name, func] : _addSubscriptions)
    {
        try
        {
            func(pel);
        }
        catch (const std::exception& e)
        {
            lg2::error(
                "PEL Repository add callback exception. Name = {NAME}, Error = {ERROR}",
                "NAME", name, "ERROR", e);
        }
    }
}

void Repository::processDeleteCallbacks(uint32_t id) const
{
    for (auto& [name, func] : _deleteSubscriptions)
    {
        try
        {
            func(id);
        }
        catch (const std::exception& e)
        {
            lg2::error(
                "PEL Repository delete callback exception. Name = {NAME}, Error = {ERROR}",
                "NAME", name, "ERROR", e);
        }
    }
}

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);
            return true;
        };

        try
        {
            updatePEL(attr->second.path, func);
        }
        catch (const std::exception& e)
        {
            lg2::error(
                "Unable to update PEL host transmission state. Path = {PATH}, Error = {ERROR}",
                "PATH", attr->second.path, "ERROR", e);
        }
    }
}

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);
            return true;
        };

        try
        {
            updatePEL(attr->second.path, func);
        }
        catch (const std::exception& e)
        {
            lg2::error(
                "Unable to update PEL HMC transmission state. Path = {PATH}, Error = {ERROR}",
                "PATH", attr->second.path, "ERROR", e);
        }
    }
}

bool 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())
    {
        if (updateFunc(pel))
        {
            // Three attribute fields can change post creation from
            // an updatePEL call:
            //  - hmcTransmissionState - When HMC acks a PEL
            //  - hostTransmissionState - When host acks a PEL
            //  - deconfig flag - Can be cleared for PELs that call out
            //                    hotplugged FRUs.
            // Make sure they're up to date.
            LogID id{LogID::Pel(pel.id())};
            auto attr =
                std::find_if(_pelAttributes.begin(), _pelAttributes.end(),
                             [&id](const auto& a) { return a.first == id; });
            if (attr != _pelAttributes.end())
            {
                attr->second.hmcState = pel.hmcTransmissionState();
                attr->second.hostState = pel.hostTransmissionState();
                attr->second.deconfig = pel.getDeconfigFlag();
            }

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

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)))
    {
        lg2::info(
            "Repository::sizeWarning function:Deleting the files in archive");

        for (const auto& dirEntry : fs::directory_iterator(_archivePath))
        {
            fs::remove(dirEntry.path(), ec);
            if (ec)
            {
                lg2::info("Repository::sizeWarning: Could not delete "
                          "file {FILE} in PEL archive",
                          "FILE", dirEntry.path());
            }
        }

        _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;
    lg2::info("Pruning PEL repository that takes up {TOTAL} bytes and has "
              "{NUM_PELS} PELs",
              "TOTAL", _sizes.total, "NUM_PELS", _pelAttributes.size());

    // 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())
    {
        lg2::info("Number of PELs removed to save space: {NUM_PELS}",
                  "NUM_PELS", obmcLogIDs.size());
    }

    return obmcLogIDs;
}

void Repository::removePELs(const IsOverLimitFunc& isOverLimit,
                            const 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
