extern "C" {
#include <libpdbg.h>
}

#include "fapi_data_process.hpp"

#include <attributes_info.H>
#include <fmt/format.h>

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <list>
#include <map>
#include <phosphor-logging/elog.hpp>
#include <sstream>
#include <string>

namespace openpower
{
namespace pels
{
namespace phal
{

using namespace phosphor::logging;

/**
 * Used to pass buffer to pdbg callback api to get required target
 * data (attributes) based on given data (attribute).
 */
struct TargetInfo
{
    ATTR_PHYS_BIN_PATH_Type physBinPath;
    ATTR_LOCATION_CODE_Type locationCode;
    ATTR_PHYS_DEV_PATH_Type physDevPath;
    ATTR_MRU_ID_Type mruId;

    bool deconfigure;

    TargetInfo()
    {
        memset(&physBinPath, '\0', sizeof(physBinPath));
        memset(&locationCode, '\0', sizeof(locationCode));
        memset(&physDevPath, '\0', sizeof(physDevPath));
        mruId = 0;
        deconfigure = false;
    }
};

/**
 * Used to return in callback function which are used to get
 * physical path value and it binary format value.
 *
 * The value for constexpr defined based on pdbg_target_traverse function usage.
 */
constexpr int continueTgtTraversal = 0;
constexpr int requireAttrFound = 1;
constexpr int requireAttrNotFound = 2;

/**
 * @brief Used to get target location code from phal device tree
 *
 * @param[in] target current device tree target
 * @param[out] appPrivData used for accessing|storing from|to application
 *
 * @return 0 to continue traverse, non-zero to stop traverse
 */
int pdbgCallbackToGetTgtReqAttrsVal(struct pdbg_target* target,
                                    void* appPrivData)
{
    TargetInfo* targetInfo = static_cast<TargetInfo*>(appPrivData);

    ATTR_PHYS_BIN_PATH_Type physBinPath;
    /**
     * TODO: Issue: phal/pdata#16
     * Should not use direct pdbg api to read attribute. Need to use DT_GET_PROP
     * macro for bmc app's and this will call libdt-api api but, it will print
     * "pdbg_target_get_attribute failed" trace if attribute is not found and
     * this callback will call recursively by using pdbg_target_traverse() until
     * find expected attribute based on return code from this callback. Because,
     * need to do target iteration to get actual attribute (ATTR_PHYS_BIN_PATH)
     * value when device tree target info doesn't know to read attribute from
     * device tree. So, Due to this error trace user will get confusion while
     * looking traces. Hence using pdbg api to avoid trace until libdt-api
     * provides log level setup.
     */
    if (!pdbg_target_get_attribute(
            target, "ATTR_PHYS_BIN_PATH",
            std::stoi(dtAttr::fapi2::ATTR_PHYS_BIN_PATH_Spec),
            dtAttr::fapi2::ATTR_PHYS_BIN_PATH_ElementCount, physBinPath))
    {
        return continueTgtTraversal;
    }

    if (std::memcmp(physBinPath, targetInfo->physBinPath,
                    sizeof(physBinPath)) != 0)
    {
        return continueTgtTraversal;
    }

    if (DT_GET_PROP(ATTR_LOCATION_CODE, target, targetInfo->locationCode))
    {
        log<level::ERR>("Could not read LOCATION_CODE attribute");
        return requireAttrNotFound;
    }

    if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, target, targetInfo->physDevPath))
    {
        log<level::ERR>("Could not read PHYS_DEV_PATH attribute");
        return requireAttrNotFound;
    }

    if (DT_GET_PROP(ATTR_MRU_ID, target, targetInfo->mruId))
    {
        log<level::ERR>("Could not read MRU_ID attribute");
        return requireAttrNotFound;
    }

    if (targetInfo->deconfigure)
    {
        ATTR_HWAS_STATE_Type hwasState;
        if (DT_GET_PROP(ATTR_HWAS_STATE, target, hwasState))
        {
            log<level::ERR>("Could not read HWAS_STATE attribute");
            return requireAttrNotFound;
        }

        log<level::INFO>(fmt::format("Marking target({}) as Non-Functional",
                                     targetInfo->physDevPath)
                             .c_str());
        hwasState.functional = 0;

        if (DT_SET_PROP(ATTR_HWAS_STATE, target, hwasState))
        {
            log<level::ERR>("Could not write HWAS_STATE attribute");
            return requireAttrNotFound;
        }
    }

    return requireAttrFound;
}

/**
 * @brief Used to get target info (attributes data)
 *
 * To get target required attributes value using another attribute value
 * ("PHYS_BIN_PATH" which is present in same target attributes list) by using
 * "ipdbg_target_traverse" api because, here we have attribute value only and
 * doesn't have respective device tree target info to get required attributes
 * values from it attributes list.
 *
 * @param[in] physBinPath to pass PHYS_BIN_PATH value
 * @param[out] targetInfo to pas buufer to fill with required attributes
 *
 * @return true on success otherwise false
 */
bool getTgtReqAttrsVal(const std::vector<uint8_t>& physBinPath,
                       TargetInfo& targetInfo)
{
    std::memcpy(&targetInfo.physBinPath, physBinPath.data(),
                sizeof(targetInfo.physBinPath));

    int ret = pdbg_target_traverse(NULL, pdbgCallbackToGetTgtReqAttrsVal,
                                   &targetInfo);
    if (ret == 0)
    {
        log<level::ERR>(fmt::format("Given ATTR_PHYS_BIN_PATH value({}) "
                                    "not found in phal device tree",
                                    targetInfo.physBinPath)
                            .c_str());
        return false;
    }
    else if (ret == requireAttrNotFound)
    {
        return false;
    }

    return true;
}

/**
 * @brief GET PEL priority from pHAL priority
 *
 * The pHAL callout priority is in different format than PEL format
 * so, this api is used to return current phal supported priority into
 * PEL expected format.
 *
 * @param[in] phalPriority used to pass phal priority format string
 *
 * @return pel priority format string else empty if failure
 *
 * @note For "NONE" returning "L" (LOW)
 */
static std::string getPelPriority(const std::string& phalPriority)
{
    const std::map<std::string, std::string> priorityMap = {
        {"HIGH", "H"}, {"MEDIUM", "M"}, {"LOW", "L"}, {"NONE", "L"}};

    auto it = priorityMap.find(phalPriority);
    if (it == priorityMap.end())
    {
        log<level::ERR>(fmt::format("Unsupported phal priority({}) is given "
                                    "to get pel priority format",
                                    phalPriority)
                            .c_str());
        return "H";
    }

    return it->second;
}

void convertFAPItoPELformat(FFDC& ffdc, json& pelJSONFmtCalloutDataList,
                            FFDCData& ffdcUserData)
{
    if (ffdc.ffdc_type == FFDC_TYPE_HWP)
    {
        // Adding hardware procedures return code details
        ffdcUserData.emplace_back("HWP_RC", ffdc.hwp_errorinfo.rc);
        ffdcUserData.emplace_back("HWP_RC_DESC", ffdc.hwp_errorinfo.rc_desc);

        // Adding hardware procedures required ffdc data for debug
        for_each(
            ffdc.hwp_errorinfo.ffdcs_data.begin(),
            ffdc.hwp_errorinfo.ffdcs_data.end(),
            [&ffdcUserData](std::pair<std::string, std::string>& ele) -> void {
                std::string keyWithPrefix("HWP_FFDC_");
                keyWithPrefix.append(ele.first);

                ffdcUserData.emplace_back(keyWithPrefix, ele.second);
            });

        // Adding hardware callout details
        int calloutCount = 0;
        for_each(
            ffdc.hwp_errorinfo.hwcallouts.begin(),
            ffdc.hwp_errorinfo.hwcallouts.end(),
            [&ffdcUserData, &calloutCount,
             &pelJSONFmtCalloutDataList](const HWCallout& hwCallout) -> void {
                calloutCount++;
                std::stringstream keyPrefix;
                keyPrefix << "HWP_HW_CO_" << std::setfill('0') << std::setw(2)
                          << calloutCount << "_";

                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("HW_ID"),
                    hwCallout.hwid);

                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("PRIORITY"),
                    hwCallout.callout_priority);

                phal::TargetInfo targetInfo;
                phal::getTgtReqAttrsVal(hwCallout.target_entity_path,
                                        targetInfo);

                std::string locationCode = std::string(targetInfo.locationCode);
                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("LOC_CODE"),
                    locationCode);

                std::string physPath = std::string(targetInfo.physDevPath);
                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("PHYS_PATH"), physPath);

                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("CLK_POS"),
                    std::to_string(hwCallout.clkPos));

                json jsonCalloutData;
                jsonCalloutData["LocationCode"] = locationCode;
                std::string pelPriority =
                    getPelPriority(hwCallout.callout_priority);
                jsonCalloutData["Priority"] = pelPriority;

                if (targetInfo.mruId != 0)
                {
                    jsonCalloutData["MRUs"] = json::array({
                        {{"ID", targetInfo.mruId}, {"Priority", pelPriority}},
                    });
                }

                pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
            });

        // Adding CDG (callout, deconfigure and guard) targets details
        calloutCount = 0;
        for_each(
            ffdc.hwp_errorinfo.cdg_targets.begin(),
            ffdc.hwp_errorinfo.cdg_targets.end(),
            [&ffdcUserData, &calloutCount,
             &pelJSONFmtCalloutDataList](const CDG_Target& cdg_tgt) -> void {
                calloutCount++;
                std::stringstream keyPrefix;
                keyPrefix << "HWP_CDG_TGT_" << std::setfill('0') << std::setw(2)
                          << calloutCount << "_";

                phal::TargetInfo targetInfo;
                targetInfo.deconfigure = cdg_tgt.deconfigure;

                phal::getTgtReqAttrsVal(cdg_tgt.target_entity_path, targetInfo);

                std::string locationCode = std::string(targetInfo.locationCode);
                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("LOC_CODE"),
                    locationCode);
                std::string physPath = std::string(targetInfo.physDevPath);
                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("PHYS_PATH"), physPath);

                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("CO_REQ"),
                    (cdg_tgt.callout == true ? "true" : "false"));

                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("CO_PRIORITY"),
                    cdg_tgt.callout_priority);

                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("DECONF_REQ"),
                    (cdg_tgt.deconfigure == true ? "true" : "false"));

                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("GUARD_REQ"),
                    (cdg_tgt.guard == true ? "true" : "false"));

                ffdcUserData.emplace_back(
                    std::string(keyPrefix.str()).append("GUARD_TYPE"),
                    cdg_tgt.guard_type);

                json jsonCalloutData;
                jsonCalloutData["LocationCode"] = locationCode;
                std::string pelPriority =
                    getPelPriority(cdg_tgt.callout_priority);
                jsonCalloutData["Priority"] = pelPriority;

                if (targetInfo.mruId != 0)
                {
                    jsonCalloutData["MRUs"] = json::array({
                        {{"ID", targetInfo.mruId}, {"Priority", pelPriority}},
                    });
                }
                jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
                jsonCalloutData["Guarded"] = cdg_tgt.guard;
                jsonCalloutData["GuardType"] = cdg_tgt.guard_type;
                jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;

                pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
            });
    }
    else if ((ffdc.ffdc_type != FFDC_TYPE_NONE) &&
             (ffdc.ffdc_type != FFDC_TYPE_UNSUPPORTED))
    {
        log<level::ERR>(fmt::format("Unsupported phal FFDC type to create PEL. "
                                    "MSG: {}",
                                    ffdc.message)
                            .c_str());
    }
}

} // namespace phal
} // namespace pels
} // namespace openpower
