#include "motors/usb/hid.h"

namespace frc971 {
namespace teensy {
namespace {

constexpr uint8_t hid_class() { return 0x03; }

namespace hid_class_requests {
constexpr uint8_t get_report() { return 0x01; }
constexpr uint8_t get_idle() { return 0x02; }
constexpr uint8_t get_protocol() { return 0x03; }
constexpr uint8_t set_report() { return 0x09; }
constexpr uint8_t set_idle() { return 0x0a; }
constexpr uint8_t set_protcol() { return 0x0b; }
}  // namespace hid_class_requests

}  // namespace

void HidFunction::Initialize() {
  interface_ = AddInterface();
  in_endpoint_ = AddEndpoint();

  CreateIadDescriptor(
      /*first_interface=*/interface_,
      /*interface_count=*/1,
      /*function_class=*/hid_class(),
      /*function_subclass=*/0,
      /*function_protocol=*/0, "HidIad");

  {
    const auto interface_descriptor = CreateDescriptor(
        interface_descriptor_length(), UsbDescriptorType::kInterface);
    interface_descriptor->AddByte(interface_);   // bInterfaceNumber
    interface_descriptor->AddByte(0);            // bAlternateSetting
    interface_descriptor->AddByte(1);            // bNumEndpoints
    interface_descriptor->AddByte(hid_class());  // bInterfaceClass
    interface_descriptor->AddByte(0);            // bInterfaceSubClass
    interface_descriptor->AddByte(0);            // bInterfaceProtocol
    interface_descriptor->AddByte(device()->AddString("Hid"));  // iInterface
  }

  {
    const auto hid_descriptor = hid_descriptor_list_.CreateDescriptor(
        9, UsbClassDescriptorType::kHidHid);
    hid_descriptor->AddUint16(0x0110);  // bcdHID
    hid_descriptor->AddByte(0);         // bCountryCode
    hid_descriptor->AddByte(1);         // bNumDescriptors
    hid_descriptor->AddByte(static_cast<uint8_t>(
        UsbClassDescriptorType::kHidReport));              // bDescriptorType
    hid_descriptor->AddUint16(report_descriptor_.size());  // wDescriptorLength
  }
  AddPremadeDescriptor(hid_descriptor_list_);

  {
    const auto endpoint_descriptor = CreateDescriptor(
        endpoint_descriptor_length(), UsbDescriptorType::kEndpoint);
    endpoint_descriptor->AddByte(in_endpoint_ |
                                 m_endpoint_address_in());  // bEndpointAddress
    endpoint_descriptor->AddByte(
        m_endpoint_attributes_interrupt());                  // bmAttributes
    endpoint_descriptor->AddUint16(in_endpoint_max_size());  // wMaxPacketSize
    endpoint_descriptor->AddByte(0x8);                       // bInterval
  }
}

UsbFunction::SetupResponse HidFunction::HandleEndpoint0SetupPacket(
    const UsbDevice::SetupPacket &setup_packet) {
  if (G_SETUP_REQUEST_TYPE_TYPE(setup_packet.request_type) !=
      SetupRequestType::kClass) {
    return SetupResponse::kIgnored;
  }
  if (G_SETUP_REQUEST_TYPE_RECIPIENT(setup_packet.request_type) !=
      standard_setup_recipients::kInterface) {
    return SetupResponse::kIgnored;
  }
  if (setup_packet.index != interface_) {
    return SetupResponse::kIgnored;
  }
  const bool in = setup_packet.request_type & M_SETUP_REQUEST_TYPE_IN;
  switch (setup_packet.request) {
    case hid_class_requests::get_report():
      if (!in) {
        return SetupResponse::kStall;
      }
      // If it's not requesting the only Input report, no idea what the host
      // wants so stall.
      if (setup_packet.value != 0x0100) {
        return SetupResponse::kStall;
      }
      {
        DisableInterrupts disable_interrupts;
        memcpy(get_report_response_buffer_.data(),
               report_tx_buffer_being_sent(disable_interrupts), kMaxReportSize);
      }
      device()->QueueEndpoint0Data(
          reinterpret_cast<const char *>(get_report_response_buffer_.data()),
          ::std::min<uint16_t>(setup_packet.length, report_max_size_));
      return SetupResponse::kHandled;

    case hid_class_requests::set_idle():
      // Minimum implementation to make the host stack happy.
      if (in) {
        return SetupResponse::kStall;
      }
      device()->SendEmptyEndpoint0Packet();
      return SetupResponse::kHandled;

      // TODO(Brian): Should we actually implement the idle stuff?

    default:
      return SetupResponse::kStall;
  }
}

UsbFunction::SetupResponse HidFunction::HandleGetDescriptor(
    const UsbDevice::SetupPacket &setup_packet) {
  const uint8_t recipient =
      G_SETUP_REQUEST_TYPE_RECIPIENT(setup_packet.request_type);
  if (recipient != standard_setup_recipients::kInterface) {
    return SetupResponse::kIgnored;
  }

  const uint8_t descriptor_type = (setup_packet.value >> 8) & 0xFF;
  if (G_DESCRIPTOR_TYPE_TYPE(descriptor_type) !=
      standard_descriptor_type_types::kClass) {
    return SetupResponse::kIgnored;
  }
  if (setup_packet.index != interface_) {
    return SetupResponse::kIgnored;
  }

  const uint8_t descriptor_index = setup_packet.value & 0xFF;
  switch (descriptor_type) {
    case static_cast<uint8_t>(UsbClassDescriptorType::kHidHid):
      if (descriptor_index != 0) {
        return SetupResponse::kStall;
      }
      device()->QueueEndpoint0Data(
          hid_descriptor_list_.GetData(),
          ::std::min<int>(setup_packet.length,
                          hid_descriptor_list_.CurrentSize()));
      return SetupResponse::kHandled;

    case static_cast<uint8_t>(UsbClassDescriptorType::kHidReport):
      if (descriptor_index != 0) {
        return SetupResponse::kStall;
      }
      device()->QueueEndpoint0Data(
          report_descriptor_.data(),
          ::std::min<int>(setup_packet.length, report_descriptor_.size()));
      return SetupResponse::kHandled;

    case static_cast<uint8_t>(UsbClassDescriptorType::kHidPhysical):
      static constexpr char kNoPhysicalDescriptors[] = {0, 0, 0};
      device()->QueueEndpoint0Data(
          kNoPhysicalDescriptors,
          ::std::min<int>(setup_packet.length, sizeof(kNoPhysicalDescriptors)));
      return SetupResponse::kHandled;
  }
  return SetupResponse::kStall;
}

void HidFunction::HandleInFinished(int endpoint, BdtEntry * /*bdt_entry*/,
                                   EvenOdd odd) {
  if (endpoint == in_endpoint_) {
    DisableInterrupts disable_interrupts;
    if (odd != BufferStateToEmpty(tx_state_)) {
      __builtin_trap();
    }

    // Copy the current one into the just-sent buffer.
    memcpy(report_tx_buffer_being_sent(disable_interrupts),
           report_tx_buffer_to_fill(disable_interrupts), kMaxReportSize);

    dma_memory_barrier();
    device()->SetBdtEntry(
        in_endpoint_, Direction::kTx, BufferStateToFill(tx_state_),
        {M_USB_BD_OWN | M_USB_BD_DTS | V_USB_BD_BC(report_max_size_) |
             static_cast<uint32_t>(next_tx_toggle_),
         report_tx_buffer_to_fill(disable_interrupts)});

    // Advance the state to indicate we've swapped buffers.
    tx_state_ = BufferStateAfterFill(BufferStateAfterEmpty(tx_state_));
    next_tx_toggle_ = Data01Inverse(next_tx_toggle_);
  }
}

void HidFunction::HandleConfigured(int endpoint) {
  if (endpoint == in_endpoint_) {
    device()->ConfigureEndpointFor(in_endpoint_, false, true, true);
    DisableInterrupts disable_interrupts;
    next_tx_toggle_ = Data01::kData0;

    EvenOdd to_fill;
    if (BufferStateHasFull(tx_state_)) {
      to_fill = BufferStateToEmpty(tx_state_);
    } else {
      to_fill = BufferStateToFill(tx_state_);
      tx_state_ = BufferStateAfterFill(tx_state_);
    }

    dma_memory_barrier();
    device()->SetBdtEntry(
        in_endpoint_, Direction::kTx, to_fill,
        {M_USB_BD_OWN | M_USB_BD_DTS | V_USB_BD_BC(report_max_size_) |
             static_cast<uint32_t>(next_tx_toggle_),
         report_tx_buffer_to_fill(disable_interrupts)});
    next_tx_toggle_ = Data01Inverse(next_tx_toggle_);
  }
}

}  // namespace teensy
}  // namespace frc971
