#include <analyzer/service_data.hpp>

namespace analyzer
{

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

void ServiceData::calloutTarget(pdbg_target* i_target,
                                const callout::Priority& i_priority,
                                bool i_guard)
{
    // Add the target to the callout list.
    addTargetCallout(i_target, i_priority, i_guard);

    // Add the callout FFDC.
    nlohmann::json ffdc;
    ffdc["Callout Type"] = "Hardware Callout";
    ffdc["Target"]       = util::pdbg::getPhysDevPath(i_target);
    ffdc["Priority"]     = i_priority.getRegistryString();
    ffdc["Guard"]        = i_guard;
    addCalloutFFDC(ffdc);
}

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

void ServiceData::calloutConnected(pdbg_target* i_rxTarget,
                                   const callout::BusType& i_busType,
                                   const callout::Priority& i_priority,
                                   bool i_guard)
{
    // Get the endpoint target for the transfer side of the bus.
    auto txTarget = util::pdbg::getConnectedTarget(i_rxTarget, i_busType);

    // Callout the TX endpoint.
    addTargetCallout(txTarget, i_priority, i_guard);

    // Add the callout FFDC.
    nlohmann::json ffdc;
    ffdc["Callout Type"] = "Connected Callout";
    ffdc["Bus Type"]     = i_busType.getString();
    ffdc["RX Target"]    = util::pdbg::getPhysDevPath(i_rxTarget);
    ffdc["TX Target"]    = util::pdbg::getPhysDevPath(txTarget);
    ffdc["Priority"]     = i_priority.getRegistryString();
    ffdc["Guard"]        = i_guard;
    addCalloutFFDC(ffdc);
}

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

void ServiceData::calloutBus(pdbg_target* i_rxTarget,
                             const callout::BusType& i_busType,
                             const callout::Priority& i_priority, bool i_guard)
{
    // Get the endpoint target for the transfer side of the bus.
    auto txTarget = util::pdbg::getConnectedTarget(i_rxTarget, i_busType);

    // Callout the RX endpoint.
    addTargetCallout(i_rxTarget, i_priority, i_guard);

    // Callout the TX endpoint.
    addTargetCallout(txTarget, i_priority, i_guard);

    // Callout everything else in between.
    // TODO: For P10 (OMI bus and XBUS), the callout is simply the backplane.
    addBackplaneCallout(i_priority);

    // Add the callout FFDC.
    nlohmann::json ffdc;
    ffdc["Callout Type"] = "Bus Callout";
    ffdc["Bus Type"]     = i_busType.getString();
    ffdc["RX Target"]    = util::pdbg::getPhysDevPath(i_rxTarget);
    ffdc["TX Target"]    = util::pdbg::getPhysDevPath(txTarget);
    ffdc["Priority"]     = i_priority.getRegistryString();
    ffdc["Guard"]        = i_guard;
    addCalloutFFDC(ffdc);
}

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

void ServiceData::calloutClock(const callout::ClockType& i_clockType,
                               const callout::Priority& i_priority, bool)
{
    // Callout the clock target.
    // TODO: For P10, the callout is simply the backplane. Also, there are no
    //       clock targets in the device tree. So at the moment there is no
    //       guard support for clock targets.
    addBackplaneCallout(i_priority);

    // Add the callout FFDC.
    // TODO: Add the target and guard type if guard is ever supported.
    nlohmann::json ffdc;
    ffdc["Callout Type"] = "Clock Callout";
    ffdc["Clock Type"]   = i_clockType.getString();
    ffdc["Priority"]     = i_priority.getRegistryString();
    addCalloutFFDC(ffdc);
}

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

void ServiceData::calloutProcedure(const callout::Procedure& i_procedure,
                                   const callout::Priority& i_priority)
{
    // Add the actual callout to the service data.
    nlohmann::json callout;
    callout["Procedure"] = i_procedure.getString();
    callout["Priority"]  = i_priority.getUserDataString();
    addCallout(callout);

    // Add the callout FFDC.
    nlohmann::json ffdc;
    ffdc["Callout Type"] = "Procedure Callout";
    ffdc["Procedure"]    = i_procedure.getString();
    ffdc["Priority"]     = i_priority.getRegistryString();
    addCalloutFFDC(ffdc);
}

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

void ServiceData::calloutPart(const callout::PartType& i_part,
                              const callout::Priority& i_priority)
{
    if (callout::PartType::PNOR == i_part)
    {
        // The PNOR is on the BMC card.
        // TODO: Will need to be modified if we ever support systems with more
        //       than one BMC.
        addTargetCallout(util::pdbg::getTrgt("/bmc0"), i_priority, false);
    }
    else
    {
        throw std::logic_error("Unsupported part type: " + i_part.getString());
    }

    // Add the callout FFDC.
    nlohmann::json ffdc;
    ffdc["Callout Type"] = "Part Callout";
    ffdc["Part Type"]    = i_part.getString();
    ffdc["Priority"]     = i_priority.getRegistryString();
    addCalloutFFDC(ffdc);
}

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

void ServiceData::addCallout(const nlohmann::json& i_callout)
{
    // The new callout is either a hardware callout with a location code or a
    // procedure callout.

    std::string type{};
    if (i_callout.contains("LocationCode"))
    {
        type = "LocationCode";
    }
    else if (i_callout.contains("Procedure"))
    {
        type = "Procedure";
    }
    else
    {
        throw std::logic_error("Unsupported callout: " + i_callout.dump());
    }

    // A map to determine the priority order. All of the medium priorities,
    // including the medium group priorities, are all the same level.
    static const std::map<std::string, unsigned int> m = {
        {"H", 3}, {"M", 2}, {"A", 2}, {"B", 2}, {"C", 2}, {"L", 1},
    };

    bool addCallout = true;

    for (auto& c : iv_calloutList)
    {
        if (c.contains(type) && (c.at(type) == i_callout.at(type)))
        {
            // The new callout already exists. Don't add a new callout.
            addCallout = false;

            if (m.at(c.at("Priority")) < m.at(i_callout.at("Priority")))
            {
                // The new callout has a higher priority, update it.
                c["Priority"] = i_callout.at("Priority");
            }
        }
    }

    if (addCallout)
    {
        iv_calloutList.push_back(i_callout);
    }
}

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

void ServiceData::addTargetCallout(pdbg_target* i_target,
                                   const callout::Priority& i_priority,
                                   bool i_guard)
{
    nlohmann::json callout;

    callout["LocationCode"] = util::pdbg::getLocationCode(i_target);
    callout["Priority"]     = i_priority.getUserDataString();
    callout["Deconfigured"] = false;
    callout["Guarded"]      = false; // default

    // Check if guard info should be added.
    if (i_guard)
    {
        auto guardType = queryGuardPolicy();

        if (!(callout::GuardType::NONE == guardType))
        {
            callout["Guarded"]    = true;
            callout["EntityPath"] = util::pdbg::getPhysBinPath(i_target);
            callout["GuardType"]  = guardType.getString();
        }
    }

    addCallout(callout);
}

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

void ServiceData::addBackplaneCallout(const callout::Priority& i_priority)
{
    // TODO: There isn't a device tree object for this. So will need to hardcode
    //       the location code for now. In the future, we will need a mechanism
    //       to make this data driven.

    nlohmann::json callout;

    callout["LocationCode"] = "P0";
    callout["Priority"]     = i_priority.getUserDataString();
    callout["Deconfigured"] = false;
    callout["Guarded"]      = false;

    addCallout(callout);
}

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

} // namespace analyzer
