#include "parser.hpp"

#include "constants.hpp"
#include "event_logger.hpp"

#include <utility/dbus_utility.hpp>
#include <utility/json_utility.hpp>
#include <utility/vpd_specific_utility.hpp>

#include <fstream>

namespace vpd
{
Parser::Parser(const std::string& vpdFilePath, nlohmann::json parsedJson) :
    m_vpdFilePath(vpdFilePath), m_parsedJson(parsedJson)
{
    std::error_code l_errCode;

    // ToDo: Add minimum file size check in all the concert praser classes,
    // depends on their VPD type.
    if (!std::filesystem::exists(m_vpdFilePath, l_errCode))
    {
        std::string l_message{"Parser object creation failed, file [" +
                              m_vpdFilePath + "] doesn't exists."};

        if (l_errCode)
        {
            l_message += " Error message: " + l_errCode.message();
        }

        throw std::runtime_error(l_message);
    }

    // Read VPD offset if applicable.
    if (!m_parsedJson.empty())
    {
        m_vpdStartOffset = jsonUtility::getVPDOffset(m_parsedJson, vpdFilePath);
    }
}

std::shared_ptr<vpd::ParserInterface> Parser::getVpdParserInstance()
{
    // Read the VPD data into a vector.
    vpdSpecificUtility::getVpdDataInVector(m_vpdFilePath, m_vpdVector,
                                           m_vpdStartOffset);

    // This will detect the type of parser required.
    std::shared_ptr<vpd::ParserInterface> l_parser =
        ParserFactory::getParser(m_vpdVector, m_vpdFilePath, m_vpdStartOffset);

    return l_parser;
}

types::VPDMapVariant Parser::parse()
{
    std::shared_ptr<vpd::ParserInterface> l_parser = getVpdParserInstance();
    return l_parser->parse();
}

int Parser::updateVpdKeyword(const types::WriteVpdParams& i_paramsToWriteData)
{
    int l_bytesUpdatedOnHardware = constants::FAILURE;

    // A lambda to extract Record : Keyword string from i_paramsToWriteData
    auto l_keyWordIdentifier =
        [](const types::WriteVpdParams& i_paramsToWriteData) -> std::string {
        std::string l_keywordString{};
        if (const types::IpzData* l_ipzData =
                std::get_if<types::IpzData>(&i_paramsToWriteData))
        {
            l_keywordString =
                std::get<0>(*l_ipzData) + ":" + std::get<1>(*l_ipzData);
        }
        else if (const types::KwData* l_kwData =
                     std::get_if<types::KwData>(&i_paramsToWriteData))
        {
            l_keywordString = std::get<0>(*l_kwData);
        }
        return l_keywordString;
    };

    try
    {
        // Enable Reboot Guard
        if (constants::FAILURE == dbusUtility::EnableRebootGuard())
        {
            EventLogger::createAsyncPel(
                types::ErrorType::DbusFailure,
                types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
                std::string(
                    "Failed to enable BMC Reboot Guard while updating " +
                    l_keyWordIdentifier(i_paramsToWriteData)),
                std::nullopt, std::nullopt, std::nullopt, std::nullopt);

            return constants::FAILURE;
        }

        // Update keyword's value on hardware
        try
        {
            std::shared_ptr<ParserInterface> l_vpdParserInstance =
                getVpdParserInstance();
            l_bytesUpdatedOnHardware =
                l_vpdParserInstance->writeKeywordOnHardware(
                    i_paramsToWriteData);
        }
        catch (const std::exception& l_exception)
        {
            std::string l_errMsg(
                "Error while updating keyword's value on hardware path " +
                m_vpdFilePath + ", error: " + std::string(l_exception.what()));

            // TODO : Log PEL

            throw std::runtime_error(l_errMsg);
        }

        auto [l_fruPath, l_inventoryObjPath, l_redundantFruPath] =
            jsonUtility::getAllPathsToUpdateKeyword(m_parsedJson,
                                                    m_vpdFilePath);

        // If inventory D-bus object path is present, update keyword's value on
        // DBus
        if (!l_inventoryObjPath.empty())
        {
            types::Record l_recordName;
            std::string l_interfaceName;
            std::string l_propertyName;
            types::DbusVariantType l_keywordValue;

            if (const types::IpzData* l_ipzData =
                    std::get_if<types::IpzData>(&i_paramsToWriteData))
            {
                l_recordName = std::get<0>(*l_ipzData);
                l_interfaceName = constants::ipzVpdInf + l_recordName;
                l_propertyName = std::get<1>(*l_ipzData);

                try
                {
                    // Read keyword's value from hardware to write the same on
                    // D-bus.
                    std::shared_ptr<ParserInterface> l_vpdParserInstance =
                        getVpdParserInstance();

                    logging::logMessage(
                        "Performing VPD read on " + m_vpdFilePath);

                    l_keywordValue =
                        l_vpdParserInstance->readKeywordFromHardware(
                            types::ReadVpdParams(
                                std::make_tuple(l_recordName, l_propertyName)));
                }
                catch (const std::exception& l_exception)
                {
                    // Unable to read keyword's value from hardware.
                    std::string l_errMsg(
                        "Error while reading keyword's value from hadware path " +
                        m_vpdFilePath +
                        ", error: " + std::string(l_exception.what()));

                    // TODO: Log PEL

                    throw std::runtime_error(l_errMsg);
                }
            }
            else
            {
                // Input parameter type provided isn't compatible to perform
                // update.
                std::string l_errMsg(
                    "Input parameter type isn't compatible to update keyword's value on DBus for object path: " +
                    l_inventoryObjPath);
                throw std::runtime_error(l_errMsg);
            }

            // Get D-bus name for the given keyword
            l_propertyName =
                vpdSpecificUtility::getDbusPropNameForGivenKw(l_propertyName);

            // Create D-bus object map
            types::ObjectMap l_dbusObjMap = {std::make_pair(
                l_inventoryObjPath,
                types::InterfaceMap{std::make_pair(
                    l_interfaceName, types::PropertyMap{std::make_pair(
                                         l_propertyName, l_keywordValue)})})};

            // Call PIM's Notify method to perform update
            if (!dbusUtility::callPIM(std::move(l_dbusObjMap)))
            {
                // Call to PIM's Notify method failed.
                std::string l_errMsg("Notify PIM is failed for object path: " +
                                     l_inventoryObjPath);
                throw std::runtime_error(l_errMsg);
            }
        }

        // Update keyword's value on redundant hardware if present
        if (!l_redundantFruPath.empty())
        {
            if (updateVpdKeywordOnRedundantPath(l_redundantFruPath,
                                                i_paramsToWriteData) < 0)
            {
                std::string l_errMsg(
                    "Error while updating keyword's value on redundant path " +
                    l_redundantFruPath);
                throw std::runtime_error(l_errMsg);
            }
        }

        // TODO: Check if revert is required when any of the writes fails.
        // TODO: Handle error logging
    }
    catch (const std::exception& l_ex)
    {
        logging::logMessage("Update VPD Keyword failed for : " +
                            l_keyWordIdentifier(i_paramsToWriteData) +
                            " failed due to error: " + l_ex.what());

        // update failed, set return value to failure
        l_bytesUpdatedOnHardware = constants::FAILURE;
    }

    // Disable Reboot Guard
    if (constants::FAILURE == dbusUtility::DisableRebootGuard())
    {
        EventLogger::createAsyncPel(
            types::ErrorType::DbusFailure, types::SeverityType::Critical,
            __FILE__, __FUNCTION__, 0,
            std::string("Failed to disable BMC Reboot Guard while updating " +
                        l_keyWordIdentifier(i_paramsToWriteData)),
            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
    }

    return l_bytesUpdatedOnHardware;
}

int Parser::updateVpdKeywordOnRedundantPath(
    const std::string& i_fruPath,
    const types::WriteVpdParams& i_paramsToWriteData)
{
    try
    {
        std::shared_ptr<Parser> l_parserObj =
            std::make_shared<Parser>(i_fruPath, m_parsedJson);

        std::shared_ptr<ParserInterface> l_vpdParserInstance =
            l_parserObj->getVpdParserInstance();

        return l_vpdParserInstance->writeKeywordOnHardware(i_paramsToWriteData);
    }
    catch (const std::exception& l_exception)
    {
        EventLogger::createSyncPel(
            types::ErrorType::InvalidVpdMessage,
            types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
            "Error while updating keyword's value on redundant path " +
                i_fruPath + ", error: " + std::string(l_exception.what()),
            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
        return -1;
    }
}

int Parser::updateVpdKeywordOnHardware(
    const types::WriteVpdParams& i_paramsToWriteData)
{
    int l_bytesUpdatedOnHardware = constants::FAILURE;

    // A lambda to extract Record : Keyword string from i_paramsToWriteData
    auto l_keyWordIdentifier =
        [](const types::WriteVpdParams& i_paramsToWriteData) -> std::string {
        std::string l_keywordString{};
        if (const types::IpzData* l_ipzData =
                std::get_if<types::IpzData>(&i_paramsToWriteData))
        {
            l_keywordString =
                std::get<0>(*l_ipzData) + ":" + std::get<1>(*l_ipzData);
        }
        else if (const types::KwData* l_kwData =
                     std::get_if<types::KwData>(&i_paramsToWriteData))
        {
            l_keywordString = std::get<0>(*l_kwData);
        }
        return l_keywordString;
    };

    try
    {
        // Enable Reboot Guard
        if (constants::FAILURE == dbusUtility::EnableRebootGuard())
        {
            EventLogger::createAsyncPel(
                types::ErrorType::DbusFailure,
                types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
                std::string(
                    "Failed to enable BMC Reboot Guard while updating " +
                    l_keyWordIdentifier(i_paramsToWriteData)),
                std::nullopt, std::nullopt, std::nullopt, std::nullopt);

            return constants::FAILURE;
        }

        std::shared_ptr<ParserInterface> l_vpdParserInstance =
            getVpdParserInstance();
        l_bytesUpdatedOnHardware =
            l_vpdParserInstance->writeKeywordOnHardware(i_paramsToWriteData);
    }
    catch (const std::exception& l_exception)
    {
        types::ErrorType l_errorType;

        if (typeid(l_exception) == typeid(EccException))
        {
            l_errorType = types::ErrorType::EccCheckFailed;
        }
        else
        {
            l_errorType = types::ErrorType::InvalidVpdMessage;
        }

        EventLogger::createAsyncPel(
            l_errorType, types::SeverityType::Informational, __FILE__,
            __FUNCTION__, 0,
            "Error while updating keyword's value on hardware path [" +
                m_vpdFilePath + "], error: " + std::string(l_exception.what()),
            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
    }

    // Disable Reboot Guard
    if (constants::FAILURE == dbusUtility::DisableRebootGuard())
    {
        EventLogger::createAsyncPel(
            types::ErrorType::DbusFailure, types::SeverityType::Critical,
            __FILE__, __FUNCTION__, 0,
            std::string("Failed to disable BMC Reboot Guard while updating " +
                        l_keyWordIdentifier(i_paramsToWriteData)),
            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
    }

    return l_bytesUpdatedOnHardware;
}

} // namespace vpd
