#include <isolator/hei_isolation_node.hpp>
#include <util/hei_bit_string.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();

    // Capture default set of registers for this node.
    captureRegisters(i_chip, io_isoData);

    // Get the rule for this attention type.
    auto rule_itr = iv_rules.find(i_attnType);

    // It is possible that a rule does not exist. The likely scenario is that
    // this node is intended to only gather FFDC for a specific bit in the
    // parent node.
    if (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() <= (1 << (sizeof(BitPosition_t) * 8)));

        // Find all active bits for this rule.
        for (BitPosition_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;

            // Capture registers specific to this isolation bit.
            captureRegisters(i_chip, io_isoData, bit);

            // 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)
                {
                    // It is possible the child node is only intended for FFDC.
                    // See comment near the check for a valid rule above.
                    // Otherwise, it is possible something went wrong. If 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_id, iv_instance, 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_id, iv_instance, bit, i_attnType});
            }
        }
    }

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

    return o_activeAttn;
}

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

void IsolationNode::addCaptureRegister(HardwareRegister::ConstPtr i_hwReg,
                                       BitPosition_t i_bit)
{
    HEI_ASSERT(i_hwReg); // should not be null

    // Check the bit range.
    if (MAX_BIT_POSITION != i_bit)
    {
        if (REG_TYPE_SCOM == iv_regType || REG_TYPE_ID_SCOM == iv_regType)
        {
            HEI_ASSERT(i_bit < 64);
        }
        else
        {
            HEI_ASSERT(false); // register type unsupported
        }
    }

    // Add this capture register only if it does not already exist in the list.
    auto itr = iv_capRegs.find(i_bit);
    if (iv_capRegs.end() == itr ||
        itr->second.end() ==
            std::find(itr->second.begin(), itr->second.end(), i_hwReg))
    {
        iv_capRegs[i_bit].push_back(i_hwReg);
    }
}

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

void IsolationNode::addRule(AttentionType_t i_attnType,
                            Register::ConstPtr i_rule)
{
    HEI_ASSERT(i_rule); // should not be null

    auto ret = iv_rules.emplace(i_attnType, i_rule);

    // If an entry already existed, it must point to the same object.
    HEI_ASSERT(ret.second || (ret.first->second == i_rule));
}

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

void IsolationNode::addChild(uint8_t i_bit, ConstPtr i_child)
{
    HEI_ASSERT(i_child); // should not be null

    auto ret = iv_children.emplace(i_bit, i_child);

    // If an entry already existed, it must point to the same object.
    HEI_ASSERT(ret.second || (ret.first->second == 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);
}

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

void IsolationNode::captureRegisters(const Chip& i_chip,
                                     IsolationData& io_isoData,
                                     BitPosition_t i_bit) const
{
    auto itr = iv_capRegs.find(i_bit);
    if (iv_capRegs.end() != itr)
    {
        // Capture all registers for this node.
        for (const auto& hwReg : itr->second)
        {
            // Read the register (adds BitString to register cache).
            if (hwReg->read(i_chip))
            {
                // The register read failed.
                // TODO: Would be nice to add SCOM errors to the log just in
                // case
                //       traces are not available.
                // TODO: This trace could be redundant with the user
                // application,
                //       which will have more information on the actual chip
                //       that failed anyway. Leaving it commented out for now
                //       until the SCOM errors are added to the log.
                // HEI_ERR("register read failed on chip type=0x%0" PRIx32
                //         "address=0x%0" PRIx64,
                //         i_chip.getType(), hwReg->getAddress());
            }
            else
            {
                // Add to the FFDC.
                io_isoData.addRegister(i_chip, hwReg->getId(),
                                       hwReg->getInstance(),
                                       hwReg->getBitString(i_chip));
            }
        }
    }
}

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

} // end namespace libhei
