// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright OpenBMC Authors

#include "gpio.hpp"

#include "utilities.hpp"

#include <cstring>
#include <filesystem>
#include <format>
#include <iostream>
#include <unordered_map>

static std::unordered_map<std::string, gpiod::line> io;
using namespace std::chrono_literals;

namespace gpio
{

void set(const char* line_name, int value,
         std::chrono::milliseconds find_timeout)
{
    std::cerr << std::format("{} Request to set to {}\n", line_name, value);
    std::chrono::milliseconds polling_time = 10ms;
    gpiod::line& line = io[line_name];
    if (!line)
    {
        do
        {
            line = gpiod::find_line(line_name);
            if (!line)
            {
                std::cerr << std::format(
                    "{} not found yet, waiting and retrying\n", line_name);

                sleep_milliseconds(polling_time);
                find_timeout -= polling_time;
            }
        } while (!line && find_timeout > 0s);
        if (!line && find_timeout <= 0s)
        {
            std::cerr << std::format("{} Unable to find\n", line_name);
            return;
        }
        try
        {
            line.request({app_name, gpiod::line_request::DIRECTION_OUTPUT, 0},
                         value);
        }
        catch (const std::system_error& e)
        {
            std::cerr << std::format(
                "{} unable to set direction and value {}\n", line_name,
                e.what());
            return;
        }
        // No need to set if the init did it for us
        std::cerr << std::format("{} Set to {}\n", line_name, value);
        return;
    }
    std::cerr << std::format("{} Settingto {}\n", line_name, value);
    line.set_value(value);
}

int get(const char* line_name)
{
    std::cerr << std::format("{} Request to get\n", line_name);

    gpiod::line line = gpiod::find_line(line_name);
    if (!line)
    {
        std::cerr << std::format("{} Set unable to find\n", line_name);
        return -1;
    }
    try
    {
        line.request({app_name, gpiod::line_request::DIRECTION_INPUT, 0});
    }
    catch (const std::system_error& e)
    {
        std::cerr << std::format("{} unable to set {}\n", line_name, e.what());
    }

    int value = line.get_value();
    std::cerr << std::format("{} was {}\n", line_name, value);
    return value;
}

Event::Event(const char* line_name_in, int value_in) :
    line_name(line_name_in), value(value_in)
{
    line = gpiod::find_line(line_name);
    if (!line)
    {
        std::cerr << std::format("{} GpioEvent: Unable to find\n", line_name);
        return;
    }
    int edge = (value != 0) ? ::gpiod::line_request::EVENT_RISING_EDGE
                            : ::gpiod::line_request::EVENT_FALLING_EDGE;

    line.request({app_name, edge, 0});

    int val = line.get_value();
    if (val == value)
    {
        std::cerr << std::format("{} GpioEvent is already {}\n", line_name,
                                 val);
    }
    else
    {
        std::cerr << std::format("GpioEvent created for {}\n", line_name);
    }
}

EventResult Event::wait()
{
    if (!line)
    {
        std::cerr << std::format("Line {} wasn't initialized\n", line_name);
        return EventResult::Error;
    }
    std::cerr << std::format("{}  Waiting to go to {}\n", line_name,
                             (value != 0) ? "assert" : "deassert");
    auto events = line.event_wait(std::chrono::seconds(120));
    if (!events)
    {
        std::cerr << std::format("{} Timeout\n", line_name);
        return EventResult::Timeout;
    }

    std::cerr << std::format("{} Asserted\n", line_name);

    return EventResult::Asserted;
}

void set_raw(unsigned int chip_num, unsigned int bit_num, int value)
{
    std::string syspath = std::format("gpiochip{}", chip_num);
    std::cerr << std::format("Setting gpiochip{} bit {} to {}\n", chip_num,
                             bit_num, value);
    try
    {
        gpiod::chip chip(syspath);
        gpiod::line line = chip.get_line(bit_num);
        line.request({app_name, gpiod::line_request::DIRECTION_OUTPUT, 0},
                     value);
        std::cerr << std::format("gpiochip{} bit {} set to {}\n", chip_num,
                                 bit_num, value);
    }
    catch (const std::system_error& e)
    {
        std::cerr << std::format("Error setting gpiochip{} bit {}: {}\n",
                                 chip_num, bit_num, e.what());
    }
}

int find_chip_idx_from_dir(std::string_view device_path)
{
    std::string gpio_chip;
    for (const auto& entry : std::filesystem::directory_iterator(device_path))
    {
        std::string path = entry.path().string();
        if (path.find("gpiochip") != std::string::npos)
        {
            gpio_chip =
                path.substr(path.find("gpiochip") + std::strlen("gpiochip"));
            break;
        }
    }
    if (gpio_chip.empty())
    {
        std::cerr << "Error: Could not find GPIO chip number\n";
        return -ENOENT;
    }

    std::cerr << "Found GPIO chip: gpiochip" << gpio_chip << "\n";
    unsigned int gpiochipint = 0;
    std::from_chars_result r =
        std::from_chars(&*gpio_chip.begin(), &*gpio_chip.end(), gpiochipint);
    if (r.ec != std::error_code() || r.ptr != &*gpio_chip.end())
    {
        std::cout << "Failed to convert gpiochip\n";
        return -EINVAL;
    }
    return gpiochipint;
}
} // namespace gpio
