#pragma once

#include "fru_parser.hpp"
#include "libpldmresponder/pdr_utils.hpp"
#include "oem_handler.hpp"
#include "pldmd/handler.hpp"

#include <libpldm/fru.h>
#include <libpldm/pdr.h>

#include <sdbusplus/message.hpp>

#include <map>
#include <string>
#include <variant>
#include <vector>

namespace pldm
{

namespace responder
{
namespace platform
{
class Handler; // forward declaration
}

namespace dbus
{

using Value =
    std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t,
                 uint64_t, double, std::string, std::vector<uint8_t>,
                 std::vector<uint64_t>, std::vector<std::string>>;
using PropertyMap = std::map<Property, Value>;
using InterfaceMap = std::map<Interface, PropertyMap>;
using ObjectValueTree = std::map<sdbusplus::object_path, InterfaceMap>;
using ObjectPath = std::string;
using AssociatedEntityMap = std::map<ObjectPath, pldm_entity>;
using ObjectPathToRSIMap = std::map<ObjectPath, uint16_t>;

} // namespace dbus

/** @class FruImpl
 *
 *  @brief Builds the PLDM FRU table containing the FRU records
 */
class FruImpl
{
  public:
    /* @brief Header size for FRU record, it includes the FRU record set
     *        identifier, FRU record type, Number of FRU fields, Encoding type
     *        of FRU fields
     */
    static constexpr size_t recHeaderSize =
        sizeof(struct pldm_fru_record_data_format) -
        sizeof(struct pldm_fru_record_tlv);

    /** @brief Constructor for FruImpl, the configPath is consumed to build the
     *         FruParser object.
     *
     *  @param[in] configPath - path to the directory containing config files
     *                          for PLDM FRU
     *  @param[in] fruMasterJsonPath - path to the file containing the FRU D-Bus
     *                                 Lookup Map
     *  @param[in] pdrRepo - opaque pointer to PDR repository
     *  @param[in] entityTree - opaque pointer to the entity association tree
     *  @param[in] bmcEntityTree - opaque pointer to bmc's entity association
     *                             tree
     *  @param[in] oemFruHandler - OEM fru handler
     */
    FruImpl(const std::string& configPath,
            const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo,
            pldm_entity_association_tree* entityTree,
            pldm_entity_association_tree* bmcEntityTree) :
        parser(configPath, fruMasterJsonPath), pdrRepo(pdrRepo),
        entityTree(entityTree), bmcEntityTree(bmcEntityTree)
    {}

    /** @brief Total length of the FRU table in bytes, this includes the pad
     *         bytes and the checksum.
     *
     *  @return size of the FRU table
     */
    uint32_t size() const
    {
        return table.size();
    }

    /** @brief The checksum of the contents of the FRU table
     *
     *  @return checksum
     */
    uint32_t checkSum() const
    {
        return checksum;
    }

    /** @brief Number of record set identifiers in the FRU tables
     *
     *  @return number of record set identifiers
     */
    uint16_t numRSI() const
    {
        return rsi;
    }

    /** @brief The number of FRU records in the table
     *
     *  @return number of FRU records
     */
    uint16_t numRecords() const
    {
        return numRecs;
    }

    /** @brief Get the FRU table
     *
     *  @param[out] - Populate response with the FRU table
     */
    void getFRUTable(Response& response);

    /** @brief Get the Fru Table MetaData
     *
     */
    void getFRURecordTableMetadata();

    /** @brief Get FRU Record Table By Option
     *  @param[out] response - Populate response with the FRU table got by
     *                         options
     *  @param[in] fruTableHandle - The fru table handle
     *  @param[in] recordSetIdentifer - The record set identifier
     *  @param[in] recordType - The record type
     *  @param[in] fieldType - The field type
     */
    int getFRURecordByOption(Response& response, uint16_t fruTableHandle,
                             uint16_t recordSetIdentifer, uint8_t recordType,
                             uint8_t fieldType);

    /** @brief FRU table is built by processing the D-Bus inventory namespace
     *         based on the config files for FRU. The table is populated based
     *         on the isBuilt flag.
     */
    void buildFRUTable();

    /** @brief Get std::map associated with the entity
     *         key: object path
     *         value: pldm_entity
     *
     *  @return std::map<ObjectPath, pldm_entity>
     */
    inline const pldm::responder::dbus::AssociatedEntityMap&
        getAssociateEntityMap() const
    {
        return associatedEntityMap;
    }

    /* @brief Method to set the oem platform handler in FRU handler class
     *
     * @param[in] handler - oem platform handler
     */
    inline void setOemPlatformHandler(
        pldm::responder::oem_platform::Handler* handler)
    {
        oemPlatformHandler = handler;
    }

    /** @brief Get pldm entity by the object path
     *
     *  @param[in] intfMaps - D-Bus interfaces and the associated property
     *                        values for the FRU
     *
     *  @return pldm_entity
     */
    std::optional<pldm_entity> getEntityByObjectPath(
        const dbus::InterfaceMap& intfMaps);

    /** @brief Update pldm entity to association tree
     *
     *  @param[in] objects - std::map The object value tree
     *  @param[in] path    - Object path
     *
     *  Ex: Input path =
     *  "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"
     *
     *  Get the parent class in turn and store it in a temporary vector
     *
     *  Output tmpObjPaths = {
     *  "/xyz/openbmc_project/inventory/system",
     *  "/xyz/openbmc_project/inventory/system/chassis/",
     *  "/xyz/openbmc_project/inventory/system/chassis/motherboard",
     *  "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"}
     *
     */
    void updateAssociationTree(const dbus::ObjectValueTree& objects,
                               const std::string& path);

    /* @brief Method to populate the firmware version ID
     *
     * @return firmware version ID
     */
    std::string populatefwVersion();

    /* @brief Method to resize the table
     *
     * @return resized table
     */
    std::vector<uint8_t> tableResize();

    /* @brief set FRU Record Table
     *
     * @param[in] fruData - the data of the fru
     *
     * @return PLDM completion code
     */
    int setFRUTable(const std::vector<uint8_t>& fruData);

    /* @brief Method to set the oem platform handler in fru handler class
     *
     * @param[in] handler - oem fru handler
     */
    inline void setOemFruHandler(pldm::responder::oem_fru::Handler* handler)
    {
        oemFruHandler = handler;
    }

    inline void setPlatformHandler(pldm::responder::platform::Handler* handler)
    {
        platformHandler = handler;
    }

  private:
    uint16_t nextRSI()
    {
        return ++rsi;
    }

    uint32_t nextRecordHandle()
    {
        return ++rh;
    }

    uint32_t rh = 0;
    uint16_t rsi = 0;
    uint16_t numRecs = 0;
    uint8_t padBytes = 0;
    std::vector<uint8_t> table;
    uint32_t checksum = 0;
    bool isBuilt = false;

    fru_parser::FruParser parser;
    pldm_pdr* pdrRepo;
    pldm_entity_association_tree* entityTree;
    pldm_entity_association_tree* bmcEntityTree;
    pldm::responder::oem_fru::Handler* oemFruHandler = nullptr;
    dbus::ObjectValueTree objects;
    pldm::responder::platform::Handler* platformHandler = nullptr;

    /** @OEM platform handler */
    pldm::responder::oem_platform::Handler* oemPlatformHandler;

    std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{};

    dbus::ObjectPathToRSIMap objectPathToRSIMap{};

    pdr_utils::DbusObjMaps effecterDbusObjMaps{};
    pdr_utils::DbusObjMaps sensorDbusObjMaps{};

    /** @brief populateRecord builds the FRU records for an instance of FRU and
     *         updates the FRU table with the FRU records.
     *
     *  @param[in] interfaces - D-Bus interfaces and the associated property
     *                          values for the FRU
     *  @param[in] recordInfos - FRU record info to build the FRU records
     *  @param[in/out] entity - PLDM entity corresponding to FRU instance
     */
    void populateRecords(const dbus::InterfaceMap& interfaces,
                         const fru_parser::FruRecordInfos& recordInfos,
                         const pldm_entity& entity);

    /** @brief Add hotplug record that was modified or added to the PDR entry
     *  HotPlug is a feature where a FRU can be removed or added when
     *  the system is running, without needing it to power off.
     *
     *  @param[in] pdrEntry - PDR record structure in PDR repository
     *
     *  @return record handle of added or modified hotplug record
     */
    uint32_t addHotPlugRecord(pldm::responder::pdr_utils::PdrEntry pdrEntry);

    /** @brief Deletes a FRU record from record set table.
     *  @param[in] rsi - the FRU Record Set Identifier
     *
     *  @return
     */
    void deleteFRURecord(uint16_t rsi);

    /** @brief Deletes a FRU record set PDR and it's associated PDRs after
     *         a concurrent remove operation.
     *  @param[in] fruObjectPath - the FRU object path
     *  @return
     */
    void removeIndividualFRU(const std::string& fruObjPath);

    /** @brief Associate sensor/effecter to FRU entity
     */
    dbus::AssociatedEntityMap associatedEntityMap;
};

namespace fru
{

class Handler : public CmdHandler
{
  public:
    Handler(const std::string& configPath,
            const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo,
            pldm_entity_association_tree* entityTree,
            pldm_entity_association_tree* bmcEntityTree) :
        impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree)
    {
        handlers.emplace(
            PLDM_GET_FRU_RECORD_TABLE_METADATA,
            [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
                return this->getFRURecordTableMetadata(request, payloadLength);
            });
        handlers.emplace(
            PLDM_GET_FRU_RECORD_TABLE,
            [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
                return this->getFRURecordTable(request, payloadLength);
            });
        handlers.emplace(
            PLDM_GET_FRU_RECORD_BY_OPTION,
            [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
                return this->getFRURecordByOption(request, payloadLength);
            });
        handlers.emplace(
            PLDM_SET_FRU_RECORD_TABLE,
            [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
                return this->setFRURecordTable(request, payloadLength);
            });
    }

    /** @brief Handler for Get FRURecordTableMetadata
     *
     *  @param[in] request - Request message payload
     *  @param[in] payloadLength - Request payload length
     *
     *  @return PLDM response message
     */
    Response getFRURecordTableMetadata(const pldm_msg* request,
                                       size_t payloadLength);

    /** @brief Handler for GetFRURecordTable
     *
     *  @param[in] request - Request message payload
     *  @param[in] payloadLength - Request payload length
     *
     *  @return PLDM response message
     */
    Response getFRURecordTable(const pldm_msg* request, size_t payloadLength);

    /** @brief Build FRU table is bnot already built
     *
     */
    void buildFRUTable()
    {
        impl.buildFRUTable();
    }

    /** @brief Get std::map associated with the entity
     *         key: object path
     *         value: pldm_entity
     *
     *  @return std::map<ObjectPath, pldm_entity>
     */
    const pldm::responder::dbus::AssociatedEntityMap& getAssociateEntityMap()
        const
    {
        return impl.getAssociateEntityMap();
    }

    /* @brief Method to set the oem platform  handler in host pdr handler class
     *
     * @param[in] handler - oem platform handler
     */
    void setOemPlatformHandler(pldm::responder::oem_platform::Handler* handler)
    {
        return impl.setOemPlatformHandler(handler);
    }

    /** @brief Handler for GetFRURecordByOption
     *
     *  @param[in] request - Request message payload
     *  @param[in] payloadLength - Request payload length
     *
     *  @return PLDM response message
     */
    Response getFRURecordByOption(const pldm_msg* request,
                                  size_t payloadLength);

    /** @brief Handler for SetFRURecordTable
     *
     *  @param[in] request - Request message
     *  @param[in] payloadLength - Request payload length
     *
     *  @return PLDM response message
     */
    Response setFRURecordTable(const pldm_msg* request, size_t payloadLength);

    /* @brief Method to set the oem platform handler in fru handler class
     *
     * @param[in] handler - oem fru handler
     */
    void setOemFruHandler(pldm::responder::oem_fru::Handler* handler)
    {
        impl.setOemFruHandler(handler);
    }

    void setPlatformHandler(pldm::responder::platform::Handler* handler)
    {
        impl.setPlatformHandler(handler);
    }

    using Table = std::vector<uint8_t>;

  private:
    FruImpl impl;
};

} // namespace fru

} // namespace responder

} // namespace pldm
