#pragma once

#include "constants.hpp"
#include "types.hpp"

#include <nlohmann/json.hpp>

#include <mutex>
#include <optional>
#include <semaphore>
#include <tuple>

namespace vpd
{
/**
 * @brief A class to process and publish VPD data.
 *
 * The class works on VPD and is mainly responsible for following tasks:
 * 1) Select appropriate device tree and JSON. Reboot if required.
 * 2) Get desired parser using parser factory.
 * 3) Calling respective parser class to get parsed VPD.
 * 4) Arranging VPD data under required interfaces.
 * 5) Calling PIM to publish VPD.
 *
 * The class may also implement helper functions required for VPD handling.
 */
class Worker
{
  public:
    /**
     * List of deleted functions.
     */
    Worker(const Worker&);
    Worker& operator=(const Worker&);
    Worker(Worker&&) = delete;

    /**
     * @brief Constructor.
     *
     * In case the processing is not JSON based, no argument needs to be passed.
     * Constructor will also, based on symlink pick the correct JSON and
     * initialize the parsed JSON variable.
     *
     * @param[in] pathToConfigJSON - Path to the config JSON, if applicable.
     * @param[in] i_maxThreadCount - Maximum thread while collecting FRUs VPD.
     *
     * Note: Throws std::exception in case of construction failure. Caller needs
     * to handle to detect successful object creation.
     */
    Worker(std::string pathToConfigJson = std::string(),
           uint8_t i_maxThreadCount = constants::MAX_THREADS);

    /**
     * @brief Destructor
     */
    ~Worker() = default;

    /**
     * @brief An API to check if system VPD is already published.
     *
     * @return Status, true if system is already collected else false.
     */
    bool isSystemVPDOnDBus() const;

    /**
     * @brief API to process all FRUs presnt in config JSON file.
     *
     * This API based on config JSON passed/selected for the system, will
     * trigger parser for all the FRUs and publish it on DBus.
     *
     * Note: Config JSON file path should be passed to worker class constructor
     * to make use of this API.
     *
     */
    void collectFrusFromJson();

    /**
     * @brief API to parse VPD data
     *
     * @param[in] i_vpdFilePath - Path to the VPD file.
     */
    types::VPDMapVariant parseVpdFile(const std::string& i_vpdFilePath);

    /**
     * @brief An API to populate DBus interfaces for a FRU.
     *
     * Note: Call this API to populate D-Bus. Also caller should handle empty
     * objectInterfaceMap.
     *
     * @param[in] parsedVpdMap - Parsed VPD as a map.
     * @param[out] objectInterfaceMap - Object and its interfaces map.
     * @param[in] vpdFilePath - EEPROM path of FRU.
     */
    void populateDbus(const types::VPDMapVariant& parsedVpdMap,
                      types::ObjectMap& objectInterfaceMap,
                      const std::string& vpdFilePath);

    /**
     * @brief An API to delete FRU VPD over DBus.
     *
     * @param[in] i_dbusObjPath - Dbus object path of the FRU.
     *
     * @throw std::runtime_error if given input path is empty.
     */
    void deleteFruVpd(const std::string& i_dbusObjPath);

    /**
     * @brief API to get status of VPD collection process.
     *
     * @return - True when done, false otherwise.
     */
    inline bool isAllFruCollectionDone() const
    {
        return m_isAllFruCollected;
    }

    /**
     * @brief API to get system config JSON object
     *
     * @return System config JSON object.
     */
    inline nlohmann::json getSysCfgJsonObj() const
    {
        return m_parsedJson;
    }

    /**
     * @brief API to get active thread count.
     *
     * Each FRU is collected in a separate thread. This API gives the active
     * thread collecting FRU's VPD at any given time.
     *
     * @return Count of active threads.
     */
    size_t getActiveThreadCount() const
    {
        return m_activeCollectionThreadCount;
    }

    /**
     * @brief API to get list of EEPROMs for which thread creation failed.
     *
     * This API returns reference to list of EEPROM paths for which VPD
     * collection thread creation has failed. Manager needs to process this list
     * of EEPROMs and take appropriate action.
     *
     * @return reference to list of EEPROM paths for which VPD collection thread
     * creation has failed
     */
    inline std::forward_list<std::string>& getFailedEepromPaths() noexcept
    {
        return m_failedEepromPaths;
    }

    /**
     * @brief Collect single FRU VPD
     * API can be used to perform VPD collection for the given FRU, only if the
     * current state of the system matches with the state at which the FRU is
     * allowed for VPD recollection.
     *
     * @param[in] i_dbusObjPath - D-bus object path
     */
    void collectSingleFruVpd(
        const sdbusplus::message::object_path& i_dbusObjPath);

    /**
     * @brief  Perform VPD recollection
     * This api will trigger parser to perform VPD recollection for FRUs that
     * can be replaced at standby.
     */
    void performVpdRecollection();

    /**
     * @brief API to prime inventory Objects.
     *
     * @param[in] i_vpdFilePath - EEPROM file path.
     * @return true if the prime inventory is success, false otherwise.
     */
    bool primeInventory(const std::string& i_vpdFilePath);

    /**
     * @brief An API to set appropriate device tree and JSON.
     *
     * This API based on system chooses corresponding device tree and JSON.
     * If device tree change is required, it updates the "fitconfig" and reboots
     * the system. Else it is NOOP.
     *
     * @throw std::exception
     */
    void setDeviceTreeAndJson();

  private:
    /**
     * @brief An API to parse and publish a FRU VPD over D-Bus.
     *
     * Note: This API will handle all the exceptions internally and will only
     * return status of parsing and publishing of VPD over D-Bus.
     *
     * @param[in] i_vpdFilePath - Path of file containing VPD.
     * @return Tuple of status and file path. Status, true if successfull else
     * false.
     */
    std::tuple<bool, std::string> parseAndPublishVPD(
        const std::string& i_vpdFilePath);

    /**
     * @brief API to select system specific JSON.
     *
     * The API based on the IM value of VPD, will select appropriate JSON for
     * the system. In case no system is found corresponding to the extracted IM
     * value, error will be logged.
     *
     * @param[out] systemJson - System JSON name.
     * @param[in] parsedVpdMap - Parsed VPD map.
     */
    void getSystemJson(std::string& systemJson,
                       const types::VPDMapVariant& parsedVpdMap);

    /**
     * @brief An API to read IM value from VPD.
     *
     * Note: Throws exception in case of error. Caller need to handle.
     *
     * @param[in] parsedVpd - Parsed VPD.
     */
    std::string getIMValue(const types::IPZVpdMap& parsedVpd) const;

    /**
     * @brief An API to read HW version from VPD.
     *
     * Note: Throws exception in case of error. Caller need to handle.
     *
     * @param[in] parsedVpd - Parsed VPD.
     */
    std::string getHWVersion(const types::IPZVpdMap& parsedVpd) const;

    /**
     * @brief An API to parse given VPD file path.
     *
     * @throw std::exception
     *
     * @param[in] vpdFilePath - EEPROM file path.
     * @param[out] parsedVpd - Parsed VPD as a map.
     */
    void fillVPDMap(const std::string& vpdFilePath,
                    types::VPDMapVariant& parsedVpd);

    /**
     * @brief An API to parse and publish system VPD on D-Bus.
     *
     * Note: Throws exception in case of invalid VPD format.
     *
     * @param[in] parsedVpdMap - Parsed VPD as a map.
     */
    void publishSystemVPD(const types::VPDMapVariant& parsedVpdMap);

    /**
     * @brief An API to process extrainterfaces w.r.t a FRU.
     *
     * @param[in] singleFru - JSON block for a single FRU.
     * @param[out] interfaces - Map to hold interface along with its properties.
     * @param[in] parsedVpdMap - Parsed VPD as a map.
     */
    void processExtraInterfaces(const nlohmann::json& singleFru,
                                types::InterfaceMap& interfaces,
                                const types::VPDMapVariant& parsedVpdMap);

    /**
     * @brief An API to process embedded and synthesized FRUs.
     *
     * @param[in] singleFru - FRU to be processed.
     * @param[out] interfaces - Map to hold interface along with its properties.
     */
    void processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru,
                                           types::InterfaceMap& interfaces);

    /**
     * @brief An API to read process FRU based in CCIN.
     *
     * For some FRUs VPD can be processed only if the FRU has some specific
     * value for CCIN. In case the value is not from that set, VPD for those
     * FRUs can't be processed.
     *
     * @param[in] singleFru - Fru whose CCIN value needs to be matched.
     * @param[in] parsedVpdMap - Parsed VPD map.
     */
    bool processFruWithCCIN(const nlohmann::json& singleFru,
                            const types::VPDMapVariant& parsedVpdMap);

    /**
     * @brief API to process json's inherit flag.
     *
     * Inherit flag denotes that some property in the child FRU needs to be
     * inherited from parent FRU.
     *
     * @param[in] parsedVpdMap - Parsed VPD as a map.
     * @param[out] interfaces - Map to hold interface along with its properties.
     */
    void processInheritFlag(const types::VPDMapVariant& parsedVpdMap,
                            types::InterfaceMap& interfaces);

    /**
     * @brief API to process json's "copyRecord" flag.
     *
     * copyRecord flag denotes if some record data needs to be copies in the
     * given FRU.
     *
     * @param[in] singleFru - FRU being processed.
     * @param[in] parsedVpdMap - Parsed VPD as a map.
     * @param[out] interfaces - Map to hold interface along with its properties.
     */
    void processCopyRecordFlag(const nlohmann::json& singleFru,
                               const types::VPDMapVariant& parsedVpdMap,
                               types::InterfaceMap& interfaces);

    /**
     * @brief An API to populate IPZ VPD property map.
     *
     * @param[out] interfacePropMap - Map of interface and properties under it.
     * @param[in] keyordValueMap - Keyword value map of IPZ VPD.
     * @param[in] interfaceName - Name of the interface.
     */
    void populateIPZVPDpropertyMap(types::InterfaceMap& interfacePropMap,
                                   const types::IPZKwdValueMap& keyordValueMap,
                                   const std::string& interfaceName);

    /**
     * @brief An API to populate Kwd VPD property map.
     *
     * @param[in] keyordValueMap - Keyword value map of Kwd VPD.
     * @param[out] interfaceMap - interface and property,value under it.
     */
    void populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap,
                                   types::InterfaceMap& interfaceMap);

    /**
     * @brief API to populate all required interface for a FRU.
     *
     * @param[in] interfaceJson - JSON containing interfaces to be populated.
     * @param[out] interfaceMap - Map to hold populated interfaces.
     * @param[in] parsedVpdMap - Parsed VPD as a map.
     */
    void populateInterfaces(const nlohmann::json& interfaceJson,
                            types::InterfaceMap& interfaceMap,
                            const types::VPDMapVariant& parsedVpdMap);

    /**
     * @brief Check if the given CPU is an IO only chip.
     *
     * The CPU is termed as IO, whose all of the cores are bad and can never be
     * used. Those CPU chips can be used for IO purpose like connecting PCIe
     * devices etc., The CPU whose every cores are bad, can be identified from
     * the CP00 record's PG keyword, only if all of the 8 EQs' value equals
     * 0xE7F9FF. (1EQ has 4 cores grouped together by sharing its cache memory.)
     *
     * @param [in] pgKeyword - PG Keyword of CPU.
     * @return true if the given cpu is an IO, false otherwise.
     */
    bool isCPUIOGoodOnly(const std::string& pgKeyword);

    /**
     * @brief API to process preAction(base_action) defined in config JSON.
     *
     * @note sequence of tags under any given flag of preAction is EXTREMELY
     * important to ensure proper processing. The API will process all the
     * nested items under the base action sequentially. Also if any of the tag
     * processing fails, the code will not process remaining tags under the
     * flag.
     * ******** sample format **************
     * fru EEPROM path: {
     *     base_action: {
     *         flag1: {
     *           tag1: {
     *            },
     *           tag2: {
     *            }
     *         }
     *         flag2: {
     *           tags: {
     *            }
     *         }
     *     }
     * }
     * *************************************
     *
     * @param[in] i_vpdFilePath - Path to the EEPROM file.
     * @param[in] i_flagToProcess - To identify which flag(s) needs to be
     * processed under PreAction tag of config JSON.
     * @return Execution status.
     */
    bool processPreAction(const std::string& i_vpdFilePath,
                          const std::string& i_flagToProcess);

    /**
     * @brief API to process postAction(base_action) defined in config JSON.
     *
     * @note Sequence of tags under any given flag of postAction is EXTREMELY
     * important to ensure proper processing. The API will process all the
     * nested items under the base action sequentially. Also if any of the tag
     * processing fails, the code will not process remaining tags under the
     * flag.
     * ******** sample format **************
     * fru EEPROM path: {
     *     base_action: {
     *         flag1: {
     *           tag1: {
     *            },
     *           tag2: {
     *            }
     *         }
     *         flag2: {
     *           tags: {
     *            }
     *         }
     *     }
     * }
     * *************************************
     * Also, if post action is required to be processed only for FRUs with
     * certain CCIN then CCIN list can be provided under flag.
     *
     * @param[in] i_vpdFruPath - Path to the EEPROM file.
     * @param[in] i_flagToProcess - To identify which flag(s) needs to be
     * processed under postAction tag of config JSON.
     * @param[in] i_parsedVpd - Optional Parsed VPD map. If CCIN match is
     * required.
     * @return Execution status.
     */
    bool processPostAction(
        const std::string& i_vpdFruPath, const std::string& i_flagToProcess,
        const std::optional<types::VPDMapVariant> i_parsedVpd = std::nullopt);

    /**
     * @brief An API to perform backup or restore of VPD.
     *
     * @param[in,out] io_srcVpdMap - Source VPD map.
     */
    void performBackupAndRestore(types::VPDMapVariant& io_srcVpdMap);

    /**
     * @brief API to update "Functional" property.
     *
     * The API sets the default value for "Functional" property once if the
     * property is not yet populated over DBus. As the property value is not
     * controlled by the VPD-Collection process, if it is found already
     * populated, the functions skips re-populating the property so that already
     * existing value can be retained.
     *
     * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
     * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
     */
    void processFunctionalProperty(const std::string& i_inventoryObjPath,
                                   types::InterfaceMap& io_interfaces);

    /**
     * @brief API to update "enabled" property.
     *
     * The API sets the default value for "enabled" property once if the
     * property is not yet populated over DBus. As the property value is not
     * controlled by the VPD-Collection process, if it is found already
     * populated, the functions skips re-populating the property so that already
     * existing value can be retained.
     *
     * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
     * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
     */
    void processEnabledProperty(const std::string& i_inventoryObjPath,
                                types::InterfaceMap& io_interfaces);

    /**
     * @brief API to form asset tag string for the system.
     *
     * @param[in] i_parsedVpdMap - Parsed VPD map.
     *
     * @throw std::runtime_error
     *
     * @return - Formed asset tag string.
     */
    std::string createAssetTagString(
        const types::VPDMapVariant& i_parsedVpdMap);

    /**
     * @brief API to set symbolic link for system config JSON.
     *
     * Once correct device tree is set, symbolic link to the correct sytsem
     * config JSON is set to be used in subsequent BMC boot.
     *
     * @param[in] i_systemJson - system config JSON.
     */
    void setJsonSymbolicLink(const std::string& i_systemJson);

    /**
     * @brief API to set present property.
     *
     * This API updates the present property of the given FRU with the given
     * value. Note: It is the responsibility of the caller to determine whether
     * the present property for the FRU should be updated or not.
     *
     * @param[in] i_vpdPath - EEPROM or inventory path.
     * @param[in] i_value - value to be set.
     */
    void setPresentProperty(const std::string& i_fruPath, const bool& i_value);

    /**
     * @brief API to check if the path needs to be skipped for collection.
     *
     * Some FRUs, under some given scenarios should not be collected and
     * skipped.
     *
     * @param[in] i_vpdFilePath - EEPROM path.
     *
     * @return True - if path is empty or should be skipped, false otherwise.
     */
    bool skipPathForCollection(const std::string& i_vpdFilePath);

    /**
     * @brief API to check if present property should be handled for given FRU.
     *
     * vpd-manager should update present property for a FRU if and only if it's
     * not synthesized and vpd-manager handles present property for the FRU.
     * This API assumes "handlePresence" tag is a subset of "synthesized" tag.
     *
     * @param[in] i_fru -  JSON block for a single FRU.
     *
     * @return true if present property should be handled, false otherwise.
     */
    inline bool isPresentPropertyHandlingRequired(
        const nlohmann::json& i_fru) const noexcept
    {
        // TODO: revisit this to see if this logic can be optimized.
        return !i_fru.value("synthesized", false) &&
               i_fru.value("handlePresence", true);
    }

    /**
     * @brief API to set CollectionStatus property.
     *
     * This API updates the CollectionStatus property of the given FRU with the
     * given value.
     *
     * @param[in] i_vpdPath - EEPROM or inventory path.
     * @param[in] i_value - Value to be set.
     */
    void setCollectionStatusProperty(const std::string& i_fruPath,
                                     const std::string& i_value) const noexcept;

    // Parsed JSON file.
    nlohmann::json m_parsedJson{};

    // Hold if symlink is present or not.
    bool m_isSymlinkPresent = false;

    // Path to config JSON if applicable.
    std::string& m_configJsonPath;

    // Keeps track of active thread(s) doing VPD collection.
    size_t m_activeCollectionThreadCount = 0;

    // Holds status, if VPD collection has been done or not.
    // Note: This variable does not give information about successfull or failed
    // collection. It just states, if the VPD collection process is over or not.
    bool m_isAllFruCollected = false;

    // To distinguish the factory reset path.
    bool m_isFactoryResetDone = false;

    // Mutex to guard critical resource m_activeCollectionThreadCount.
    std::mutex m_mutex;

    // Counting semaphore to limit the number of threads.
    std::counting_semaphore<constants::MAX_THREADS> m_semaphore;

    // List of EEPROM paths for which VPD collection thread creation has failed.
    std::forward_list<std::string> m_failedEepromPaths;
};
} // namespace vpd
