#include "config.h"

#include "editor_impl.hpp"

#include "vpdecc/vpdecc.h"

#include "common_utility.hpp"
#include "ibm_vpd_utils.hpp"
#include "ipz_parser.hpp"
#include "parser_factory.hpp"
#include "vpd_exceptions.hpp"

#include <phosphor-logging/elog-errors.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

using namespace openpower::vpd::parser::interface;
using namespace openpower::vpd::constants;
using namespace openpower::vpd::parser::factory;
using namespace openpower::vpd::ipz::parser;

namespace openpower
{
namespace vpd
{
namespace manager
{
namespace editor
{

void EditorImpl::checkPTForRecord(Binary::const_iterator& iterator,
                                  Byte ptLength)
{
    // auto iterator = ptRecord.cbegin();
    auto end = std::next(iterator, ptLength + 1);

    // Look at each entry in the PT keyword for the record name
    while (iterator < end)
    {
        auto stop = std::next(iterator, lengths::RECORD_NAME);
        std::string record(iterator, stop);

        if (record == thisRecord.recName)
        {
            // Skip record name and record type
            std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));

            // Get record offset
            thisRecord.recOffset = readUInt16LE(iterator);

            // pass the record offset length to read record length
            std::advance(iterator, lengths::RECORD_OFFSET);
            thisRecord.recSize = readUInt16LE(iterator);

            std::advance(iterator, lengths::RECORD_LENGTH);
            thisRecord.recECCoffset = readUInt16LE(iterator);

            ECCLength len;
            std::advance(iterator, lengths::RECORD_ECC_OFFSET);
            len = readUInt16LE(iterator);
            thisRecord.recECCLength = len;

            // once we find the record we don't need to look further
            return;
        }
        else
        {
            // Jump the record
            std::advance(iterator,
                         lengths::RECORD_NAME + sizeof(RecordType) +
                             sizeof(RecordOffset) + sizeof(RecordLength) +
                             sizeof(ECCOffset) + sizeof(ECCLength));
        }
    }
    // imples the record was not found
    throw std::runtime_error("Record not found");
}

void EditorImpl::updateData(const Binary& kwdData)
{
    std::size_t lengthToUpdate = kwdData.size() <= thisRecord.kwdDataLength
                                     ? kwdData.size()
                                     : thisRecord.kwdDataLength;

    auto iteratorToNewdata = kwdData.cbegin();
    auto end = iteratorToNewdata;
    std::advance(end, lengthToUpdate);

    // update data in file buffer as it will be needed to update ECC
    // avoiding extra stream operation here
    auto iteratorToKWdData = vpdFile.begin();
    std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
    std::copy(iteratorToNewdata, end, iteratorToKWdData);

#ifdef ManagerTest
    auto startItr = vpdFile.begin();
    std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
    auto endItr = startItr;
    std::advance(endItr, thisRecord.kwdDataLength);

    Binary updatedData(startItr, endItr);
    if (updatedData == kwdData)
    {
        throw std::runtime_error("Data updated successfully");
    }
#else

    // update data in EEPROM as well. As we will not write complete file back
    vpdFileStream.seekp(startOffset + thisRecord.kwDataOffset, std::ios::beg);

    iteratorToNewdata = kwdData.cbegin();
    std::copy(iteratorToNewdata, end,
              std::ostreambuf_iterator<char>(vpdFileStream));

    // get a hold to new data in case encoding is needed
    thisRecord.kwdUpdatedData.resize(thisRecord.kwdDataLength);
    auto itrToKWdData = vpdFile.cbegin();
    std::advance(itrToKWdData, thisRecord.kwDataOffset);
    auto kwdDataEnd = itrToKWdData;
    std::advance(kwdDataEnd, thisRecord.kwdDataLength);
    std::copy(itrToKWdData, kwdDataEnd, thisRecord.kwdUpdatedData.begin());
#endif
}

void EditorImpl::checkRecordForKwd()
{
    RecordOffset recOffset = thisRecord.recOffset;

    // Amount to skip for record ID, size, and the RT keyword
    constexpr auto skipBeg = sizeof(RecordId) + sizeof(RecordSize) +
                             lengths::KW_NAME + sizeof(KwSize);

    auto iterator = vpdFile.cbegin();
    std::advance(iterator, recOffset + skipBeg + lengths::RECORD_NAME);

    auto end = iterator;
    std::advance(end, thisRecord.recSize);
    std::size_t dataLength = 0;

    while (iterator < end)
    {
        // Note keyword name
        std::string kw(iterator, iterator + lengths::KW_NAME);

        // Check if the Keyword starts with '#'
        char kwNameStart = *iterator;
        std::advance(iterator, lengths::KW_NAME);

        // if keyword starts with #
        if (POUND_KW == kwNameStart)
        {
            // Note existing keyword data length
            dataLength = readUInt16LE(iterator);

            // Jump past 2Byte keyword length + data
            std::advance(iterator, sizeof(PoundKwSize));
        }
        else
        {
            // Note existing keyword data length
            dataLength = *iterator;

            // Jump past keyword length and data
            std::advance(iterator, sizeof(KwSize));
        }

        if (thisRecord.recKWd == kw)
        {
            thisRecord.kwDataOffset = std::distance(vpdFile.cbegin(), iterator);
            thisRecord.kwdDataLength = dataLength;
            return;
        }

        // jump the data of current kwd to point to next kwd name
        std::advance(iterator, dataLength);
    }

    throw std::runtime_error("Keyword not found");
}

void EditorImpl::updateRecordECC()
{
    auto itrToRecordData = vpdFile.cbegin();
    std::advance(itrToRecordData, thisRecord.recOffset);

    auto itrToRecordECC = vpdFile.cbegin();
    std::advance(itrToRecordECC, thisRecord.recECCoffset);

    auto l_status = vpdecc_create_ecc(
        const_cast<uint8_t*>(&itrToRecordData[0]), thisRecord.recSize,
        const_cast<uint8_t*>(&itrToRecordECC[0]), &thisRecord.recECCLength);
    if (l_status != VPD_ECC_OK)
    {
        throw std::runtime_error("Ecc update failed");
    }

    auto end = itrToRecordECC;
    std::advance(end, thisRecord.recECCLength);

#ifndef ManagerTest
    vpdFileStream.seekp(startOffset + thisRecord.recECCoffset, std::ios::beg);
    std::copy(itrToRecordECC, end,
              std::ostreambuf_iterator<char>(vpdFileStream));
#endif
}

auto EditorImpl::getValue(offsets::Offsets offset)
{
    auto itr = vpdFile.cbegin();
    std::advance(itr, offset);
    LE2ByteData lowByte = *itr;
    LE2ByteData highByte = *(itr + 1);
    lowByte |= (highByte << 8);

    return lowByte;
}

void EditorImpl::checkRecordData()
{
    auto itrToRecordData = vpdFile.cbegin();
    std::advance(itrToRecordData, thisRecord.recOffset);

    auto itrToRecordECC = vpdFile.cbegin();
    std::advance(itrToRecordECC, thisRecord.recECCoffset);

    checkECC(itrToRecordData, itrToRecordECC, thisRecord.recSize,
             thisRecord.recECCLength);
}

void EditorImpl::checkECC(Binary::const_iterator& itrToRecData,
                          Binary::const_iterator& itrToECCData,
                          RecordLength recLength, ECCLength eccLength)
{
    auto l_status =
        vpdecc_check_data(const_cast<uint8_t*>(&itrToRecData[0]), recLength,
                          const_cast<uint8_t*>(&itrToECCData[0]), eccLength);

    if (l_status == VPD_ECC_CORRECTABLE_DATA)
    {
        try
        {
            if (vpdFileStream.is_open())
            {
                vpdFileStream.seekp(startOffset + thisRecord.recOffset,
                                    std::ios::beg);
                auto end = itrToRecData;
                std::advance(end, recLength);
                std::copy(itrToRecData, end,
                          std::ostreambuf_iterator<char>(vpdFileStream));
            }
            else
            {
                throw std::runtime_error("Ecc correction failed");
            }
        }
        catch (const std::fstream::failure& e)
        {
            std::cout << "Error while operating on file with exception";
            throw std::runtime_error("Ecc correction failed");
        }
    }
    else if (l_status != VPD_ECC_OK)
    {
        throw std::runtime_error("Ecc check failed");
    }
}

void EditorImpl::readVTOC()
{
    // read VTOC offset
    RecordOffset tocOffset = getValue(offsets::VTOC_PTR);

    // read VTOC record length
    RecordLength tocLength = getValue(offsets::VTOC_REC_LEN);

    // read TOC ecc offset
    ECCOffset tocECCOffset = getValue(offsets::VTOC_ECC_OFF);

    // read TOC ecc length
    ECCLength tocECCLength = getValue(offsets::VTOC_ECC_LEN);

    auto itrToRecord = vpdFile.cbegin();
    std::advance(itrToRecord, tocOffset);

    auto iteratorToECC = vpdFile.cbegin();
    std::advance(iteratorToECC, tocECCOffset);

    // validate ecc for the record
    checkECC(itrToRecord, iteratorToECC, tocLength, tocECCLength);

    // to get to the record name.
    std::advance(itrToRecord, sizeof(RecordId) + sizeof(RecordSize) +
                                  // Skip past the RT keyword, which contains
                                  // the record name.
                                  lengths::KW_NAME + sizeof(KwSize));

    std::string recordName(itrToRecord, itrToRecord + lengths::RECORD_NAME);

    if ("VTOC" != recordName)
    {
        throw std::runtime_error("VTOC record not found");
    }

    // jump to length of PT kwd
    std::advance(itrToRecord, lengths::RECORD_NAME + lengths::KW_NAME);

    // Note size of PT
    Byte ptLen = *itrToRecord;
    std::advance(itrToRecord, 1);

    checkPTForRecord(itrToRecord, ptLen);
}

template <typename T>
void EditorImpl::makeDbusCall(
    const std::string& object, const std::string& interface,
    const std::string& property, const std::variant<T>& data)
{
    auto bus = sdbusplus::bus::new_default();
    auto properties =
        bus.new_method_call(INVENTORY_MANAGER_SERVICE, object.c_str(),
                            "org.freedesktop.DBus.Properties", "Set");
    properties.append(interface);
    properties.append(property);
    properties.append(data);

    auto result = bus.call(properties);

    if (result.is_method_error())
    {
        throw std::runtime_error("bus call failed");
    }
}

void EditorImpl::processAndUpdateCI(const std::string& objectPath)
{
    inventory::ObjectMap objects;
    for (auto& commonInterface : jsonFile["commonInterfaces"].items())
    {
        for (auto& ciPropertyList : commonInterface.value().items())
        {
            if (ciPropertyList.value().type() ==
                nlohmann::json::value_t::object)
            {
                if ((ciPropertyList.value().value("recordName", "") ==
                     thisRecord.recName) &&
                    (ciPropertyList.value().value("keywordName", "") ==
                     thisRecord.recKWd))
                {
                    inventory::PropertyMap prop;
                    inventory::InterfaceMap interfaces;
                    std::string kwdData(thisRecord.kwdUpdatedData.begin(),
                                        thisRecord.kwdUpdatedData.end());

                    prop.emplace(ciPropertyList.key(), std::move(kwdData));
                    interfaces.emplace(commonInterface.key(), std::move(prop));
                    objects.emplace(objectPath, std::move(interfaces));
                }
            }
        }
    }
    // Notify PIM
    common::utility::callPIM(std::move(objects));
}

void EditorImpl::processAndUpdateEI(const nlohmann::json& Inventory,
                                    const inventory::Path& objPath)
{
    inventory::ObjectMap objects;
    for (const auto& extraInterface : Inventory["extraInterfaces"].items())
    {
        if (extraInterface.value() != NULL)
        {
            for (const auto& eiPropertyList : extraInterface.value().items())
            {
                if (eiPropertyList.value().type() ==
                    nlohmann::json::value_t::object)
                {
                    if ((eiPropertyList.value().value("recordName", "") ==
                         thisRecord.recName) &&
                        ((eiPropertyList.value().value("keywordName", "") ==
                          thisRecord.recKWd)))
                    {
                        inventory::PropertyMap prop;
                        inventory::InterfaceMap interfaces;
                        std::string kwdData(thisRecord.kwdUpdatedData.begin(),
                                            thisRecord.kwdUpdatedData.end());
                        encodeKeyword(kwdData, eiPropertyList.value().value(
                                                   "encoding", ""));

                        prop.emplace(eiPropertyList.key(), std::move(kwdData));
                        interfaces.emplace(extraInterface.key(),
                                           std::move(prop));
                        objects.emplace(objPath, std::move(interfaces));
                    }
                }
            }
        }
    }
    // Notify PIM
    common::utility::callPIM(std::move(objects));
}

void EditorImpl::updateCache()
{
    const std::vector<nlohmann::json>& groupEEPROM =
        jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();

    inventory::ObjectMap objects;
    // iterate through all the inventories for this file path
    for (const auto& singleInventory : groupEEPROM)
    {
        inventory::PropertyMap prop;
        inventory::InterfaceMap interfaces;
        // by default inherit property is true
        bool isInherit = true;

        if (singleInventory.find("inherit") != singleInventory.end())
        {
            isInherit = singleInventory["inherit"].get<bool>();
        }

        if (isInherit)
        {
            prop.emplace(getDbusNameForThisKw(thisRecord.recKWd),
                         thisRecord.kwdUpdatedData);
            interfaces.emplace(
                (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
                std::move(prop));
            objects.emplace(
                (singleInventory["inventoryPath"].get<std::string>()),
                std::move(interfaces));

            // process Common interface
            processAndUpdateCI(singleInventory["inventoryPath"]
                                   .get_ref<const nlohmann::json::string_t&>());
        }

        // process extra interfaces
        processAndUpdateEI(singleInventory,
                           singleInventory["inventoryPath"]
                               .get_ref<const nlohmann::json::string_t&>());

        // check if we need to copy some specific records in this case.
        if (singleInventory.find("copyRecords") != singleInventory.end())
        {
            if (find(singleInventory["copyRecords"].begin(),
                     singleInventory["copyRecords"].end(),
                     thisRecord.recName) !=
                singleInventory["copyRecords"].end())
            {
                prop.emplace(thisRecord.recKWd, thisRecord.kwdUpdatedData);
                interfaces.emplace(
                    (IPZ_INTERFACE + std::string{"."} + thisRecord.recName),
                    std::move(prop));
                objects.emplace(
                    (singleInventory["inventoryPath"].get<std::string>()),
                    std::move(interfaces));
            }
        }
    }
    // Notify PIM
    common::utility::callPIM(std::move(objects));
}

void EditorImpl::expandLocationCode(const std::string& locationCodeType)
{
    std::string propertyFCorTM{};
    std::string propertySE{};

    if (locationCodeType == "fcs")
    {
        propertyFCorTM =
            readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
        propertySE =
            readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "SE");
    }
    else if (locationCodeType == "mts")
    {
        propertyFCorTM =
            readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
        propertySE =
            readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "SE");
    }

    const nlohmann::json& groupFRUS =
        jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
    inventory::ObjectMap objects;

    for (const auto& itemFRUS : groupFRUS.items())
    {
        const std::vector<nlohmann::json>& groupEEPROM =
            itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
        for (const auto& itemEEPROM : groupEEPROM)
        {
            inventory::PropertyMap prop;
            inventory::InterfaceMap interfaces;
            const auto& objectPath = itemEEPROM["inventoryPath"];
            sdbusplus::message::object_path object(objectPath);

            // check if the given item implements location code interface
            if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
                itemEEPROM["extraInterfaces"].end())
            {
                const std::string& unexpandedLocationCode =
                    itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
                              ["LocationCode"]
                                  .get_ref<const nlohmann::json::string_t&>();
                std::size_t idx = unexpandedLocationCode.find(locationCodeType);
                if (idx != std::string::npos)
                {
                    std::string expandedLocationCode(unexpandedLocationCode);

                    if (locationCodeType == "fcs")
                    {
                        expandedLocationCode.replace(
                            idx, 3,
                            propertyFCorTM.substr(0, 4) + ".ND0." + propertySE);
                    }
                    else if (locationCodeType == "mts")
                    {
                        std::replace(propertyFCorTM.begin(),
                                     propertyFCorTM.end(), '-', '.');
                        expandedLocationCode.replace(
                            idx, 3, propertyFCorTM + "." + propertySE);
                    }

                    // update the DBUS interface COM as well as XYZ path
                    prop.emplace("LocationCode", expandedLocationCode);
                    // TODO deprecate this com.ibm interface later
                    interfaces.emplace(IBM_LOCATION_CODE_INF, prop);
                    interfaces.emplace(XYZ_LOCATION_CODE_INF, std::move(prop));
                }
            }
            objects.emplace(std::move(object), std::move(interfaces));
        }
    }
    // Notify PIM
    common::utility::callPIM(std::move(objects));
}

#ifndef ManagerTest
static void enableRebootGuard()
{
    try
    {
        auto bus = sdbusplus::bus::new_default();
        auto method = bus.new_method_call(
            "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
            "org.freedesktop.systemd1.Manager", "StartUnit");
        method.append("reboot-guard-enable.service", "replace");
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception_t& e)
    {
        std::string errMsg =
            "Bus call to enable BMC reboot failed for reason: ";
        errMsg += e.what();

        throw std::runtime_error(errMsg);
    }
}

static void disableRebootGuard()
{
    try
    {
        auto bus = sdbusplus::bus::new_default();
        auto method = bus.new_method_call(
            "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
            "org.freedesktop.systemd1.Manager", "StartUnit");
        method.append("reboot-guard-disable.service", "replace");
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception_t& e)
    {
        using namespace phosphor::logging;
        using InternalFailure =
            sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;

        std::string errMsg =
            "Bus call to disable BMC reboot failed for reason: ";
        errMsg += e.what();

        log<level::ERR>("Disable boot guard failed");
        elog<InternalFailure>();

        throw std::runtime_error(errMsg);
    }
}
#endif

void EditorImpl::updateKeyword(const Binary& kwdData, uint32_t offset,
                               const bool& updCache)
{
    try
    {
        startOffset = offset;
#ifndef ManagerTest
        // Restrict BMC from rebooting when VPD is being written. This will
        // prevent any data/ECC corruption in case BMC reboots while VPD update.
        enableRebootGuard();

        Binary completeVPDFile;
        vpdFileStream.exceptions(
            std::ifstream::badbit | std::ifstream::failbit);
        try
        {
            vpdFileStream.open(vpdFilePath,
                               std::ios::in | std::ios::out | std::ios::binary);

            auto vpdFileSize =
                std::min(std::filesystem::file_size(vpdFilePath), MAX_VPD_SIZE);
            if (vpdFileSize == 0)
            {
                std::cerr << "File size is 0 for " << vpdFilePath << std::endl;
                throw std::runtime_error("File size is 0.");
            }

            completeVPDFile.resize(vpdFileSize);
            vpdFileStream.seekg(startOffset, std::ios_base::cur);
            vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]),
                               vpdFileSize);
            vpdFileStream.clear(std::ios_base::eofbit);
        }
        catch (const std::system_error& fail)
        {
            std::cerr << "Exception in file handling [" << vpdFilePath
                      << "] error : " << fail.what();
            std::cerr << "Stream file size = " << vpdFileStream.gcount()
                      << std::endl;
            throw;
        }
        vpdFile = completeVPDFile;

        if (objPath.empty() &&
            jsonFile["frus"].find(vpdFilePath) != jsonFile["frus"].end())
        {
            objPath = jsonFile["frus"][vpdFilePath][0]["inventoryPath"]
                          .get_ref<const nlohmann::json::string_t&>();
        }

#else

        Binary completeVPDFile = vpdFile;

#endif
        if (vpdFile.empty())
        {
            throw std::runtime_error("Invalid File");
        }
        auto iterator = vpdFile.cbegin();
        std::advance(iterator, IPZ_DATA_START);

        Byte vpdType = *iterator;
        if (vpdType == KW_VAL_PAIR_START_TAG)
        {
            // objPath should be empty only in case of test run.
            ParserInterface* Iparser = ParserFactory::getParser(
                completeVPDFile, objPath, vpdFilePath, startOffset);
            IpzVpdParser* ipzParser = dynamic_cast<IpzVpdParser*>(Iparser);

            try
            {
                if (ipzParser == nullptr)
                {
                    throw std::runtime_error("Invalid cast");
                }

                ipzParser->processHeader();
                delete ipzParser;
                ipzParser = nullptr;
                // ParserFactory::freeParser(Iparser);

                // process VTOC for PTT rkwd
                readVTOC();

                // check record for keywrod
                checkRecordForKwd();

                // Check Data before updating
                checkRecordData();

                // update the data to the file
                updateData(kwdData);

                // update the ECC data for the record once data has been updated
                updateRecordECC();

                if (updCache)
                {
#ifndef ManagerTest
                    // update the cache once data has been updated
                    updateCache();
#endif
                }
            }
            catch (const std::exception& e)
            {
                if (ipzParser != nullptr)
                {
                    delete ipzParser;
                }
                throw std::runtime_error(e.what());
            }

#ifndef ManagerTest
            // Once VPD data and Ecc update is done, disable BMC boot guard.
            disableRebootGuard();
#endif

            return;
        }
        else
        {
            throw openpower::vpd::exceptions::VpdDataException(
                "Could not find start tag in VPD " + vpdFilePath);
        }
    }
    catch (const std::exception& e)
    {
#ifndef ManagerTest
        // Disable reboot guard.
        disableRebootGuard();
#endif

        throw std::runtime_error(e.what());
    }
}
} // namespace editor
} // namespace manager
} // namespace vpd
} // namespace openpower
