#include <isolator/hei_isolation_node.hpp>

namespace libhei
{

//------------------------------------------------------------------------------

bool IsolationNode::analyze( const Chip & i_chip, AttentionType_t i_attnType,
                             IsolationData & io_isoData ) const
{
    bool o_activeAttn = false; // Initially, assume no active attentions.

    // Keep track of nodes that have been analyzed to avoid cyclic isolation.
    pushIsolationStack();

    // A rule for i_attnType must exist.
    auto rule_itr = iv_rules.find( i_attnType );
    HEI_ASSERT( iv_rules.end() != rule_itr );

    // Get the returned BitString for this rule.
    const BitString * bs = rule_itr->second->getBitString( i_chip );

    // Ensure this BitString is not longer than the maximum bit field.
    HEI_ASSERT( bs->getBitLen() <= sizeof(RegisterBit_t) * 8 );

    // Find all active bits for this rule.
    for ( RegisterBit_t bit = 0; bit < bs->getBitLen(); bit++ )
    {
        // Continue to the next bit if not active.
        if ( !bs->isBitSet(bit) ) continue;

        // At least one active bit was found.
        o_activeAttn = true;

        // Determine if this attention originated from another register or if it
        // is a leaf in the isolation tree.
        auto child_itr = iv_children.find( bit );
        if ( iv_children.end() != child_itr )
        {
            // This bit was driven from an attention from another register.
            // Continue down the isolation tree to look for more attentions.
            bool attnFound = child_itr->second->analyze( i_chip, i_attnType,
                                                         io_isoData );
            if ( !attnFound )
            {
                // Something went wrong. There should have been an active
                // attention. It's possible there is a bug in the Chip Data
                // File. Or, it is also possible some other piece of code is
                // clearing the attention before this code is able to analyze
                // it. Another possibility is that the hardware it not behaving
                // as expected. Since we really don't know what happened, we
                // should not assert. Instead, add this bit's signature to
                // io_isoData. If there are no other active attentions, the user
                // application could use this signature to help determine, and
                // circumvent, the isolation problem.
                io_isoData.addSignature( Signature { i_chip, iv_hwReg.getId(),
                                                     iv_hwReg.getInstance(),
                                                     bit, i_attnType } );
            }
        }
        else
        {
            // We have reached a leaf in the isolation tree. Add this bit's
            // signature to io_isoData.
            io_isoData.addSignature( Signature { i_chip, iv_hwReg.getId(),
                                                 iv_hwReg.getInstance(),
                                                 bit, i_attnType } );
        }
    }

    // Analysis is complete on this node. So remove it from cv_isolationStack.
    popIsolationStack();

    return o_activeAttn;
}

//------------------------------------------------------------------------------

void IsolationNode::addRule( AttentionType_t i_attnType,
                             const Register * i_rule )
{
    // A rule for this attention type should not already exist.
    HEI_ASSERT( iv_rules.end() == iv_rules.find(i_attnType) );

    // The rule should not be null.
    HEI_ASSERT( nullptr != i_rule );

    // Add the new rule.
    iv_rules[i_attnType] = i_rule;
}

//------------------------------------------------------------------------------

void IsolationNode::addChild( uint8_t i_bit, const IsolationNode * i_child )
{
    // An entry for this bit should not already exist.
    HEI_ASSERT( iv_children.end() == iv_children.find(i_bit) );

    // The child register should not be null.
    HEI_ASSERT( nullptr != i_child );

    // Add the new rule.
    iv_children[i_bit] = i_child;
}

//------------------------------------------------------------------------------

std::vector<const IsolationNode *> IsolationNode::cv_isolationStack {};

//------------------------------------------------------------------------------

void IsolationNode::pushIsolationStack() const
{
    // Ensure this node does not already exist in cv_isolationStack.
    auto itr = std::find( cv_isolationStack.begin(),
                          cv_isolationStack.end(), this );
    HEI_ASSERT( cv_isolationStack.end() == itr );

    // Push to node to the stack.
    cv_isolationStack.push_back( this );
}

//------------------------------------------------------------------------------

} // end namespace libhei

