#include <libpdbg.h>

#include <analyzer/analyzer_main.hpp>
#include <attn/attention.hpp>
#include <attn/attn_common.hpp>
#include <attn/attn_config.hpp>
#include <attn/attn_dbus.hpp>
#include <attn/attn_handler.hpp>
#include <attn/attn_logging.hpp>
#include <attn/bp_handler.hpp>
#include <attn/ti_handler.hpp>
#include <attn/vital_handler.hpp>

#include <algorithm>
#include <iomanip>
#include <map>
#include <sstream>
#include <vector>

namespace attn
{

/**
 * @brief Handle checkstop attention
 *
 * @param i_attention Attention object
 * @return 0 indicates that the checkstop attention was successfully handled
 *         1 indicates that the checkstop attention was NOT successfully
 *           handled.
 */
int handleCheckstop(Attention* i_attention);

/**
 * @brief Handle special attention
 *
 * @param i_attention Attention object
 * @return 0 indicates that the special attention was successfully handled
 *         1 indicates that the special attention was NOT successfully handled
 */
int handleSpecial(Attention* i_attention);

/** @brief Determine if attention is active and not masked */
bool activeAttn(uint32_t i_val, uint32_t i_mask, uint32_t i_attn);

/**
 * @brief The main attention handler logic
 *
 * @param i_breakpoints true = breakpoint special attn handling enabled
 */
void attnHandler(Config* i_config)
{
    // Vector of active attentions to be handled
    std::vector<Attention> active_attentions;

    uint32_t isr_val, isr_mask;

    // loop through processors looking for active attentions
    trace<level::INFO>("Attention handler started");

    pdbg_target* target;
    pdbg_for_each_class_target("proc", target)
    {
        if (PDBG_TARGET_ENABLED == pdbg_target_probe(target))
        {
            auto proc = pdbg_target_index(target); // get processor number

            // Use PIB target to determine if a processor is enabled
            char path[16];
            sprintf(path, "/proc%d/pib", proc);
            pdbg_target* pibTarget = pdbg_target_from_path(nullptr, path);

            // sanity check
            if (nullptr == pibTarget)
            {
                trace<level::INFO>("pib path or target not found");
                continue;
            }

            // check if pib target is enabled
            if (PDBG_TARGET_ENABLED == pdbg_target_probe(pibTarget))
            {
                // The processor FSI target is required for CFAM read
                sprintf(path, "/proc%d/fsi", proc);
                pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, path);

                // sanity check
                if (nullptr == fsiTarget)
                {
                    trace<level::INFO>("fsi path or target not found");
                    continue;
                }

                // trace the proc number
                std::string traceMsg = "proc: " + std::to_string(proc);
                trace<level::INFO>(traceMsg.c_str());

                isr_val = 0xffffffff; // invalid isr value

                // get active attentions on processor
                if (RC_SUCCESS != fsi_read(fsiTarget, 0x1007, &isr_val))
                {
                    // log cfam read error
                    trace<level::INFO>("Error! cfam read 0x1007 FAILED");
                    eventAttentionFail((int)AttnSection::attnHandler |
                                       ATTN_PDBG_CFAM);
                }
                else if (0xffffffff == isr_val)
                {
                    trace<level::INFO>("Error! cfam read 0x1007 INVALID");
                    continue;
                }
                else
                {
                    // trace isr value
                    std::stringstream ssIsr;
                    ssIsr << "cfam 0x1007 = 0x" << std::setw(8)
                          << std::setfill('0') << std::hex << isr_val;
                    std::string strobjIsr = ssIsr.str();
                    trace<level::INFO>(strobjIsr.c_str());

                    isr_mask = 0xffffffff; // invalid isr mask

                    // get interrupt enabled special attentions mask
                    if (RC_SUCCESS != fsi_read(fsiTarget, 0x100d, &isr_mask))
                    {
                        // log cfam read error
                        trace<level::INFO>("Error! cfam read 0x100d FAILED");
                        eventAttentionFail((int)AttnSection::attnHandler |
                                           ATTN_PDBG_CFAM);
                    }
                    else if (0xffffffff == isr_mask)
                    {
                        trace<level::INFO>("Error! cfam read 0x100d INVALID");
                        continue;
                    }
                    else
                    {
                        // trace true mask
                        std::stringstream ssMask;
                        ssMask << "cfam 0x100d = 0x" << std::setw(8)
                               << std::setfill('0') << std::hex << isr_mask;
                        std::string strobjMask = ssMask.str();
                        trace<level::INFO>(strobjMask.c_str());

                        // SBE vital attention active and not masked?
                        if (true == activeAttn(isr_val, isr_mask, SBE_ATTN))
                        {
                            active_attentions.emplace_back(Attention::Vital,
                                                           handleVital, target,
                                                           i_config);
                        }

                        // Checkstop attention active and not masked?
                        if (true ==
                            activeAttn(isr_val, isr_mask, CHECKSTOP_ATTN))
                        {
                            active_attentions.emplace_back(Attention::Checkstop,
                                                           handleCheckstop,
                                                           target, i_config);
                        }

                        // Special attention active and not masked?
                        if (true == activeAttn(isr_val, isr_mask, SPECIAL_ATTN))
                        {
                            active_attentions.emplace_back(Attention::Special,
                                                           handleSpecial,
                                                           target, i_config);
                        }
                    } // cfam 0x100d valid
                }     // cfam 0x1007 valid
            }         // fsi target enabled
        }             // pib target enabled
    }                 // next processor

    // convert to heap, highest priority is at front
    if (!std::is_heap(active_attentions.begin(), active_attentions.end()))
    {
        std::make_heap(active_attentions.begin(), active_attentions.end());
    }

    // call the attention handler until one is handled or all were attempted
    while (false == active_attentions.empty())
    {
        // handle highest priority attention, done if successful
        if (RC_SUCCESS == active_attentions.front().handle())
        {
            // an attention was handled so we are done
            break;
        }

        // move attention to back of vector
        std::pop_heap(active_attentions.begin(), active_attentions.end());

        // remove attention from vector
        active_attentions.pop_back();
    }
}

/**
 * @brief Handle checkstop attention
 *
 * @param i_attention Attention object
 * @return 0 indicates that the checkstop attention was successfully handled
 *         1 indicates that the checkstop attention was NOT successfully
 *           handled.
 */
int handleCheckstop(Attention* i_attention)
{
    int rc = RC_SUCCESS; // assume checkstop handled

    trace<level::INFO>("checkstop handler started");

    // if checkstop handling enabled, handle checkstop attention
    if (false == (i_attention->getConfig()->getFlag(enCheckstop)))
    {
        trace<level::INFO>("Checkstop handling disabled");
    }
    else
    {
        // Look for any attentions found in hardware. This will generate and
        // commit a PEL if any errors are found.
        if (true != analyzer::analyzeHardware())
        {
            rc = RC_ANALYZER_ERROR;
        }
    }

    return rc;
}

/**
 * @brief Handle special attention
 *
 * @param i_attention Attention object
 * @return 0 indicates that the special attention was successfully handled
 *         1 indicates that the special attention was NOT successfully handled
 */
int handleSpecial(Attention* i_attention)
{
    int rc = RC_SUCCESS; // assume special attention handled

    // The TI info chipop will give us a pointer to the TI info data
    uint8_t* tiInfo       = nullptr;                  // ptr to TI info data
    uint32_t tiInfoLen    = 0;                        // length of TI info data
    pdbg_target* attnProc = i_attention->getTarget(); // proc with attention

    bool tiInfoStatic = false; // assume TI info was provided (not created)

    if (attnProc != nullptr)
    {
        // The processor PIB target is required for get TI info chipop
        char path[16];
        sprintf(path, "/proc%d/pib", pdbg_target_index(attnProc));
        pdbg_target* tiInfoTarget = pdbg_target_from_path(nullptr, path);

        if (nullptr != tiInfoTarget)
        {
            if (PDBG_TARGET_ENABLED == pdbg_target_probe(tiInfoTarget))
            {
                sbe_mpipl_get_ti_info(tiInfoTarget, &tiInfo, &tiInfoLen);

                // If TI info not available use default based on host state
                if (nullptr == tiInfo)
                {
                    trace<level::INFO>("TI info data ptr is invalid");

                    HostRunningState runningState = hostRunningState();
                    std::string stateString       = "host state unknown";

                    if ((HostRunningState::Started == runningState) ||
                        (HostRunningState::Unknown == runningState))
                    {
                        if (HostRunningState::Started == runningState)
                        {
                            stateString = "host started";
                        }
                        tiInfo = (uint8_t*)defaultPhypTiInfo;
                    }
                    else
                    {
                        stateString = "host not started";
                        tiInfo      = (uint8_t*)defaultHbTiInfo;
                    }

                    // trace host state
                    trace<level::INFO>(stateString.c_str());

                    tiInfoStatic = true; // using our TI info
                }
            }
        }
    }

    bool tiInfoValid = false; // TI area data not valid or not available

    // If TI area exists and is marked valid we can assume TI occurred
    if ((nullptr != tiInfo) && (0 != tiInfo[0]))
    {
        TiDataArea* tiDataArea = (TiDataArea*)tiInfo;

        std::stringstream ss; // string stream object for tracing
        std::string strobj;   // string object for tracing

        // trace a few known TI data area values
        ss.str(std::string()); // empty the stream
        ss.clear();            // clear the stream
        ss << "TI data command = 0x" << std::setw(2) << std::setfill('0')
           << std::hex << (int)tiDataArea->command;
        strobj = ss.str();
        trace<level::INFO>(strobj.c_str());

        // Another check for valid TI Info since it has been seen that
        // tiInfo[0] != 0 but TI info is not valid
        if (0xa1 == tiDataArea->command)
        {
            tiInfoValid = true;

            // trace some more data since TI info appears valid
            ss.str(std::string()); // empty the stream
            ss.clear();            // clear the stream
            ss << "TI data term-type = 0x" << std::setw(2) << std::setfill('0')
               << std::hex << (int)tiDataArea->hbTerminateType;
            strobj = ss.str();
            trace<level::INFO>(strobj.c_str());

            ss.str(std::string()); // empty the stream
            ss.clear();            // clear the stream
            ss << "TI data SRC format = 0x" << std::setw(2) << std::setfill('0')
               << std::hex << (int)tiDataArea->srcFormat;
            strobj = ss.str();
            trace<level::INFO>(strobj.c_str());

            ss.str(std::string()); // empty the stream
            ss.clear();            // clear the stream
            ss << "TI data source = 0x" << std::setw(2) << std::setfill('0')
               << std::hex << (int)tiDataArea->source;
            strobj = ss.str();
            trace<level::INFO>(strobj.c_str());

            if (true == (i_attention->getConfig()->getFlag(enTerminate)))
            {
                // Call TI special attention handler
                rc = tiHandler(tiDataArea);
            }
        }
    }

    // If TI area not valid or not available
    if (false == tiInfoValid)
    {
        trace<level::INFO>("TI info NOT available");

        // if configured to handle breakpoint as default special attention
        if (i_attention->getConfig()->getFlag(dfltBreakpoint))
        {
            if (true == (i_attention->getConfig()->getFlag(enBreakpoints)))
            {
                // Call the breakpoint special attention handler
                bpHandler();
            }
        }
        // if configured to handle TI as default special attention
        else
        {
            if (true == (i_attention->getConfig()->getFlag(enTerminate)))
            {
                // Call TI special attention handler
                rc = tiHandler(nullptr);
            }
        }
    }

    // release TI data buffer
    if ((nullptr != tiInfo) && (false == tiInfoStatic))
    {
        free(tiInfo);
    }

    if (RC_SUCCESS != rc)
    {
        trace<level::INFO>("Special attn not handled");
    }

    return rc;
}

/**
 * @brief Determine if attention is active and not masked
 *
 * Determine whether an attention needs to be handled and trace details of
 * attention type and whether it is masked or not.
 *
 * @param i_val attention status register
 * @param i_mask attention true mask register
 * @param i_attn attention type
 * @param i_proc processor associated with registers
 *
 * @return true if attention is active and not masked, otherwise false
 */
bool activeAttn(uint32_t i_val, uint32_t i_mask, uint32_t i_attn)
{
    bool rc = false; // assume attn masked and/or inactive

    // if attention active
    if (0 != (i_val & i_attn))
    {
        std::stringstream ss;

        bool validAttn = true; // known attention type

        switch (i_attn)
        {
            case SBE_ATTN:
                ss << "SBE attn";
                break;
            case CHECKSTOP_ATTN:
                ss << "Checkstop attn";
                break;
            case SPECIAL_ATTN:
                ss << "Special attn";
                break;
            default:
                ss << "Unknown attn";
                validAttn = false;
        }

        // see if attention is masked
        if (true == validAttn)
        {
            if (0 != (i_mask & i_attn))
            {
                rc = true; // attention active and not masked
            }
            else
            {
                ss << " masked";
            }
        }

        std::string strobj = ss.str();      // ss.str() is temporary
        trace<level::INFO>(strobj.c_str()); // commit trace stream
    }

    return rc;
}

} // namespace attn
