#include "gpio_presence.hpp"

#include "xyz/openbmc_project/Common/error.hpp"

#include <fcntl.h>
#include <libevdev/libevdev.h>

#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/lg2.hpp>

#include <fstream>

namespace phosphor
{
namespace gpio
{
namespace presence
{

using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;

constexpr auto INVENTORY_PATH = "/xyz/openbmc_project/inventory";
constexpr auto INVENTORY_INTF = "xyz.openbmc_project.Inventory.Manager";

constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";

std::string getService(const std::string& path, const std::string& interface,
                       sdbusplus::bus_t& bus)
{
    auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
                                          MAPPER_INTERFACE, "GetObject");

    mapperCall.append(path);
    mapperCall.append(std::vector<std::string>({interface}));

    std::map<std::string, std::vector<std::string>> mapperResponse;
    try
    {
        auto mapperResponseMsg = bus.call(mapperCall);
        mapperResponseMsg.read(mapperResponse);
    }
    catch (const sdbusplus::exception_t& e)
    {
        lg2::error(
            "Error in mapper call to get service name, path: {PATH}, interface: {INTERFACE}, error: {ERROR}",
            "PATH", path, "INTERFACE", interface, "ERROR", e);
        elog<InternalFailure>();
    }

    return mapperResponse.begin()->first;
}

void Presence::determinePresence()
{
    auto present = false;
    auto value = static_cast<int>(0);
    auto fetch_rc =
        libevdev_fetch_event_value(devicePtr.get(), EV_KEY, key, &value);
    if (0 == fetch_rc)
    {
        lg2::error("Device does not support event type, key: {KEYCODE}",
                   "KEYCODE", key);
        elog<InternalFailure>();
        return;
    }
    if (value > 0)
    {
        present = true;
    }

    updateInventory(present);
}

// Callback handler when there is an activity on the FD
int Presence::processEvents(sd_event_source*, int, uint32_t, void* userData)
{
    auto presence = static_cast<Presence*>(userData);

    presence->analyzeEvent();
    return 0;
}

// Analyzes the GPIO event
void Presence::analyzeEvent()
{
    // Data returned
    struct input_event ev{};
    int rc = 0;

    // While testing, observed that not having a loop here was leading
    // into events being missed.
    while (rc >= 0)
    {
        // Wait until no more events are available on the device.
        rc = libevdev_next_event(devicePtr.get(), LIBEVDEV_READ_FLAG_NORMAL,
                                 &ev);
        if (rc < 0)
        {
            // There was an error waiting for events, mostly that there are no
            // events to be read.. So continue waiting...
            return;
        }

        if (rc == LIBEVDEV_READ_STATUS_SUCCESS)
        {
            if (ev.type == EV_SYN && ev.code == SYN_REPORT)
            {
                continue;
            }
            else if (ev.code == key)
            {
                auto present = false;
                if (ev.value > 0)
                {
                    present = true;
                    std::this_thread::sleep_for(
                        std::chrono::milliseconds(delay));
                    bindOrUnbindDrivers(present);
                    updateInventory(present);
                }
                else
                {
                    updateInventory(present);
                    bindOrUnbindDrivers(present);
                }
            }
        }
    }

    return;
}

Presence::ObjectMap Presence::getObjectMap(bool present)
{
    ObjectMap invObj;
    InterfaceMap invIntf;
    PropertyMap invProp;

    invProp.emplace("Present", present);
    invProp.emplace("PrettyName", name);
    invIntf.emplace("xyz.openbmc_project.Inventory.Item", std::move(invProp));
    // Add any extra interfaces we want to associate with the inventory item
    for (auto& iface : ifaces)
    {
        invIntf.emplace(iface, PropertyMap());
    }
    invObj.emplace(std::move(inventory), std::move(invIntf));

    return invObj;
}

void Presence::updateInventory(bool present)
{
    ObjectMap invObj = getObjectMap(present);

    lg2::info(
        "Updating inventory present property value to {PRESENT}, path: {PATH}",
        "PRESENT", present, "PATH", inventory);

    auto invService = getService(INVENTORY_PATH, INVENTORY_INTF, bus);

    // Update inventory
    auto invMsg = bus.new_method_call(invService.c_str(), INVENTORY_PATH,
                                      INVENTORY_INTF, "Notify");
    invMsg.append(std::move(invObj));
    try
    {
        auto invMgrResponseMsg = bus.call(invMsg);
    }
    catch (const sdbusplus::exception_t& e)
    {
        lg2::error(
            "Error in inventory manager call to update inventory: {ERROR}",
            "ERROR", e);
        elog<InternalFailure>();
    }
}

void Presence::bindOrUnbindDrivers(bool present)
{
    auto action = (present) ? "bind" : "unbind";

    for (auto& driver : drivers)
    {
        auto path = std::get<pathField>(driver) / action;
        auto device = std::get<deviceField>(driver);

        if (present)
        {
            lg2::info("Binding a {DEVICE} driver: {PATH}", "DEVICE", device,
                      "PATH", path);
        }
        else
        {
            lg2::info("Unbinding a {DEVICE} driver: {PATH}", "DEVICE", device,
                      "PATH", path);
        }

        std::ofstream file;

        file.exceptions(std::ofstream::failbit | std::ofstream::badbit |
                        std::ofstream::eofbit);

        try
        {
            file.open(path);
            file << device;
            file.close();
        }
        catch (const std::exception& e)
        {
            lg2::error(
                "Failed binding or unbinding a {DEVICE} after a card was removed or added, path: {PATH}, error: {ERROR}",
                "DEVICE", device, "PATH", path, "ERROR", e);
        }
    }
}

} // namespace presence
} // namespace gpio
} // namespace phosphor
