#include <fmt/format.h>

#include <util/dbus.hpp>
#include <util/trace.hpp>
#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>

namespace util
{
namespace dbus
{
//------------------------------------------------------------------------------

constexpr auto objectMapperService   = "xyz.openbmc_project.ObjectMapper";
constexpr auto objectMapperPath      = "/xyz/openbmc_project/object_mapper";
constexpr auto objectMapperInterface = "xyz.openbmc_project.ObjectMapper";

constexpr uint8_t terminusIdZero = 0;

/** @brief Find the path and service that implements the given interface */
int find(const std::string& i_interface, std::string& o_path,
         std::string& o_service)
{
    int rc = 1; // assume not success

    auto bus = sdbusplus::bus::new_default();

    try
    {
        constexpr auto function = "GetSubTree";

        auto method = bus.new_method_call(objectMapperService, objectMapperPath,
                                          objectMapperInterface, function);

        // Search the entire dbus tree for the specified interface
        method.append(std::string{"/"}, 0,
                      std::vector<std::string>{i_interface});

        auto reply = bus.call(method);

        DBusSubTree response;
        reply.read(response);

        if (!response.empty())
        {
            // Response is a map of object paths to a map of service, interfaces
            auto object = *(response.begin());
            o_path      = object.first;                 // return path
            o_service   = object.second.begin()->first; // return service

            rc = 0; // success
        }
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        trace::err("util::dbus::find exception");
        std::string traceMsg = std::string(e.what());
        trace::err(traceMsg.c_str());
    }

    return rc;
}

/** @brief Find the service that implements the given object and interface */
int findService(const std::string& i_interface, const std::string& i_path,
                std::string& o_service)
{
    int rc = 1; // assume not success

    auto bus = sdbusplus::bus::new_default();

    try
    {
        constexpr auto function = "GetObject";

        auto method = bus.new_method_call(objectMapperService, objectMapperPath,
                                          objectMapperInterface, function);

        // Find services that implement the object path, constrain the search
        // to the given interface.
        method.append(i_path, std::vector<std::string>{i_interface});

        auto reply = bus.call(method);

        // response is a map of service names to their interfaces
        std::map<DBusService, DBusInterfaceList> response;
        reply.read(response);

        if (!response.empty())
        {
            // return the service
            o_service = response.begin()->first;

            rc = 0; // success
        }
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        trace::err("util::dbus::map exception");
        std::string traceMsg = std::string(e.what());
        trace::err(traceMsg.c_str());
    }

    return rc;
}

/** @brief Read a property from a dbus object interface */
int getProperty(const std::string& i_interface, const std::string& i_path,
                const std::string& i_service, const std::string& i_property,
                DBusValue& o_response)
{
    int rc = 1; // assume not success

    auto bus = sdbusplus::bus::new_default();

    try
    {
        constexpr auto interface = "org.freedesktop.DBus.Properties";
        constexpr auto function  = "Get";

        // calling the get property method
        auto method = bus.new_method_call(i_service.c_str(), i_path.c_str(),
                                          interface, function);

        method.append(i_interface, i_property);
        auto reply = bus.call(method);

        // returning the property value
        reply.read(o_response);

        rc = 0; // success
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        trace::err("util::dbus::getProperty exception");
        std::string traceMsg = std::string(e.what());
        trace::err(traceMsg.c_str());
    }

    return rc;
}

/** @brief Get the IBM compatible names defined for this system */
std::vector<std::string> systemNames()
{
    std::vector<std::string> names;

    constexpr auto interface =
        "xyz.openbmc_project.Configuration.IBMCompatibleSystem";

    DBusService service;
    DBusPath path;

    // find a dbus object and path that implements the interface
    if (0 == find(interface, path, service))
    {
        DBusValue value;

        // compatible system names are implemented as a property
        constexpr auto property = "Names";

        if (0 == getProperty(interface, path, service, property, value))
        {
            // return value is a variant, names are in the vector
            names = std::get<std::vector<std::string>>(value);
        }
    }

    return names;
}

/** @brief Transition the host state */
void transitionHost(const HostState i_hostState)
{
    try
    {
        // We will be transitioning host by starting appropriate dbus target
        std::string target = "obmc-host-quiesce@0.target"; // quiesce is default

        // crash (mpipl) mode state requested
        if (HostState::Crash == i_hostState)
        {
            target = "obmc-host-crash@0.target";
        }

        auto bus    = sdbusplus::bus::new_system();
        auto method = bus.new_method_call(
            "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
            "org.freedesktop.systemd1.Manager", "StartUnit");

        method.append(target);    // target unit to start
        method.append("replace"); // mode = replace conflicting queued jobs

        bus.call_noreply(method); // start the service
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        trace::err("util::dbus::transitionHost exception");
        std::string traceMsg = std::string(e.what());
        trace::err(traceMsg.c_str());
    }
}

/** @brief Read state of autoRebootEnabled property via dbus */
bool autoRebootEnabled()
{
    // Assume true in case autoRebootEnbabled property is not available
    bool autoReboot = true;

    constexpr auto interface = "xyz.openbmc_project.Control.Boot.RebootPolicy";

    DBusService service; // will find this
    DBusPath path;       // will find this

    // find a dbus object and path that implements the interface
    if (0 == find(interface, path, service))
    {
        DBusValue value;

        // autoreboot policy is implemented as a property
        constexpr auto property = "AutoReboot";

        if (0 == getProperty(interface, path, service, property, value))
        {
            // return value is a variant, autoreboot policy is boolean
            autoReboot = std::get<bool>(value);
        }
    }

    return autoReboot;
}

/** @brief Get the running state of the host */
HostRunningState hostRunningState()
{
    // assume not able to get host running state
    HostRunningState host = HostRunningState::Unknown;

    constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress";

    DBusService service;
    DBusPath path;

    // find a dbus object and path that implements the interface
    if (0 == find(interface, path, service))
    {
        DBusValue value;

        // boot progress is implemented as a property
        constexpr auto property = "BootProgress";

        if (0 == getProperty(interface, path, service, property, value))
        {
            // return value is a variant, progress is in the vector of strings
            std::string bootProgress(std::get<std::string>(value));

            // convert boot progress to host state
            using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::
                server::Progress::ProgressStages;

            BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot::
                server::Progress::convertProgressStagesFromString(bootProgress);

            if ((stage == BootProgress::SystemInitComplete) ||
                (stage == BootProgress::OSStart) ||
                (stage == BootProgress::OSRunning))
            {
                host = HostRunningState::Started;
            }
            else
            {
                host = HostRunningState::NotStarted;
            }
        }
    }

    return host;
}

/** @brief Read state of dumpPolicyEnabled property via dbus */
bool dumpPolicyEnabled()
{
    // Assume true In case dumpPolicyEnabled property is not available
    bool dumpPolicyEnabled = true;

    constexpr auto interface = "xyz.openbmc_project.Object.Enable";
    constexpr auto path      = "/xyz/openbmc_project/dump/system_dump_policy";

    DBusService service; // will find this

    // find a dbus object and path that implements the interface
    if (0 == findService(interface, path, service))
    {
        DBusValue value;

        // autoreboot policy is implemented as a property
        constexpr auto property = "Enabled";

        if (0 == getProperty(interface, path, service, property, value))
        {
            // return value is a variant, dump policy enabled is a boolean
            dumpPolicyEnabled = std::get<bool>(value);
        }
    }

    return dumpPolicyEnabled;
}

/** @brief Create a PEL */
uint32_t createPel(const std::string& i_message, const std::string& i_severity,
                   std::map<std::string, std::string>& io_additional,
                   const std::vector<util::FFDCTuple>& i_ffdc)
{
    // CreatePELWithFFDCFiles returns plid
    int plid = 0;

    // Sdbus call specifics
    constexpr auto interface = "org.open_power.Logging.PEL";
    constexpr auto path      = "/xyz/openbmc_project/logging";

    // we need to find the service implementing the interface
    util::dbus::DBusService service;

    if (0 == findService(interface, path, service))
    {
        try
        {
            constexpr auto function = "CreatePELWithFFDCFiles";

            // The "Create" method requires manually adding the process ID.
            io_additional["_PID"] = std::to_string(getpid());

            // create dbus method
            auto bus = sdbusplus::bus::new_system();
            sdbusplus::message_t method =
                bus.new_method_call(service.c_str(), path, interface, function);

            // append additional dbus call paramaters
            method.append(i_message, i_severity, io_additional, i_ffdc);

            // using system dbus
            auto response = bus.call(method);

            // reply will be tuple containing bmc log id, platform log id
            std::tuple<uint32_t, uint32_t> reply = {0, 0};

            // parse dbus response into reply
            response.read(reply);
            plid = std::get<1>(reply); // platform log id is tuple "second"
        }
        catch (const sdbusplus::exception::SdBusError& e)
        {
            trace::err("createPel exception");
            trace::err(e.what());
        }
    }

    return plid; // platform log id or 0
}

MachineType getMachineType()
{
    // default to Rainier 2S4U
    MachineType machineType = MachineType::Rainier_2S4U;

    // The return value of the dbus operation is a vector of 4 uint8_ts
    std::vector<uint8_t> ids;

    constexpr auto interface = "com.ibm.ipzvpd.VSBP";

    DBusService service;
    DBusPath path;

    if (0 == find(interface, path, service))
    {
        DBusValue value;

        // Machine ID is given from the "IM" keyword
        constexpr auto property = "IM";

        if (0 == getProperty(interface, path, service, property, value))
        {
            // return value is a variant, ID value is a vector of 4 uint8_ts
            ids = std::get<std::vector<uint8_t>>(value);

            // Convert the returned ID value to a hex string to determine
            // machine type. The hex values corresponding to the machine type
            // are defined in /openbmc/openpower-vpd-parser/const.hpp
            // RAINIER_2S4U == 0x50001000
            // RAINIER_2S2U == 0x50001001
            // RAINIER_1S4U == 0x50001002
            // RAINIER_1S2U == 0x50001003
            // EVEREST      == 0x50003000
            try
            {
                // Format the vector into a single hex string to compare to.
                std::string hexId =
                    fmt::format("0x{:02x}{:02x}{:02x}{:02x}", ids.at(0),
                                ids.at(1), ids.at(2), ids.at(3));

                std::map<std::string, MachineType> typeMap = {
                    {"0x50001000", MachineType::Rainier_2S4U},
                    {"0x50001001", MachineType::Rainier_2S2U},
                    {"0x50001002", MachineType::Rainier_1S4U},
                    {"0x50001003", MachineType::Rainier_1S2U},
                    {"0x50003000", MachineType::Everest},
                };

                machineType = typeMap.at(hexId);
            }
            catch (const std::out_of_range& e)
            {
                trace::err("Out of range exception caught from returned "
                           "machine ID.");
                for (const auto& id : ids)
                {
                    trace::err("Returned Machine ID value: 0x%x", id);
                }
                throw;
            }
        }
    }
    else
    {
        throw std::invalid_argument(
            "Unable to find dbus service to get machine type.");
    }

    return machineType;
}

/** @brief Get list of state effecter PDRs */
bool getStateEffecterPdrs(std::vector<std::vector<uint8_t>>& pdrList,
                          uint16_t stateSetId)
{
    constexpr auto service   = "xyz.openbmc_project.PLDM";
    constexpr auto path      = "/xyz/openbmc_project/pldm";
    constexpr auto interface = "xyz.openbmc_project.PLDM.PDR";
    constexpr auto function  = "FindStateEffecterPDR";

    constexpr uint16_t PLDM_ENTITY_PROC = 135;

    try
    {
        // create dbus method
        auto bus = sdbusplus::bus::new_default();
        sdbusplus::message_t method =
            bus.new_method_call(service, path, interface, function);

        // append additional method data
        method.append(terminusIdZero, PLDM_ENTITY_PROC, stateSetId);

        // request PDRs
        auto reply = bus.call(method);
        reply.read(pdrList);
    }
    catch (const sdbusplus::exception_t& e)
    {
        trace::err("failed to find state effecter PDRs");
        trace::err(e.what());
        return false;
    }

    return true;
}

/** @brief Get list of state sensor PDRs */
bool getStateSensorPdrs(std::vector<std::vector<uint8_t>>& pdrList,
                        uint16_t stateSetId)
{
    constexpr auto service   = "xyz.openbmc_project.PLDM";
    constexpr auto path      = "/xyz/openbmc_project/pldm";
    constexpr auto interface = "xyz.openbmc_project.PLDM.PDR";
    constexpr auto function  = "FindStateSensorPDR";

    constexpr uint16_t PLDM_ENTITY_PROC = 135;

    try
    {
        // create dbus method
        auto bus = sdbusplus::bus::new_default();
        sdbusplus::message_t method =
            bus.new_method_call(service, path, interface, function);

        // append additional method data
        method.append(terminusIdZero, PLDM_ENTITY_PROC, stateSetId);

        // request PDRs
        auto reply = bus.call(method);
        reply.read(pdrList);
    }
    catch (const sdbusplus::exception_t& e)
    {
        trace::err("failed to find state sensor PDRs");
        trace::err(e.what());
        return false;
    }

    return true;
}

/** @brief Get MCTP instance associated with endpoint */
bool getMctpInstance(uint8_t& mctpInstance, uint8_t Eid)
{
    constexpr auto service   = "xyz.openbmc_project.PLDM";
    constexpr auto path      = "/xyz/openbmc_project/pldm";
    constexpr auto interface = "xyz.openbmc_project.PLDM.Requester";
    constexpr auto function  = "GetInstanceId";

    try
    {
        // create dbus method
        auto bus = sdbusplus::bus::new_default();
        sdbusplus::message_t method =
            bus.new_method_call(service, path, interface, function);

        // append endpoint ID
        method.append(Eid);

        // request MCTP instance ID
        auto reply = bus.call(method);
        reply.read(mctpInstance);
    }
    catch (const sdbusplus::exception_t& e)
    {
        trace::err("get MCTP instance exception");
        trace::err(e.what());
        return false;
    }

    return true;
}

} // namespace dbus
} // namespace util
