// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "message_hoth_usb.hpp"

#include <stdplus/util/cexec.hpp>

#include <charconv>
#include <format>
#include <stdexcept>

// NOLINTNEXTLINE(cert-dcl58-cpp)
namespace google
{
namespace hoth
{
// Helper function to throw exceptions on returning system errors
int toErrno(int error)
{
    switch (error)
    {
        case LIBUSB_SUCCESS:
            return 0;
        case LIBUSB_ERROR_IO:
            return EIO;
        case LIBUSB_ERROR_INVALID_PARAM:
            return EINVAL;
        case LIBUSB_ERROR_ACCESS:
            return EACCES;
        case LIBUSB_ERROR_NO_DEVICE:
            return ENODEV;
        case LIBUSB_ERROR_NOT_FOUND:
            return ENOENT;
        case LIBUSB_ERROR_BUSY:
            return EBUSY;
        case LIBUSB_ERROR_TIMEOUT:
            return ETIMEDOUT;
        case LIBUSB_ERROR_OVERFLOW:
            return EOVERFLOW;
        case LIBUSB_ERROR_PIPE:
            return EPIPE;
        case LIBUSB_ERROR_INTERRUPTED:
            return EINTR;
        case LIBUSB_ERROR_NO_MEM:
            return ENOMEM;
        case LIBUSB_ERROR_NOT_SUPPORTED:
            return ENOTSUP;
        default:
            return ENOSYS;
    }
}

inline auto makeError(int error, const char* msg)
{
    return std::system_error(toErrno(-error), std::generic_category(), msg);
}

template <typename... Args>
inline auto callCheck(const char* msg, Args&&... args)
{
    return stdplus::util::callCheckRet<makeError, Args...>(
        msg, std::forward<Args>(args)...);
}

class TimeOut : public std::runtime_error
{
  public:
    explicit TimeOut(const std::string &msg) : runtime_error(msg) {}
};

// Helper function to throw exceptions on returning libhoth_usb errors.
template <class F, class... T>
void callThrow(F f, T... args)
{
    auto ret = f(std::forward<T>(args)...);
    switch (ret)
    {
        case LIBHOTH_OK:
            return;
        case LIBHOTH_ERR_UNKNOWN_VENDOR:
            throw std::runtime_error("hothusb error: unknown vendor");
        case LIBHOTH_ERR_INTERFACE_NOT_FOUND:
            throw std::runtime_error("hothusb error: interface not found");
        case LIBHOTH_ERR_MALLOC_FAILED:
            throw std::runtime_error("hothusb error: malloc failed");
        case LIBUSB_ERROR_TIMEOUT:
            throw TimeOut("hothusb error: timeout");
        case LIBHOTH_ERR_OUT_UNDERFLOW:
            throw std::runtime_error("hothusb error: out underflow");
        case LIBUSB_ERROR_OVERFLOW:
            throw std::runtime_error("hothusb error: in overflow");
        case LIBHOTH_ERR_UNSUPPORTED_VERSION:
            throw std::runtime_error("hothusb error: unsupported version");
        case LIBUSB_ERROR_BUSY:
        case LIBHOTH_ERR_INTERFACE_BUSY:
            throw std::runtime_error(
                "hothusb error: interface already claimed");
        default:
            throw std::runtime_error(
                std::format("hothusb error: unknown ({})", ret));
    }
}

// RAII wrapper around USB claim.
// Claim on initialization.
// Release on destruction.
class USBClaim
{
  public:
    explicit USBClaim(LibHothUsbIntf* usb, libhoth_device* device)
    {
        callThrow([usb, device] { return usb->claim(device); });
        usb_ = usb;
        device_ = device;
    }

    USBClaim(const USBClaim&) = delete;
    USBClaim& operator=(const USBClaim&) = delete;
    USBClaim(USBClaim&&) = delete;
    USBClaim& operator=(USBClaim&&) = delete;

    ~USBClaim()
    {
        usb_->release(device_);
    }

  private:
    LibHothUsbIntf* usb_ = nullptr;
    libhoth_device* device_ = nullptr;
};

// Helper function to parse USB id.
// The function will extract the numbers into Int type until the first
// `separator` and truncate. For example:
//      extract_separated_int<int>(str = "123.456")
//          -> return = (int)123, str = "456"
template <typename Int>
Int extract_separated_int(std::string_view& str, char separator)
{
    if (str.empty())
    {
        throw std::invalid_argument("Int str is empty");
    }

    Int ret;
    auto term = str.substr(0, str.find(separator));
    const auto* end = term.data() + term.size();
    auto res = std::from_chars(term.data(), end, ret);
    if (res.ec != std::errc() || res.ptr != end)
    {
        throw std::invalid_argument("Failed to parse int");
    }
    str.remove_prefix(term.size() + (term.size() == str.size() ? 0 : 1));
    return ret;
}

// helper function to find usb device from usb id.
libusb_device* find_dev(LibusbIntf* libusb, libusb_context* ctx,
                        std::string_view usb_id)
{
    if (libusb == nullptr)
    {
        throw std::runtime_error("libusb is nullptr");
    }
    auto bus_id = extract_separated_int<uint8_t>(usb_id, '-');
    std::vector<uint8_t> port_ids;
    do
    {
        port_ids.push_back(extract_separated_int<uint8_t>(usb_id, '.'));
    } while (!usb_id.empty());

    libusb_device** devices;
    auto dev_count = callCheck("get_device_list", &LibusbIntf::get_device_list,
                               libusb, ctx, &devices);

    for (int count = 0; count < dev_count; count++)
    {
        libusb_device* dev = devices[count];
        if (bus_id == libusb->get_bus_number(dev))
        {
            // As per the USB 3.0 specs, the current maximum limit for the depth
            // is 7
            uint8_t port_numbers[7];
            size_t r = 0;
            try
            {
                r = callCheck("get_port_numbers", &LibusbIntf::get_port_numbers,
                              libusb, dev, port_numbers, sizeof(port_numbers));
            }
            catch (const std::exception& e)
            {
                libusb->free_device_list(devices, 0);
                throw;
            }
            if (r != port_ids.size())
            {
                continue;
            }
            unsigned i = 0;
            for (; i < r; i++)
            {
                if (port_numbers[i] != port_ids[i])
                {
                    break;
                }
            }
            if (i == r)
            {
                libusb->ref_device(dev);
                libusb->free_device_list(devices, 1);
                return dev;
            }
        }
    }
    libusb->free_device_list(devices, 1);
    throw std::runtime_error("Failed to find usb device");
    return nullptr;
}

MessageHothUSB::MessageHothUSB(std::string_view usb_id, LibusbIntf* libusb,
                               LibHothUsbIntf* libhoth_usb) :
    libusb_(libusb),
    ctx_([this]() {
        libusb_context* context;
        libusb_->init(&context);
        return context;
    }()),
    dev_([this](std::string_view usb_id) {
        libusb_device* device = nullptr;
        try
        {
            device = find_dev(libusb_, ctx_, usb_id);
        }
        catch (const std::exception& e)
        {
            libusb_->exit(ctx_);
            throw e;
        }

        return device;
    }(usb_id)),
    libhoth_usb_(libhoth_usb), hoth_dev_([this]() {
        libhoth_device* dev;
        struct timespec monotonic_time;
        if (clock_gettime(CLOCK_MONOTONIC, &monotonic_time) != 0) {
            throw std::runtime_error("clock_gettime failed");
        }
        uint32_t prng_seed =
            monotonic_time.tv_sec ^ monotonic_time.tv_nsec ^ getpid();
        libhoth_usb_device_init_options option{dev_, ctx_, prng_seed};

        try
        {
            callThrow(
                [this, option = &option, dev = &dev] { return libhoth_usb_->open(option, dev); });

            // Don't indefinitely hold the USB interface.
            libhoth_usb_->release(dev);
        }
        catch (const std::exception& e)
        {
            libusb_->unref_device(dev_);
            libusb_->exit(ctx_);

            // If we failed to open the device, then this class can't
            // meaningfully use it. Let the caller decide what to do.
            throw;
        }

        return dev;
    }())
{}

MessageHothUSB::MessageHothUSB(MessageHothUSB &&other) noexcept
    : libusb_(nullptr), ctx_(nullptr), dev_(nullptr), libhoth_usb_(nullptr),
      hoth_dev_(nullptr)
{
    this->swap(other);
}

MessageHothUSB &MessageHothUSB::operator=(MessageHothUSB &&other) noexcept
{
    MessageHothUSB temp(std::move(other));
    this->swap(temp);
    return *this;
}

MessageHothUSB::~MessageHothUSB()
{
    if (libhoth_usb_ && hoth_dev_)
    {
        libhoth_usb_->close(hoth_dev_);
    }
    if (libusb_ && dev_)
    {
        libusb_->unref_device(dev_);
    }
    if (libusb_ && ctx_)
    {
        libusb_->exit(ctx_);
    }
}

void MessageHothUSB::send(const uint8_t* buf, size_t size,
                          [[maybe_unused]] size_t seek)
{
    USBClaim usb_claim(libhoth_usb_, hoth_dev_);

    callThrow(
        [this, buf, size] { return libhoth_usb_->send(hoth_dev_, buf, size); });

    // libhoth_usb read/write is non addressible, we need to buffer the
    // response.
    buff_.resize(kMailboxSize);
    size_t read = 0;

    // Try infinitly on timeout.
    while (true)
    {
        try
        {
            callThrow([this, data = buff_.data(), read = &read] { return libhoth_usb_->recv(hoth_dev_, data, kMailboxSize, read, timeout); });
            break;
        }
        catch (const TimeOut& e)
        {
            // continue on timeout.
            continue;
        }
    }
    buff_.resize(read);
}

void MessageHothUSB::recv(uint8_t* buf, size_t size, size_t seek)
{
    if (size + seek > kMailboxSize)
    {
        throw std::runtime_error("Memory out of boundary");
    }

    memcpy(buf, buff_.data() + seek, size);
}

} // namespace hoth
} // namespace google
