#pragma once

#include <hei_includes.hpp>
#include <hei_isolation_data.hpp>
#include <register/hei_register.hpp>

namespace libhei
{

/**
 * @brief This class contains the isolation rules and bit definition for a node
 *        in a chip's error reporting structure.
 *
 * These objects are linked together to form a tree with a single root node. Any
 * active bits found in a node will either indicate an active attention or that
 * the attention originated in a child node.
 *
 * The primary function of this class is analyze(), which will do a depth-first
 * search of the tree to find all active attentions and add their signatures to
 * the returned isolation data.
 *
 * The tree structure is built from information in the Chip Data Files. It is
 * possible that the tree could be built with loop in the isolation. This would
 * be bug in the Chip Data Files. This class will keep track of all nodes that
 * have been analyzed to prevent cyclic isolation (an infinite loop).
 *
 * Each node instance will represent a register, or set of registers, that can
 * be configured to represent one or more attention types. These configuration
 * rules are a combination of hardware register objects and operator registers
 * objects to define rules like "REG & ~MASK & CNFG", which reads "return all
 * bits in REG that are not in MASK and set in CNFG". See the definition of the
 * Register class for details on how this works.
 *
 * This class cannot be added to the flyweights. There is no way to easily
 * distinguish differences between nodes on different chips without comparing
 * all of the capture registers, rules, and child nodes. Instead, the shared
 * pointers will be stored in the isolation chip, which will ensure there isn't
 * an attempt to add two nodes with the same ID and instance.
 */
class IsolationNode
{
  public: // Aliases
    using Ptr      = std::shared_ptr<IsolationNode>;
    using ConstPtr = std::shared_ptr<const IsolationNode>;

    using Key = std::pair<NodeId_t, Instance_t>;

  public: // Constructors, destructor, assignment
    /**
     * @brief Constructor from components.
     * @param i_id       Unique ID for all instances of this node.
     * @param i_instance Instance of this node.
     */
    IsolationNode(NodeId_t i_id, Instance_t i_instance) :
        iv_id(i_id), iv_instance(i_instance)
    {}

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

    /** @brief Copy constructor. */
    IsolationNode(const IsolationNode&) = delete;

    /** @brief Assignment operator. */
    IsolationNode& operator=(const IsolationNode&) = delete;

  private: // Instance variables
    /** The unique ID for all instances of this node. */
    const NodeId_t iv_id;

    /**
     * A node may have multiple instances. All of which will have the same ID.
     * This variable is used to distinguish between each instance of the node.
     */
    const Instance_t iv_instance;

    /**
     * This register could report multiple types of attentions. We can use a
     * register 'rule' (value) to find any active attentions for each attention
     * type (key). A 'rule', like "register & ~mask", is a combination of
     * HardwareRegister objects and virtual operator registers (all children
     * of the Register class).
     */
    std::map<AttentionType_t, const Register::ConstPtr> iv_rules;

    /**
     * Each bit (key) in this map indicates that an attention was driven from
     * another register (value).
     */
    std::map<BitPosition_t, const ConstPtr> iv_children;

  public: // Member functions
    /**
     * @brief  Finds all active attentions on this node. If an active bit is a
     *         leaf in the isolation tree, the bit's signature is added to the
     *         isolation data. Otherwise, this function is recursively called
     *         to analyze the child node that is driving the attention in this
     *         node.
     * @param  i_chip     The target chip for isolation.
     * @param  i_attnType The target attention type to analyze on this register.
     *                    Will assert a rule must exist for this attention type.
     * @param  io_isoData The isolation data returned back to the user
     *                    application.
     * @return True, if any active attentions found on this register.
     *         False, otherwise.
     */
    bool analyze(const Chip& i_chip, AttentionType_t i_attnType,
                 IsolationData& io_isoData) const;

    /**
     * @brief Adds a register rule for the given attention type. See iv_rules
     *        for details.
     *
     * This is only intended to be used during initialization of the isolator.
     * Will assert that a rule has not already been defined for this type.
     *
     * @param The target attention type.
     * @param The rule for this attention type.
     */
    void addRule(AttentionType_t i_attnType, Register::ConstPtr i_rule);

    /**
     * @brief Adds a child node to analyze for the given bit position in this
     *        node. See iv_children for details.
     *
     * This is only intended to be used during initialization of the isolator.
     * Will assert that nothing has already been defined for this bit.
     *
     * @param The target bit on this node.
     * @param The child node to analyze for the given bit.
     */
    void addChild(BitPosition_t i_bit, ConstPtr i_child);

    /** @return The node ID. */
    NodeId_t getId() const
    {
        return iv_id;
    }

    /** @return The node instance. */
    Instance_t getInstance() const
    {
        return iv_instance;
    }

    /** @return The node/instance key. */
    Key getKey() const
    {
        return {iv_id, iv_instance};
    }

  private: // Isolation stack and supporting functions.
    /** When analyze() is called at the tree root, all recursive calls to
     *  analyze() will target the same chip and attention type. So we only need
     *  to keep track of the nodes that have been analyzed to avoid cyclic
     *  isolation (an infinite loop). In fact, we only need to keep track of the
     *  nodes directly from this node to the root node. As long as this node
     *  does not already exist in the list, we can be sure there will not be a
     *  loop. So the list can be treated as a stack. When analyze() is called on
     *  a node, that node is pushed to the top of the stack (as long as it
     *  doesn't already exist in the stack). Then, just before analyze() exits,
     *  this node can be popped off the top of the stack. Once all the recursive
     *  calls have returned back to the root node the stack should be empty.
     */
    static std::vector<ConstPtr> cv_isolationStack;

    /**
     * @brief Pushes this node to the top of the stack. Will assert that this
     *        node does not already exist in cv_isolationStack.
     */
    void pushIsolationStack() const;

    /** @brief Pops the top node off of cv_isolationStack. */
    void popIsolationStack() const
    {
        cv_isolationStack.pop_back();
    }
};

} // end namespace libhei
