/**
 * 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 "registry.hpp"

#include "json_utils.hpp"
#include "pel_types.hpp"
#include "pel_values.hpp"

#include <phosphor-logging/lg2.hpp>

#include <algorithm>
#include <fstream>

namespace openpower
{
namespace pels
{
namespace message
{

namespace pv = pel_values;
namespace fs = std::filesystem;

constexpr auto debugFilePath = "/etc/phosphor-logging/";

namespace helper
{

uint8_t getSubsystem(const std::string& subsystemName)
{
    // Get the actual value to use in the PEL for the string name
    auto ss = pv::findByName(subsystemName, pv::subsystemValues);
    if (ss == pv::subsystemValues.end())
    {
        // Schema validation should be catching this.
        lg2::error("Invalid subsystem name used in message registry: {SUBSYS}",
                   "SUBSYS", subsystemName);

        throw std::runtime_error("Invalid subsystem used in message registry");
    }

    return std::get<pv::fieldValuePos>(*ss);
}

uint8_t getSeverity(const std::string& severityName)
{
    auto s = pv::findByName(severityName, pv::severityValues);
    if (s == pv::severityValues.end())
    {
        // Schema validation should be catching this.
        lg2::error("Invalid severity name used in message registry: {SEV}",
                   "SEV", severityName);

        throw std::runtime_error("Invalid severity used in message registry");
    }

    return std::get<pv::fieldValuePos>(*s);
}

std::vector<RegistrySeverity> getSeverities(const nlohmann::json& severity)
{
    std::vector<RegistrySeverity> severities;

    // The plain string value, like "unrecoverable"
    if (severity.is_string())
    {
        RegistrySeverity s;
        s.severity = getSeverity(severity.get<std::string>());
        severities.push_back(std::move(s));
    }
    else
    {
        // An array, with an element like:
        // {
        //    "SevValue": "unrecoverable",
        //    "System", "systemA"
        // }
        for (const auto& sev : severity)
        {
            RegistrySeverity s;
            s.severity = getSeverity(sev["SevValue"].get<std::string>());

            if (sev.contains("System"))
            {
                s.system = sev["System"].get<std::string>();
            }

            severities.push_back(std::move(s));
        }
    }

    return severities;
}

uint16_t getActionFlags(const std::vector<std::string>& flags)
{
    uint16_t actionFlags = 0;

    // Make the bitmask based on the array of flag names
    for (const auto& flag : flags)
    {
        auto s = pv::findByName(flag, pv::actionFlagsValues);
        if (s == pv::actionFlagsValues.end())
        {
            // Schema validation should be catching this.
            lg2::error(
                "Invalid action flag name used in message registry: {FLAG}",
                "FLAG", flag);

            throw std::runtime_error(
                "Invalid action flag used in message registry");
        }

        actionFlags |= std::get<pv::fieldValuePos>(*s);
    }

    return actionFlags;
}

uint8_t getEventType(const std::string& eventTypeName)
{
    auto t = pv::findByName(eventTypeName, pv::eventTypeValues);
    if (t == pv::eventTypeValues.end())
    {
        lg2::error("Invalid event type used in message registry: {TYPE}",
                   "TYPE", eventTypeName);

        throw std::runtime_error("Invalid event type used in message registry");
    }
    return std::get<pv::fieldValuePos>(*t);
}

uint8_t getEventScope(const std::string& eventScopeName)
{
    auto s = pv::findByName(eventScopeName, pv::eventScopeValues);
    if (s == pv::eventScopeValues.end())
    {
        lg2::error("Invalid event scope used in registry: {SCOPE}", "SCOPE",
                   eventScopeName);

        throw std::runtime_error(
            "Invalid event scope used in message registry");
    }
    return std::get<pv::fieldValuePos>(*s);
}

uint16_t getSRCReasonCode(const nlohmann::json& src, const std::string& name)
{
    std::string rc = src["ReasonCode"];
    uint16_t reasonCode = strtoul(rc.c_str(), nullptr, 16);
    if (reasonCode == 0)
    {
        lg2::error(
            "Invalid reason code {RC} in message registry, error name = {ERROR}",
            "RC", rc, "ERROR", name);

        throw std::runtime_error("Invalid reason code in message registry");
    }
    return reasonCode;
}

uint8_t getSRCType(const nlohmann::json& src, const std::string& name)
{
    // Looks like: "22"
    std::string srcType = src["Type"];
    size_t type = strtoul(srcType.c_str(), nullptr, 16);
    if ((type == 0) || (srcType.size() != 2)) // 1 hex byte
    {
        lg2::error(
            "Invalid SRC Type {TYPE} in message registry, error name = {ERROR}",
            "TYPE", srcType, "ERROR", name);

        throw std::runtime_error("Invalid SRC Type in message registry");
    }

    return type;
}

bool getSRCDeconfigFlag(const nlohmann::json& src)
{
    return src["DeconfigFlag"].get<bool>();
}

bool getSRCCheckstopFlag(const nlohmann::json& src)
{
    return src["CheckstopFlag"].get<bool>();
}

std::optional<std::map<SRC::WordNum, SRC::AdditionalDataField>>
    getSRCHexwordFields(const nlohmann::json& src, const std::string& name)
{
    std::map<SRC::WordNum, SRC::AdditionalDataField> hexwordFields;

    // Build the map of which AdditionalData fields to use for which SRC words

    // Like:
    // {
    //   "8":
    //   {
    //     "AdditionalDataPropSource": "TEST"
    //   }
    //
    // }

    for (const auto& word : src["Words6To9"].items())
    {
        std::string num = word.key();
        size_t wordNum = std::strtoul(num.c_str(), nullptr, 10);

        if (wordNum == 0)
        {
            lg2::error(
                "Invalid SRC word number {NUM} in message registry, error name = {ERROR}",
                "NUM", num, "ERROR", name);

            throw std::runtime_error("Invalid SRC word in message registry");
        }

        auto attributes = word.value();

        // Use an empty string for the description if it does not exist.
        auto itr = attributes.find("Description");
        std::string desc = (attributes.end() != itr) ? *itr : "";

        std::tuple<std::string, std::string> adPropSourceDesc(
            attributes["AdditionalDataPropSource"], desc);
        hexwordFields[wordNum] = std::move(adPropSourceDesc);
    }

    if (!hexwordFields.empty())
    {
        return hexwordFields;
    }

    return std::nullopt;
}
std::optional<std::vector<SRC::WordNum>>
    getSRCSymptomIDFields(const nlohmann::json& src, const std::string& name)
{
    std::vector<SRC::WordNum> symptomIDFields;

    // Looks like:
    // "SymptomIDFields": ["SRCWord3", "SRCWord6"],

    for (const std::string field : src["SymptomIDFields"])
    {
        // Just need the last digit off the end, e.g. SRCWord6.
        // The schema enforces the format of these.
        auto srcWordNum = field.substr(field.size() - 1);
        size_t num = std::strtoul(srcWordNum.c_str(), nullptr, 10);
        if (num == 0)
        {
            lg2::error(
                "Invalid symptom ID field {FIELD} in message registry, error name = {ERROR}",
                "FIELD", field, "ERROR", name);

            throw std::runtime_error("Invalid symptom ID in message registry");
        }
        symptomIDFields.push_back(num);
    }
    if (!symptomIDFields.empty())
    {
        return symptomIDFields;
    }

    return std::nullopt;
}

uint16_t getComponentID(uint8_t srcType, uint16_t reasonCode,
                        const nlohmann::json& pelEntry, const std::string& name)
{
    uint16_t id = 0;

    // If the ComponentID field is there, use that.  Otherwise, if it's a
    // 0xBD BMC error SRC, use the reasoncode.
    if (pelEntry.contains("ComponentID"))
    {
        std::string componentID = pelEntry["ComponentID"];
        id = strtoul(componentID.c_str(), nullptr, 16);
    }
    else
    {
        // On BMC error SRCs (BD), can just get the component ID from
        // the first byte of the reason code.
        if (srcType == static_cast<uint8_t>(SRCType::bmcError))
        {
            id = reasonCode & 0xFF00;
        }
        else
        {
            lg2::error(
                "Missing component ID field in message registry, error name = {ERROR}",
                "ERROR", name);

            throw std::runtime_error(
                "Missing component ID field in message registry");
        }
    }

    return id;
}

/**
 * @brief Says if the JSON is the format that contains AdditionalData keys
 *        as in index into them.
 *
 * @param[in] json - The highest level callout JSON
 *
 * @return bool - If it is the AdditionalData format or not
 */
bool calloutUsesAdditionalData(const nlohmann::json& json)
{
    return (json.contains("ADName") &&
            json.contains("CalloutsWithTheirADValues"));
}

/**
 * @brief Finds the callouts to use when there is no AdditionalData,
 *        but the system type may be used as a key.
 *
 * A sample calloutList array looks like the following.  The System and Systems
 * key are optional.
 *
 * System key - Value of the key will be the system name as a string. The
 * callouts for a specific system can define under this key.
 *
 * Systems key - Value of the key will be an array of system names in the form
 * of string. The callouts common to the systems mentioned in the array can
 * define under this key.
 *
 * If both System and Systems not present it means that entry applies to every
 * configuration that doesn't have another entry with a matching System and
 * Systems key.
 *
 *    {
 *        "System": "system1",
 *        "CalloutList":
 *        [
 *            {
 *                "Priority": "high",
 *                "LocCode": "P1-C1"
 *            },
 *            {
 *                "Priority": "low",
 *                "LocCode": "P1"
 *            }
 *        ]
 *    },
 *    {
 *        "Systems": ["system1", 'system2"],
 *        "CalloutList":
 *        [
 *            {
 *                "Priority": "high",
 *                "LocCode": "P0-C1"
 *            },
 *            {
 *                "Priority": "low",
 *                "LocCode": "P0"
 *            }
 *        ]
 *    }
 *
 * @param[in] json - The callout JSON
 * @param[in] systemNames - List of compatible system type names
 * @param[out] calloutLists - The JSON array which will hold the calloutlist to
 * use specific to the system.
 *
 * @return - Throws runtime exception if json is not an array or if calloutLists
 *           is empty.
 */
static void findCalloutList(const nlohmann::json& json,
                            const std::vector<std::string>& systemNames,
                            nlohmann::json& calloutLists)
{
    if (!json.is_array())
    {
        throw std::runtime_error{"findCalloutList was not passed a JSON array"};
    }

    // Flag to indicate whether system specific callouts found or not
    bool foundCallouts = false;

    for (const auto& callouts : json)
    {
        if (callouts.contains("System"))
        {
            if (std::ranges::find(systemNames,
                                  callouts["System"].get<std::string>()) !=
                systemNames.end())
            {
                calloutLists.insert(calloutLists.end(),
                                    callouts["CalloutList"].begin(),
                                    callouts["CalloutList"].end());
                foundCallouts = true;
            }
            continue;
        }

        if (callouts.contains("Systems"))
        {
            std::vector<std::string> systems =
                callouts["Systems"].get<std::vector<std::string>>();
            auto inSystemNames = [systemNames](const auto& system) {
                return (std::ranges::find(systemNames, system) !=
                        systemNames.end());
            };
            if (std::ranges::any_of(systems, inSystemNames))
            {
                calloutLists.insert(calloutLists.end(),
                                    callouts["CalloutList"].begin(),
                                    callouts["CalloutList"].end());
                foundCallouts = true;
            }
            continue;
        }

        // Any entry if neither System/Systems key matches with system name
        if (!foundCallouts)
        {
            calloutLists.insert(calloutLists.end(),
                                callouts["CalloutList"].begin(),
                                callouts["CalloutList"].end());
        }
    }
    if (calloutLists.empty())
    {
        std::string types;
        std::for_each(systemNames.begin(), systemNames.end(),
                      [&types](const auto& t) { types += t + '|'; });
        lg2::warning(
            "No matching system name entry or default system name entry "
            " for PEL callout list, names = {TYPES}",
            "TYPES", types);

        throw std::runtime_error{
            "Could not find a CalloutList JSON for this error and system name"};
    }
}

/**
 * @brief Creates a RegistryCallout based on the input JSON.
 *
 * The JSON looks like:
 *     {
 *          "Priority": "high",
 *          "LocCode": "E1"
 *          ...
 *     }
 *
 * Schema validation enforces what keys are present.
 *
 * @param[in] json - The JSON dictionary entry for a callout
 *
 * @return RegistryCallout - A filled in RegistryCallout
 */
RegistryCallout makeRegistryCallout(const nlohmann::json& json)
{
    RegistryCallout callout;

    callout.priority = "high";
    callout.useInventoryLocCode = false;

    if (json.contains("Priority"))
    {
        callout.priority = json["Priority"].get<std::string>();
    }

    if (json.contains("LocCode"))
    {
        callout.locCode = json["LocCode"].get<std::string>();
    }

    if (json.contains("Procedure"))
    {
        callout.procedure = json["Procedure"].get<std::string>();
    }
    else if (json.contains("SymbolicFRU"))
    {
        callout.symbolicFRU = json["SymbolicFRU"].get<std::string>();
    }
    else if (json.contains("SymbolicFRUTrusted"))
    {
        callout.symbolicFRUTrusted =
            json["SymbolicFRUTrusted"].get<std::string>();
    }

    if (json.contains("UseInventoryLocCode"))
    {
        callout.useInventoryLocCode = json["UseInventoryLocCode"].get<bool>();
    }

    return callout;
}

/**
 * @brief Returns the callouts to use when an AdditionalData key is
 *        required to find the correct entries.
 *
 *       The System property is used to find which CalloutList to use.
 *       If System is missing, then that CalloutList is valid for
 *       everything.
 *
 * The JSON looks like:
 *    {
 *        "System": "system1",
 *        "CalloutList":
 *        [
 *            {
 *                "Priority": "high",
 *                "LocCode": "P1-C1"
 *            },
 *            {
 *                "Priority": "low",
 *                "LocCode": "P1"
 *            }
 *        ]
 *    },
 *    {
 *        "Systems": ["system1", 'system2"],
 *        "CalloutList":
 *        [
 *            {
 *                "Priority": "high",
 *                "LocCode": "P0-C1"
 *            },
 *            {
 *                "Priority": "low",
 *                "LocCode": "P0"
 *            }
 *        ]
 *    }
 *
 * @param[in] json - The callout JSON
 * @param[in] systemNames - List of compatible system type names
 *
 * @return std::vector<RegistryCallout> - The callouts to use
 */
std::vector<RegistryCallout> getCalloutsWithoutAD(
    const nlohmann::json& json, const std::vector<std::string>& systemNames)
{
    std::vector<RegistryCallout> calloutEntries;

    nlohmann::json calloutLists = nlohmann::json::array();

    // Find the CalloutList to use based on the system type
    findCalloutList(json, systemNames, calloutLists);

    // We finally found the callouts, make the objects.
    for (const auto& callout : calloutLists)
    {
        calloutEntries.push_back(std::move(makeRegistryCallout(callout)));
    }

    return calloutEntries;
}

/**
 * @brief Returns the callouts to use when an AdditionalData key is
 *        required to find the correct entries.
 *
 * The JSON looks like:
 *    {
 *        "ADName": "PROC_NUM",
 *        "CalloutsWithTheirADValues":
 *        [
 *            {
 *                "ADValue": "0",
 *                "Callouts":
 *                [
 *                    {
 *                        "CalloutList":
 *                        [
 *                            {
 *                                "Priority": "high",
 *                                "LocCode": "P1-C5"
 *                            }
 *                        ]
 *                    }
 *                ]
 *            }
 *        ]
 *     }
 *
 * Note that the "Callouts" entry above is the same as the top level
 * entry used when there is no AdditionalData key.
 *
 * @param[in] json - The callout JSON
 * @param[in] systemNames - List of compatible system type names
 * @param[in] additionalData - The AdditionalData property
 *
 * @return std::vector<RegistryCallout> - The callouts to use
 */
std::vector<RegistryCallout> getCalloutsUsingAD(
    const nlohmann::json& json, const std::vector<std::string>& systemNames,
    const AdditionalData& additionalData)
{
    // This indicates which AD field we'll be using
    auto keyName = json["ADName"].get<std::string>();

    // Get the actual value from the AD data
    auto adValue = additionalData.getValue(keyName);

    if (!adValue)
    {
        // The AdditionalData did not contain the necessary key
        lg2::warning("The PEL message registry callouts JSON "
                     "said to use an AdditionalData key that isn't in the "
                     "AdditionalData event log property, key = {KEY}",
                     "KEY", keyName);
        throw std::runtime_error{
            "Missing AdditionalData entry for this callout"};
    }

    const auto& callouts = json["CalloutsWithTheirADValues"];

    // find the entry with that AD value
    auto it = std::find_if(
        callouts.begin(), callouts.end(), [adValue](const nlohmann::json& j) {
            return *adValue == j["ADValue"].get<std::string>();
        });

    if (it == callouts.end())
    {
        // This can happen if not all possible values were in the
        // message registry and that's fine.  There may be a
        // "CalloutsWhenNoADMatch" section that contains callouts
        // to use in this case.
        if (json.contains("CalloutsWhenNoADMatch"))
        {
            return getCalloutsWithoutAD(json["CalloutsWhenNoADMatch"],
                                        systemNames);
        }
        return std::vector<RegistryCallout>{};
    }

    // Proceed to find the callouts possibly based on system type.
    return getCalloutsWithoutAD((*it)["Callouts"], systemNames);
}

/**
 * @brief Returns the journal capture information
 *
 *  The JSON looks like:
 *    "JournalCapture": {
 *        "NumLines": 30
 *    }
 *
 *    "JournalCapture":
 *    {
 *        "Sections": [
 *            {
 *                "SyslogID": "phosphor-log-manager",
 *                "NumLines": 20
 *            }
 *        ]
 *    }
 *
 * @param json - The journal capture JSON
 * @return JournalCapture - The filled in variant
 */
JournalCapture getJournalCapture(const nlohmann::json& json)
{
    JournalCapture capt;

    // Primary key is either NumLines or Sections.
    if (json.contains("NumLines"))
    {
        capt = json.at("NumLines").get<size_t>();
    }
    else if (json.contains("Sections"))
    {
        AppCaptureList captures;
        for (const auto& capture : json.at("Sections"))
        {
            AppCapture ac;
            ac.syslogID = capture.at("SyslogID").get<std::string>();
            ac.numLines = capture.at("NumLines").get<size_t>();
            captures.push_back(std::move(ac));
        }

        capt = captures;
    }
    else
    {
        lg2::error("JournalCapture section not the right format");
        throw std::runtime_error{"JournalCapture section not the right format"};
    }

    return capt;
}

} // namespace helper

std::optional<Entry> Registry::lookup(const std::string& name, LookupType type,
                                      bool toCache)
{
    std::optional<nlohmann::json> registryTmp;
    auto& registryOpt = (_registry) ? _registry : registryTmp;
    if (!registryOpt)
    {
        registryOpt = readRegistry(_registryFile);
        if (!registryOpt)
        {
            return std::nullopt;
        }
        else if (toCache)
        {
            // Save message registry in memory for peltool
            _registry = std::move(registryTmp);
        }
    }
    auto& reg = (_registry) ? _registry : registryTmp;
    const auto& registry = reg.value();
    // Find an entry with this name in the PEL array.
    auto e = std::find_if(
        registry["PELs"].begin(), registry["PELs"].end(),
        [&name, &type](const nlohmann::json& j) {
            return ((name == j.at("Name").get<std::string>() &&
                     type == LookupType::name) ||
                    (name == j.at("SRC").at("ReasonCode").get<std::string>() &&
                     type == LookupType::reasonCode));
        });

    if (e != registry["PELs"].end())
    {
        // Fill in the Entry structure from the JSON.  Most, but not all, fields
        // are optional.

        try
        {
            Entry entry;
            entry.name = (*e)["Name"];

            if (e->contains("Subsystem"))
            {
                entry.subsystem = helper::getSubsystem((*e)["Subsystem"]);
            }

            if (e->contains("ActionFlags"))
            {
                entry.actionFlags = helper::getActionFlags((*e)["ActionFlags"]);
            }

            if (e->contains("MfgActionFlags"))
            {
                entry.mfgActionFlags =
                    helper::getActionFlags((*e)["MfgActionFlags"]);
            }

            if (e->contains("Severity"))
            {
                entry.severity = helper::getSeverities((*e)["Severity"]);
            }

            if (e->contains("MfgSeverity"))
            {
                entry.mfgSeverity = helper::getSeverities((*e)["MfgSeverity"]);
            }

            if (e->contains("EventType"))
            {
                entry.eventType = helper::getEventType((*e)["EventType"]);
            }

            if (e->contains("EventScope"))
            {
                entry.eventScope = helper::getEventScope((*e)["EventScope"]);
            }

            auto& src = (*e)["SRC"];
            entry.src.reasonCode = helper::getSRCReasonCode(src, name);

            if (src.contains("Type"))
            {
                entry.src.type = helper::getSRCType(src, name);
            }
            else
            {
                entry.src.type = static_cast<uint8_t>(SRCType::bmcError);
            }

            // Now that we know the SRC type and reason code,
            // we can get the component ID.
            entry.componentID = helper::getComponentID(
                entry.src.type, entry.src.reasonCode, *e, name);

            if (src.contains("Words6To9"))
            {
                entry.src.hexwordADFields =
                    helper::getSRCHexwordFields(src, name);
            }

            if (src.contains("SymptomIDFields"))
            {
                entry.src.symptomID = helper::getSRCSymptomIDFields(src, name);
            }

            if (src.contains("DeconfigFlag"))
            {
                entry.src.deconfigFlag = helper::getSRCDeconfigFlag(src);
            }

            if (src.contains("CheckstopFlag"))
            {
                entry.src.checkstopFlag = helper::getSRCCheckstopFlag(src);
            }

            auto& doc = (*e)["Documentation"];
            entry.doc.message = doc["Message"];
            entry.doc.description = doc["Description"];
            if (doc.contains("MessageArgSources"))
            {
                entry.doc.messageArgSources = doc["MessageArgSources"];
            }

            // If there are callouts defined, save the JSON for later
            if (_loadCallouts)
            {
                if (e->contains("Callouts"))
                {
                    entry.callouts = (*e)["Callouts"];
                }
                else if (e->contains("CalloutsUsingAD"))
                {
                    entry.callouts = (*e)["CalloutsUsingAD"];
                }
            }

            if (e->contains("JournalCapture"))
            {
                entry.journalCapture =
                    helper::getJournalCapture((*e)["JournalCapture"]);
            }

            return entry;
        }
        catch (const std::exception& ex)
        {
            lg2::error("Found invalid message registry field. Error: {ERROR}",
                       "ERROR", ex);
        }
    }

    return std::nullopt;
}

std::optional<nlohmann::json>
    Registry::readRegistry(const std::filesystem::path& registryFile)
{
    // Look in /etc first in case someone put a test file there
    fs::path debugFile{fs::path{debugFilePath} / registryFileName};
    nlohmann::json registry;
    std::ifstream file;

    if (fs::exists(debugFile))
    {
        lg2::info("Using debug PEL message registry");
        file.open(debugFile);
    }
    else
    {
        file.open(registryFile);
    }

    try
    {
        registry = nlohmann::json::parse(file);
    }
    catch (const std::exception& e)
    {
        lg2::error("Error parsing message registry JSON. Error: {ERROR}",
                   "ERROR", e);
        return std::nullopt;
    }
    return registry;
}

std::vector<RegistryCallout>
    Registry::getCallouts(const nlohmann::json& calloutJSON,
                          const std::vector<std::string>& systemNames,
                          const AdditionalData& additionalData)
{
    // The JSON may either use an AdditionalData key
    // as an index, or not.
    if (helper::calloutUsesAdditionalData(calloutJSON))
    {
        return helper::getCalloutsUsingAD(calloutJSON, systemNames,
                                          additionalData);
    }

    return helper::getCalloutsWithoutAD(calloutJSON, systemNames);
}

} // namespace message
} // namespace pels
} // namespace openpower
