// 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 "usb_util.hpp"

#include <algorithm>
#include <charconv>
#include <span>
#include <stdexcept>

namespace google
{
namespace hoth
{
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;
}

libusb::Device find_dev(libusb::Context& ctx, std::string_view usb_id)
{
    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());

    for (auto& dev : ctx.get_device_list())
    {
        if (bus_id == dev.get_bus_number() &&
            dev.get_port_numbers() == port_ids)
        {
            return std::move(dev);
        }
    }

    throw std::runtime_error("Failed to find usb device");
}

const libusb_interface_descriptor& find_intf(
    libusb::Device& dev, uint8_t usbClass,
    std::span<const uint8_t> usbSubclasses, uint8_t usbProtocol)
{
    const auto& config = dev.get_active_config_descriptor();
    for (uint8_t i = 0; i < config.bNumInterfaces; ++i)
    {
        const auto& interface = config.interface[i];
        for (int j = 0; j < interface.num_altsetting; ++j)
        {
            const auto& setting = interface.altsetting[j];
            if (setting.bInterfaceClass == usbClass &&
                (std::count(usbSubclasses.begin(), usbSubclasses.end(),
                            setting.bInterfaceSubClass) > 0) &&
                setting.bInterfaceProtocol == usbProtocol)
            {
                return setting;
            }
        }
    }

    throw std::runtime_error("Failed to find hoth mailbox interface");
}

const libusb_endpoint_descriptor& find_ep(
    const libusb_interface_descriptor& interface, uint8_t dir)
{
    for (uint8_t i = 0; i < interface.bNumEndpoints; ++i)
    {
        const auto& endpoint = interface.endpoint[i];
        if ((endpoint.bmAttributes & libusb::kTransferTypeBits) ==
                LIBUSB_TRANSFER_TYPE_BULK &&
            (endpoint.bEndpointAddress & libusb::kAddressDirectionBits) == dir)
        {
            return endpoint;
        }
    }

    throw std::runtime_error("Failed to find hoth transfer endpoint");
}

} // namespace hoth

} // namespace google
