#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";
        }

        // If the system is powering off for any reason (ex. we hit a PHYP TI
        // in the graceful power off path), then we want to call the immediate
        // power off target
        if (hostRunningState() == HostRunningState::Stopping)
        {
            trace::inf("system is powering off so no dump will be requested");
            target = "obmc-chassis-hard-poweroff@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;
            }
        }
    }

    // See if host in process of powering off when we get NotStarted
    if (host == HostRunningState::NotStarted)
    {
        constexpr auto hostStateInterface = "xyz.openbmc_project.State.Host";
        if (0 == find(hostStateInterface, path, service))
        {
            DBusValue value;

            // current host state is implemented as a property
            constexpr auto stateProperty = "CurrentHostState";

            if (0 == getProperty(hostStateInterface, path, service,
                                 stateProperty, value))
            {
                // return value is a variant, host state is in the vector of
                // strings
                std::string hostState(std::get<std::string>(value));
                if (hostState == "xyz.openbmc_project.State.Host.HostState."
                                 "TransitioningToOff")
                {
                    host = HostRunningState::Stopping;
                }
            }
        }
    }

    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;
}

/** @brief Determine if power fault was detected */
bool powerFault()
{
    // power fault based on pgood property
    int32_t pgood = 0; // assume fault or unknown

    constexpr auto interface = "org.openbmc.control.Power";

    DBusService service;
    DBusPath path;

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

        // chassis pgood is implemented as a property
        constexpr auto property = "pgood";

        if (0 == getProperty(interface, path, service, property, value))
        {
            // return value is a variant, int32 == 1 for pgood OK
            pgood = std::get<int32_t>(value);
        }
    }

    return pgood != 1 ? true : false; // if not pgood then power fault
}

} // namespace dbus
} // namespace util
