#include "fru_parser.hpp"

#include <nlohmann/json.hpp>
#include <phosphor-logging/lg2.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
#include <xyz/openbmc_project/Inventory/Decorator/Asset/common.hpp>
#include <xyz/openbmc_project/Inventory/Decorator/AssetTag/common.hpp>
#include <xyz/openbmc_project/Inventory/Decorator/Revision/common.hpp>
#include <xyz/openbmc_project/Inventory/Item/common.hpp>

#include <filesystem>
#include <fstream>

PHOSPHOR_LOG2_USING;

using namespace pldm::responder::dbus;

namespace pldm
{
namespace responder
{
namespace fru_parser
{
using Json = nlohmann::json;
using InternalFailure =
    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
using InventoryDecoratorAsset =
    sdbusplus::common::xyz::openbmc_project::inventory::decorator::Asset;
using InventoryDecoratorAssetTag =
    sdbusplus::common::xyz::openbmc_project::inventory::decorator::AssetTag;
using InventoryDecoratorRevision =
    sdbusplus::common::xyz::openbmc_project::inventory::decorator::Revision;
using InventoryItem = sdbusplus::common::xyz::openbmc_project::inventory::Item;

const Json emptyJson{};
const std::vector<Json> emptyJsonList{};

FruParser::FruParser(const std::string& dirPath,
                     const fs::path& fruMasterJsonPath)
{
    if (fs::exists(fruMasterJsonPath))
    {
        setupDefaultDBusLookup(fruMasterJsonPath);
    }
    setupDefaultFruRecordMap();

    fs::path dir(dirPath);
    if (fs::exists(dir) && !fs::is_empty(dir))
    {
        setupFruRecordMap(dirPath);
    }
}

void FruParser::setupDefaultDBusLookup(const fs::path& masterJsonPath)
{
    constexpr auto service = "xyz.openbmc_project.Inventory.Manager";
    constexpr auto rootPath = "/xyz/openbmc_project/inventory";
    std::ifstream jsonFile(masterJsonPath);
    auto data = Json::parse(jsonFile, nullptr, false);
    if (data.is_discarded())
    {
        error("Failed to parse FRU Dbus Lookup Map config file '{PATH}'",
              "PATH", masterJsonPath);
        std::abort();
    }
    std::map<Interface, EntityType> defIntfToEntityType;
    auto dbusMap = data.value("FruDBusLookupMap", emptyJson);
    for (const auto& element : dbusMap.items())

    {
        try
        {
            defIntfToEntityType[static_cast<Interface>(element.key())] =
                static_cast<EntityType>(element.value());
        }
        catch (const std::exception& e)
        {
            error("Failure in FRU dbus lookup map format, error - {ERROR}",
                  "ERROR", e);
            throw InternalFailure();
        }
    }

    Interfaces interfaces{};
    for (auto [intf, entityType] : defIntfToEntityType)
    {
        intfToEntityType[intf] = entityType;
        interfaces.emplace(intf);
    }

    lookupInfo.emplace(service, rootPath, std::move(interfaces));
}

void FruParser::setupDefaultFruRecordMap()
{
    const FruRecordInfo generalRecordInfo = {
        1, // generalRecordType
        1, // encodingTypeASCII
        {
            // DSP0257 Table 5 General FRU Record Field Type Definitions
            {InventoryDecoratorAsset::interface, "Model", "string", 2},
            {InventoryDecoratorAsset::interface, "PartNumber", "string", 3},
            {InventoryDecoratorAsset::interface, "SerialNumber", "string", 4},
            {InventoryDecoratorAsset::interface, "Manufacturer", "string", 5},
            {InventoryItem::interface, "PrettyName", "string", 8},
            {InventoryDecoratorAssetTag::interface, "AssetTag", "string", 11},
            {InventoryDecoratorRevision::interface, "Version", "string", 10},
        }};

    for (auto [intf, entityType] : intfToEntityType)
    {
        recordMap[intf] = {generalRecordInfo};
    }
}

void FruParser::setupFruRecordMap(const std::string& dirPath)
{
    for (auto& file : fs::directory_iterator(dirPath))
    {
        auto fileName = file.path().filename().string();
        std::ifstream jsonFile(file.path());
        auto data = Json::parse(jsonFile, nullptr, false);
        if (data.is_discarded())
        {
            error("Failed to parse FRU config file at '{PATH}'", "PATH",
                  file.path());
            throw InternalFailure();
        }

        try
        {
            auto record = data.value("record_details", emptyJson);
            auto recordType =
                static_cast<uint8_t>(record.value("fru_record_type", 0));
            auto encType =
                static_cast<uint8_t>(record.value("fru_encoding_type", 0));
            auto dbusIntfName = record.value("dbus_interface_name", "");
            auto entries = data.value("fru_fields", emptyJsonList);
            std::vector<FieldInfo> fieldInfo;

            for (const auto& entry : entries)
            {
                auto fieldType =
                    static_cast<uint8_t>(entry.value("fru_field_type", 0));
                auto dbus = entry.value("dbus", emptyJson);
                auto interface = dbus.value("interface", "");
                auto property = dbus.value("property_name", "");
                auto propType = dbus.value("property_type", "");
                fieldInfo.emplace_back(
                    std::make_tuple(std::move(interface), std::move(property),
                                    std::move(propType), std::move(fieldType)));
            }

            FruRecordInfo fruInfo;
            fruInfo =
                std::make_tuple(recordType, encType, std::move(fieldInfo));

            auto search = recordMap.find(dbusIntfName);

            // PLDM FRU can have multiple records for the same FRU like General
            // FRU record and multiple OEM FRU records. If the FRU item
            // interface name is already in the map, that indicates a record
            // info is already added for the FRU, so append the new record info
            // to the same data.
            if (search != recordMap.end())
            {
                search->second.emplace_back(std::move(fruInfo));
            }
            else
            {
                FruRecordInfos recordInfos{fruInfo};
                recordMap.emplace(dbusIntfName, recordInfos);
            }
        }
        catch (const std::exception&)
        {
            continue;
        }
    }
}

} // namespace fru_parser

} // namespace responder

} // namespace pldm
