#include "writefrudata.hpp"

#include "fru_area.hpp"
#include "frup.hpp"
#include "types.hpp"

#include <ipmid/api.h>
#include <unistd.h>

#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/bus.hpp>

#include <algorithm>
#include <array>
#include <cstdio>
#include <cstring>
#include <exception>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <span>
#include <sstream>
#include <vector>

using namespace ipmi::vpd;

extern const FruMap frus;
extern const std::map<Path, InterfaceMap> extras;

using FruAreaVector = std::vector<std::unique_ptr<IPMIFruArea>>;

namespace
{

/**
 * Cleanup routine
 * Must always be called as last reference to fruFilePointer.
 *
 * @param[in] fruFilePointer - FRU file pointer to close
 * @param[in] fruAreaVec - vector of FRU areas
 * @return -1
 */
int cleanupError(FILE* fruFilePointer, FruAreaVector& fruAreaVec)
{
    if (fruFilePointer != nullptr)
    {
        std::fclose(fruFilePointer);
    }

    if (!(fruAreaVec.empty()))
    {
        fruAreaVec.clear();
    }

    return -1;
}

/**
 * Gets the value of the key from the FRU dictionary of the given section.
 * FRU dictionary is parsed FRU data for all the sections.
 *
 * @param[in] section - FRU section name
 * @param[in] key - key for section
 * @param[in] delimiter - delimiter for parsing custom fields
 * @param[in] fruData - the FRU data to search for the section
 * @return FRU value
 */
std::string getFRUValue(const std::string& section, const std::string& key,
                        const std::string& delimiter, IPMIFruInfo& fruData)
{
    auto minIndexValue = 0;
    auto maxIndexValue = 0;
    std::string fruValue = "";

    if (section == "Board")
    {
        minIndexValue = OPENBMC_VPD_KEY_BOARD_MFG_DATE;
        maxIndexValue = OPENBMC_VPD_KEY_BOARD_MAX;
    }
    else if (section == "Product")
    {
        minIndexValue = OPENBMC_VPD_KEY_PRODUCT_MFR;
        maxIndexValue = OPENBMC_VPD_KEY_PRODUCT_MAX;
    }
    else if (section == "Chassis")
    {
        minIndexValue = OPENBMC_VPD_KEY_CHASSIS_TYPE;
        maxIndexValue = OPENBMC_VPD_KEY_CHASSIS_MAX;
    }

    auto first = fruData.cbegin() + minIndexValue;
    auto last = first + (maxIndexValue - minIndexValue) + 1;

    auto itr = std::find_if(first, last, [&key](const auto& e) {
        return key == e.first;
    });

    if (itr != last)
    {
        fruValue = itr->second;
    }

    // if the key is custom property then the value could be in two formats.
    // 1) custom field 2 = "value".
    // 2) custom field 2 =  "key:value".
    // if delimiter length = 0 i.e custom field 2 = "value"

    constexpr auto customProp = "Custom Field";
    if (key.find(customProp) != std::string::npos)
    {
        if (delimiter.length() > 0)
        {
            size_t delimiterpos = fruValue.find(delimiter);
            if (delimiterpos != std::string::npos)
            {
                fruValue = fruValue.substr(delimiterpos + 1);
            }
        }
    }
    return fruValue;
}

/**
 * Get the inventory service from the mapper.
 *
 * @param[in] bus - sdbusplus handle to use for dbus call
 * @param[in] intf - interface
 * @param[in] path - the object path
 * @return the dbus service that owns the interface for that path
 */
auto getService(sdbusplus::bus_t& bus, const std::string& intf,
                const std::string& path)
{
    auto mapperCall =
        bus.new_method_call("xyz.openbmc_project.ObjectMapper",
                            "/xyz/openbmc_project/object_mapper",
                            "xyz.openbmc_project.ObjectMapper", "GetObject");

    mapperCall.append(path);
    mapperCall.append(std::vector<std::string>({intf}));
    std::map<std::string, std::vector<std::string>> mapperResponse;

    try
    {
        auto mapperResponseMsg = bus.call(mapperCall);
        mapperResponseMsg.read(mapperResponse);
    }
    catch (const sdbusplus::exception_t& ex)
    {
        lg2::error("Exception from sdbus call: {ERROR}", "ERROR", ex);
        throw;
    }

    if (mapperResponse.begin() == mapperResponse.end())
    {
        throw std::runtime_error("ERROR in reading the mapper response");
    }

    return mapperResponse.begin()->first;
}

/**
 * Takes FRU data, invokes Parser for each FRU record area and updates
 * inventory.
 *
 * @param[in] areaVector - vector of FRU areas
 * @param[in] bus - handle to sdbus for calling methods, etc
 * @return return non-zero of failure
 */
int updateInventory(FruAreaVector& areaVector, sdbusplus::bus_t& bus)
{
    // Generic error reporter
    int rc = 0;
    uint8_t fruid = 0;
    IPMIFruInfo fruData;

    // For each FRU area, extract the needed data , get it parsed and update
    // the Inventory.
    for (const auto& fruArea : areaVector)
    {
        fruid = fruArea->getFruID();
        // Fill the container with information
        rc = parse_fru_area(fruArea->getType(),
                            static_cast<const void*>(fruArea->getData()),
                            fruArea->getLength(), fruData);
        if (rc < 0)
        {
            lg2::error("Error parsing FRU records: {RC}", "RC", rc);
            return rc;
        }
    } // END walking the vector of areas and updating

    // For each FRU we have the list of instances which needs to be updated.
    // Each instance object implements certain interfaces.
    // Each Interface is having Dbus properties.
    // Each Dbus Property would be having metaData(eg section,VpdPropertyName).

    // Here we are just printing the object,interface and the properties.
    // which needs to be called with the new inventory manager implementation.
    using namespace std::string_literals;
    static const auto intf = "xyz.openbmc_project.Inventory.Manager"s;
    static const auto path = "/xyz/openbmc_project/inventory"s;
    std::string service;
    try
    {
        service = getService(bus, intf, path);
    }
    catch (const std::exception& e)
    {
        lg2::error("Failed to get service: {ERROR}", "ERROR", e);
        return -1;
    }

    auto iter = frus.find(fruid);
    if (iter == frus.end())
    {
        lg2::error("Unable to find fru id:({FRUID}) in generated list", "FRUID",
                   fruid);
        return -1;
    }

    auto& instanceList = iter->second;
    if (instanceList.size() <= 0)
    {
        lg2::debug("Object list empty for this fru id:({FRUID})", "FRUID",
                   fruid);
    }

    ObjectMap objects;
    for (const auto& instance : instanceList)
    {
        InterfaceMap interfaces;
        const auto& extrasIter = extras.find(instance.path);

        for (const auto& interfaceList : instance.interfaces)
        {
            PropertyMap props; // store all the properties
            for (const auto& properties : interfaceList.second)
            {
                std::string value;
                decltype(auto) pdata = properties.second;

                if (!pdata.section.empty() && !pdata.property.empty())
                {
                    value = getFRUValue(pdata.section, pdata.property,
                                        pdata.delimiter, fruData);
                }
                props.emplace(std::move(properties.first), std::move(value));
            }
            // Check and update extra properties
            if (extras.end() != extrasIter)
            {
                const auto& propsIter =
                    (extrasIter->second).find(interfaceList.first);
                if ((extrasIter->second).end() != propsIter)
                {
                    for (const auto& map : propsIter->second)
                    {
                        props.emplace(map.first, map.second);
                    }
                }
            }
            interfaces.emplace(std::move(interfaceList.first),
                               std::move(props));
        }

        // Call the inventory manager
        sdbusplus::message::object_path objectPath = instance.path;
        // Check and update extra properties
        if (extras.end() != extrasIter)
        {
            for (const auto& entry : extrasIter->second)
            {
                if (interfaces.end() == interfaces.find(entry.first))
                {
                    interfaces.emplace(entry.first, entry.second);
                }
            }
        }
        objects.emplace(objectPath, interfaces);
    }

    auto pimMsg = bus.new_method_call(service.c_str(), path.c_str(),
                                      intf.c_str(), "Notify");
    pimMsg.append(std::move(objects));

    try
    {
        auto inventoryMgrResponseMsg = bus.call(pimMsg);
    }
    catch (const sdbusplus::exception_t& ex)
    {
        lg2::error(
            "Error in notify call, service: {SERVICE}, path: {PATH}, error: {ERROR}",
            "SERVICE", service, "PATH", path, "ERROR", ex);
        return -1;
    }

    return rc;
}

} // namespace

/**
 * Takes the pointer to stream of bytes and length and returns the 8 bit
 * checksum.  This algo is per IPMI V2.0 spec
 *
 * @param[in] data - data for running crc
 * @param[in] len - the length over which to run the crc
 * @return the CRC value
 */
unsigned char calculateCRC(const unsigned char* data, size_t len)
{
    char crc = 0;
    size_t byte = 0;

    for (byte = 0; byte < len; byte++)
    {
        crc += *data++;
    }

    return (-crc);
}

/**
 * Accepts a FRU area offset into a common header and tells which area it is.
 *
 * @param[in] areaOffset - offset to lookup the area type
 * @return the ipmi_fru_area_type
 */
ipmi_fru_area_type getFruAreaType(uint8_t areaOffset)
{
    ipmi_fru_area_type type = IPMI_FRU_AREA_TYPE_MAX;

    switch (areaOffset)
    {
        case IPMI_FRU_INTERNAL_OFFSET:
            type = IPMI_FRU_AREA_INTERNAL_USE;
            break;

        case IPMI_FRU_CHASSIS_OFFSET:
            type = IPMI_FRU_AREA_CHASSIS_INFO;
            break;

        case IPMI_FRU_BOARD_OFFSET:
            type = IPMI_FRU_AREA_BOARD_INFO;
            break;

        case IPMI_FRU_PRODUCT_OFFSET:
            type = IPMI_FRU_AREA_PRODUCT_INFO;
            break;

        case IPMI_FRU_MULTI_OFFSET:
            type = IPMI_FRU_AREA_MULTI_RECORD;
            break;

        default:
            type = IPMI_FRU_AREA_TYPE_MAX;
    }

    return type;
}

/**
 * Validates the data for multirecord fields and CRC if selected
 *
 * @param[in] data - the data to verify
 * @param[in] len - the length of the region to verify
 * @param[in] validateCrc - whether to validate the CRC
 * @return non-zero on failure
 */
int verifyFruMultiRecData(const uint8_t* data, const size_t len,
                          bool validateCrc)
{
    uint8_t checksum = 0;
    int rc = -1;

    if (!validateCrc)
    {
        // There's nothing else to do for this area.
        return EXIT_SUCCESS;
    }

    // As per the IPMI platform spec, byte[3] is the record checksum.
    checksum = calculateCRC(data, len);
    if (checksum != data[3])
    {
        lg2::debug("Checksum mismatch, Calculated={CALC}, Embedded={EMBED}",
                   "CALC", lg2::hex, checksum, "EMBED", lg2::hex, data[3]);
        return rc;
    }

    return EXIT_SUCCESS;
}

/**
 * Validates the data for mandatory fields and CRC if selected.
 *
 * @param[in] data - the data to verify
 * @param[in] len - the length of the region to verify
 * @param[in] validateCrc - whether to validate the CRC
 * @return non-zero on failure
 */
int verifyFruData(const uint8_t* data, const size_t len, bool validateCrc)
{
    uint8_t checksum = 0;
    int rc = -1;

    // Validate for first byte to always have a value of [1]
    if (data[0] != IPMI_FRU_HDR_BYTE_ZERO)
    {
        lg2::error("Invalid entry in byte-0, entry: {ENTRY}", "ENTRY", lg2::hex,
                   data[0]);
        return rc;
    }
    lg2::debug("Validated in entry_1 of fruData,entry: {ENTRY}", "ENTRY",
               lg2::hex, data[0]);

    if (!validateCrc)
    {
        // There's nothing else to do for this area.
        return EXIT_SUCCESS;
    }

    // See if the calculated CRC matches with the embedded one.
    // CRC to be calculated on all except the last one that is CRC itself.
    checksum = calculateCRC(data, len - 1);
    if (checksum != data[len - 1])
    {
        lg2::debug("Checksum mismatch, Calculated={CALC}, Embedded={EMBED}",
                   "CALC", lg2::hex, checksum, "EMBED", lg2::hex, data[len]);
        return rc;
    }

    return EXIT_SUCCESS;
}

/**
 * Checks if a particular FRU area is populated or not.
 *
 * @param[in] reference to FRU area pointer
 * @return true if the area is empty
 */
bool removeInvalidArea(const std::unique_ptr<IPMIFruArea>& fruArea)
{
    // Filter the ones that are empty
    if (!(fruArea->getLength()))
    {
        return true;
    }
    return false;
}

/**
 * Populates various FRU areas.
 *
 * @prereq : This must be called only after validating common header
 * @param[in] fruData - pointer to the FRU bytes
 * @param[in] dataLen - the length of the FRU data
 * @param[in] fruAreaVec - the FRU area vector to update
 */
int ipmiPopulateFruAreas(uint8_t* fruData, const size_t dataLen,
                         FruAreaVector& fruAreaVec)
{
    // Now walk the common header and see if the file size has at least the last
    // offset mentioned by the struct common_header. If the file size is less
    // than the offset of any if the FRU areas mentioned in the common header,
    // then we do not have a complete file.
    for (uint8_t fruEntry = IPMI_FRU_INTERNAL_OFFSET;
         fruEntry < (sizeof(struct common_header) - 2); fruEntry++)
    {
        int rc = -1;
        // Actual offset in the payload is the offset mentioned in common header
        // multiplied by 8. Common header is always the first 8 bytes.
        size_t areaOffset = fruData[fruEntry] * IPMI_EIGHT_BYTES;
        if (areaOffset && (dataLen < (areaOffset + 2)))
        {
            // Our file size is less than what it needs to be. +2 because we are
            // using area len that is at 2 byte off areaOffset
            lg2::error("FRU file is incomplete, size: {SIZE}", "SIZE", dataLen);
            return rc;
        }
        else if (areaOffset)
        {
            // Read 3 bytes to know the actual size of area.
            uint8_t areaHeader[3] = {0};
            std::memcpy(areaHeader, &((uint8_t*)fruData)[areaOffset],
                        sizeof(areaHeader));

            // Size of this area will be the 2nd byte in the FRU area header.
            size_t areaLen;
            if (fruEntry == IPMI_FRU_MULTI_OFFSET)
            {
                areaLen = areaHeader[2] + IPMI_FRU_MULTIREC_HDR_BYTES;
            }
            else
            {
                areaLen = areaHeader[1] * IPMI_EIGHT_BYTES;
            }

            lg2::debug(
                "FRU Data, size: {SIZE}, area offset: {OFFSET}, area size: {AREA_SIZE}",
                "SIZE", dataLen, "OFFSET", areaOffset, "AREA_SIZE", areaLen);

            // See if we really have that much buffer. We have area offset amd
            // from there, the actual len.
            if (dataLen < (areaLen + areaOffset))
            {
                lg2::error("Incomplete FRU file, size: {SIZE}", "SIZE",
                           dataLen);
                return rc;
            }

            auto fruDataView =
                std::span<uint8_t>(&fruData[areaOffset], areaLen);
            auto areaData =
                std::vector<uint8_t>(fruDataView.begin(), fruDataView.end());

            // Validate the CRC, but not for the internal use area, since its
            // contents beyond the first byte are not defined in the spec and
            // it may not end with a CRC byte.
            bool validateCrc = fruEntry != IPMI_FRU_INTERNAL_OFFSET;

            if (fruEntry == IPMI_FRU_MULTI_OFFSET)
            {
                rc = verifyFruMultiRecData(areaData.data(), areaLen,
                                           validateCrc);
            }
            else
            {
                rc = verifyFruData(areaData.data(), areaLen, validateCrc);
            }

            if (rc < 0)
            {
                lg2::error("Err validating FRU area, offset: {OFFSET}",
                           "OFFSET", areaOffset);
                return rc;
            }
            lg2::debug("Successfully verified area, offset: {OFFSET}", "OFFSET",
                       areaOffset);

            // We already have a vector that is passed to us containing all
            // of the fields populated. Update the data portion now.
            for (auto& iter : fruAreaVec)
            {
                if (iter->getType() == getFruAreaType(fruEntry))
                {
                    iter->setData(areaData.data(), areaLen);
                }
            }
        } // If we have FRU data present
    } // Walk struct common_header

    // Not all the fields will be populated in a FRU data. Mostly all cases will
    // not have more than 2 or 3.
    fruAreaVec.erase(
        std::remove_if(fruAreaVec.begin(), fruAreaVec.end(), removeInvalidArea),
        fruAreaVec.end());

    return EXIT_SUCCESS;
}

/**
 * Validates the FRU data per ipmi common header constructs.
 * Returns with updated struct common_header and also file_size
 *
 * @param[in] fruData - the FRU data
 * @param[in] dataLen - the length of the data
 * @return non-zero on failure
 */
int ipmiValidateCommonHeader(const uint8_t* fruData, const size_t dataLen)
{
    int rc = -1;

    uint8_t commonHdr[sizeof(struct common_header)] = {0};
    if (dataLen >= sizeof(commonHdr))
    {
        std::memcpy(commonHdr, fruData, sizeof(commonHdr));
    }
    else
    {
        lg2::error("Incomplete FRU data file, size: {SIZE}", "SIZE", dataLen);
        return rc;
    }

    // Verify the CRC and size
    rc = verifyFruData(commonHdr, sizeof(commonHdr), true);
    if (rc < 0)
    {
        lg2::error("Failed to validate common header");
        return rc;
    }

    return EXIT_SUCCESS;
}

int validateFRUArea(const uint8_t fruid, const char* fruFilename,
                    sdbusplus::bus_t& bus)
{
    size_t dataLen = 0;
    size_t bytesRead = 0;
    int rc = -1;

    // Vector that holds individual IPMI FRU AREAs. Although MULTI and INTERNAL
    // are not used, keeping it here for completeness.
    FruAreaVector fruAreaVec;

    for (uint8_t fruEntry = IPMI_FRU_INTERNAL_OFFSET;
         fruEntry < (sizeof(struct common_header) - 2); fruEntry++)
    {
        // Create an object and push onto a vector.
        std::unique_ptr<IPMIFruArea> fruArea =
            std::make_unique<IPMIFruArea>(fruid, getFruAreaType(fruEntry));

        // Physically being present
        bool present = access(fruFilename, F_OK) == 0;
        fruArea->setPresent(present);

        fruAreaVec.emplace_back(std::move(fruArea));
    }

    FILE* fruFilePointer = std::fopen(fruFilename, "rb");
    if (fruFilePointer == nullptr)
    {
        lg2::error("Unable to open {FILE}, error: {ERRNO}", "FILE", fruFilename,
                   "ERRNO", std::strerror(errno));
        return cleanupError(fruFilePointer, fruAreaVec);
    }

    // Get the size of the file to see if it meets minimum requirement
    if (std::fseek(fruFilePointer, 0, SEEK_END))
    {
        lg2::error("Unable to seek {FILE}, error: {ERRNO}", "FILE", fruFilename,
                   "ERRNO", std::strerror(errno));
        return cleanupError(fruFilePointer, fruAreaVec);
    }

    // Allocate a buffer to hold entire file content
    dataLen = std::ftell(fruFilePointer);

    auto fruData = std::vector<uint8_t>(dataLen, 0);

    std::rewind(fruFilePointer);
    bytesRead = std::fread(fruData.data(), dataLen, 1, fruFilePointer);
    if (bytesRead != 1)
    {
        lg2::error(
            "Failed to reading FRU data, bytesRead: {BYTESREAD}, errno: {ERRNO}",
            "BYTESREAD", bytesRead, "ERRNO", std::strerror(errno));
        return cleanupError(fruFilePointer, fruAreaVec);
    }

    // We are done reading.
    std::fclose(fruFilePointer);
    fruFilePointer = nullptr;

    rc = ipmiValidateCommonHeader(fruData.data(), dataLen);
    if (rc < 0)
    {
        return cleanupError(fruFilePointer, fruAreaVec);
    }

    // Now that we validated the common header, populate various FRU sections if
    // we have them here.
    rc = ipmiPopulateFruAreas(fruData.data(), dataLen, fruAreaVec);
    if (rc < 0)
    {
        lg2::error("Populating fru id:({FRUID}) areas failed", "FRUID", fruid);
        return cleanupError(fruFilePointer, fruAreaVec);
    }
    lg2::debug("Populated FRU areas, file name: {FILE}", "FILE", fruFilename);

    for (const auto& iter : fruAreaVec)
    {
        lg2::debug("fru id: {FRUID}", "FRUID", iter->getFruID());
        lg2::debug("area name: {AREA}", "AREA", iter->getName());
        lg2::debug("type: {TYPE}", "TYPE", iter->getType());
        lg2::debug("length: {LEN}", "LEN", iter->getLength());
    }

    // If the vector is populated with everything, then go ahead and update the
    // inventory.
    if (!(fruAreaVec.empty()))
    {
        lg2::debug("fruAreaVec size: {SIZE}", "SIZE", fruAreaVec.size());
        rc = updateInventory(fruAreaVec, bus);
        if (rc < 0)
        {
            lg2::error("Error updating inventory.");
        }
    }

    // we are done with all that we wanted to do. This will do the job of
    // calling any destructors too.
    fruAreaVec.clear();

    return rc;
}
