#include <libpdbg.h>

#include <attn/attn_common.hpp>
#include <attn/attn_handler.hpp>
#include <attn/attn_logging.hpp>
#include <sdbusplus/bus.hpp>
#include <util/pdbg.hpp>
#include <util/trace.hpp>

#include <iomanip>
#include <iostream>
#include <map>

namespace attn
{

/** @brief Traces some regs for hostboot */
void addHbStatusRegs()
{
    // Only do this for P10 systems
    if (util::pdbg::queryHardwareAnalysisSupported())
    {
        // We only need this for PRIMARY processor
        pdbg_target* pibTarget = pdbg_target_from_path(nullptr, "/proc0/pib");
        pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, "/proc0/fsi");

        uint32_t l_cfamData  = 0xFFFFFFFF;
        uint64_t l_scomData1 = 0xFFFFFFFFFFFFFFFFull;
        uint64_t l_scomData2 = 0xFFFFFFFFFFFFFFFFull;
        uint32_t l_cfamAddr  = 0x283C;
        uint64_t l_scomAddr1 = 0x4602F489;
        uint64_t l_scomAddr2 = 0x4602F487;

        if ((nullptr != fsiTarget) && (nullptr != pibTarget))
        {
            // get first debug reg (CFAM)
            if (RC_SUCCESS != fsi_read(fsiTarget, l_cfamAddr, &l_cfamData))
            {
                trace::err("cfam read error: 0x%08x", l_cfamAddr);
                l_cfamData = 0xFFFFFFFF;
            }

            // Get SCOM regs next (just 2 of them)
            if (RC_SUCCESS != pib_read(pibTarget, l_scomAddr1, &l_scomData1))
            {
                trace::err("scom read error: 0x%016" PRIx64 "", l_scomAddr1);
                l_scomData1 = 0xFFFFFFFFFFFFFFFFull;
            }

            if (RC_SUCCESS != pib_read(pibTarget, l_scomAddr2, &l_scomData2))
            {
                trace::err("scom read error: 0x%016" PRIx64 "", l_scomAddr2);
                l_scomData2 = 0xFFFFFFFFFFFFFFFFull;
            }
        }

        // Trace out the results here of all 3 regs
        // (Format should resemble FSP: HostBoot Reg:0000283C  Data:AA801504
        // 00000000  Proc:00050001 )
        trace::inf("HostBoot Reg:%08x Data:%08x Proc:00000000", l_cfamAddr,
                   l_cfamData);
        trace::inf("HostBoot Reg:%08" PRIx64 " Data:%016" PRIx64
                   " Proc:00000000",
                   l_scomAddr1, l_scomData1);
        trace::inf("HostBoot Reg:%08" PRIx64 " Data:%016" PRIx64
                   " Proc:00000000",
                   l_scomAddr2, l_scomData2);
    }

    return;

} // end addHbStatusRegs

/** @brief Capture some scratch registers for PRD */
void addPrdScratchRegs(std::vector<util::FFDCFile>& o_files)
{
    // Get primary processor FSI target for CFAM reads
    pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, "/proc0/fsi");

    if (nullptr == fsiTarget)
    {
        trace::err("error getting scratch register target");
    }
    else
    {
        uint32_t chipId      = 0;
        uint32_t signatureId = 0;

        // get scratch register 9 (CFAM)
        if (RC_SUCCESS != fsi_read(fsiTarget, 0x2980, &chipId))
        {
            trace::err("error reading scratch register 9");
            chipId = 0;
        }

        // get scratch register 10 (CFAM)
        if (RC_SUCCESS != fsi_read(fsiTarget, 0x2981, &signatureId))
        {
            trace::err("error reading scratch register 10");
            signatureId = 0;
        }

        // Add data to traces and create user data section
        if (0 != chipId || 0 != signatureId)
        {
            // trace scratch register data
            trace::inf("PRD scratch Proc0, Chip ID: %08x, Signature ID: %08x",
                       chipId, signatureId);

            // create ffdc data for user data section
            try
            {
                util::FFDCFile file{util::FFDCFormat::Text};
                int fd = file.getFileDescriptor();
                char buffer[150];
                int len = sprintf(buffer,
                                  "Scratch Register Error Signature\n"
                                  "Processor            : 0\n"
                                  "Chip ID              : %08x\n"
                                  "Signature ID         : %08x\n",
                                  chipId, signatureId);
                if (write(fd, buffer, len) < 0)
                {
                    trace::err("error writing scratch register user data");
                }
                else
                {
                    o_files.push_back(std::move(file));
                }
            }
            catch (const std::exception& e)
            {
                trace::err(
                    "exception when creating scratch register user data");
                trace::inf(e.what());
            }
        }
    }

    return;
}

/** @brief Check for recoverable errors present */
bool recoverableErrors()
{
    bool recoverableErrors = false; // assume no recoverable attentions

    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::inf("pib path or target not found");
                continue;
            }

            // check if pib target is enabled - indicates proc 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::inf("fsi path or target not found");
                    continue;
                }

                uint32_t 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::err("cfam read 0x1007 FAILED");
                    eventAttentionFail((int)AttnSection::attnHandler |
                                       ATTN_PDBG_CFAM);
                }
                // check for invalid/stale value
                else if (0xffffffff == isr_val)
                {
                    trace::err("cfam read 0x1007 INVALID");
                    continue;
                }
                // check recoverable error status bit
                else if (0 != (isr_val & RECOVERABLE_ATTN))
                {
                    recoverableErrors = true;
                    break;
                }
            } // fsi target enabled
        }     // pib target enabled
    }         // next processor

    return recoverableErrors;
}

/** @brief timesec less-than-equal-to compare */
bool operator<=(const timespec& lhs, const timespec& rhs)
{
    if (lhs.tv_sec == rhs.tv_sec)
        return lhs.tv_nsec <= rhs.tv_nsec;
    else
        return lhs.tv_sec <= rhs.tv_sec;
}

/** @brief sleep for n-seconds */
void sleepSeconds(const unsigned int seconds)
{
    auto count = seconds;
    struct timespec requested, remaining;

    while (0 < count)
    {
        requested.tv_sec  = 1;
        requested.tv_nsec = 0;
        remaining         = requested;

        while (-1 == nanosleep(&requested, &remaining))
        {
            // if not changing or implausible then abort
            if (requested <= remaining)
            {
                break;
            }

            // back to sleep
            requested = remaining;
        }
        count--;
    }
}

} // namespace attn
