#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
