#pragma once

#include <hei_signature.hpp>
#include <util/hei_bit_string.hpp>

#include <algorithm>
#include <map>
#include <memory>
#include <vector>

namespace libhei
{

/**
 * @brief The main isolate() API is given a list of chips to analyze. This class
 *        will contain a list of all active hardware errors found on those
 *        chips, the contents of any registers associated with the active
 *        errors, and any other data that can be useful for debug.
 */
class IsolationData
{
  public: // Constructors, destructor, assignment, etc.
    /** @brief Default constructor. */
    IsolationData() = default;

    /** @brief Destructor. */
    ~IsolationData() = default;

    /** @brief Copy constructor. */
    IsolationData(const IsolationData&) = default;

    /** @brief Assignment operator. */
    IsolationData& operator=(const IsolationData&) = default;

  public:
    /** The data stored in each entry of the register dump. */
    struct RegDumpEntry
    {
        RegDumpEntry(RegisterId_t i_regId, Instance_t i_regInst,
                     std::shared_ptr<BitStringBuffer> i_data) :
            regId(i_regId),
            regInst(i_regInst), data(i_data)
        {}

        RegisterId_t regId;                    ///< 3-byte register ID
        Instance_t regInst;                    ///< 1-byte register instance
        std::shared_ptr<BitStringBuffer> data; ///< register data

        bool operator==(const RegDumpEntry& r) const
        {
            return regId == r.regId && regInst == r.regInst && *data == *r.data;
        }
    };

  private: // Instance variables
    /** A list of all signatures found during isolation. */
    std::vector<Signature> iv_sigList;

    /**
     * This intended to be a snapshot of the register values read from hardware
     * as the isolator iterates the isolation tree. Therefore, it cannot share
     * the values stored in the hardware register cache. Instead, it must be a
     * copy of the data.
     */
    std::map<Chip, std::vector<RegDumpEntry>> iv_regDump;

  public: // Member functions
    /**
     * @brief Adds a signature to the signature list.
     * @param i_signature The target signature.
     */
    void addSignature(const Signature& i_signature)
    {
        iv_sigList.push_back(i_signature);
    }

    /**
     * @brief Adds the contents of a register to the register dump.
     * @param i_chip    The chip associated with this register.
     * @param i_regId   The register ID.
     * @param i_regInst The register instance.
     * @param i_data    A BitString containing the contents of the register.
     *                  Note that this function will make a copy of the data,
     *                  which will be stored separately from the hardware
     *                  register cache.
     */
    void addRegister(const Chip& i_chip, RegisterId_t i_regId,
                     Instance_t i_regInst, const BitString* i_data)
    {
        if (!i_data->isZero()) // Only add non-zero values to save space.
        {
            // Make a copy of the register value.
            auto data = std::make_shared<BitStringBuffer>(*i_data);

            // We'll want to avoid adding duplicate data if possible.
            if (iv_regDump.end() == iv_regDump.find(i_chip))
            {
                // The chip doesn't exist in the map. Therefore, the data
                // doesn't currently exist. So, add it.
                iv_regDump[i_chip].emplace_back(i_regId, i_regInst, data);
            }
            else
            {
                // Search this chip for the data.
                RegDumpEntry entry{i_regId, i_regInst, data};
                auto itr = std::find(iv_regDump[i_chip].begin(),
                                     iv_regDump[i_chip].end(), entry);

                if (iv_regDump[i_chip].end() == itr)
                {
                    // The data doesn't currently exist. So, add it.
                    iv_regDump[i_chip].push_back(entry);
                }
            }
        }
    }

    /** @brief Allows access to the signature list. */
    const std::vector<Signature>& getSignatureList() const
    {
        return iv_sigList;
    }

    /** @brief Allows access to the register dump. */
    const std::map<Chip, std::vector<RegDumpEntry>>& getRegisterDump() const
    {
        return iv_regDump;
    }

    /** @brief Flushes the data to ensure a clean slate for isolation. */
    void flush()
    {
        iv_sigList.clear();
        iv_regDump.clear();
    }

}; // end class IsolationData

} // end namespace libhei
