// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "usb-midi-source.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>

#include <ddktl/fidl.h>
#include <fbl/auto_lock.h>
#include <usb/usb-request.h>
#include <usb/usb.h>

#include "midi.h"

namespace audio {
namespace usb {

constexpr size_t READ_REQ_COUNT = 20;

void UsbMidiSource::ReadComplete(usb_request_t* req) {
  if (req->response.status == ZX_ERR_IO_NOT_PRESENT) {
    usb_request_release(req);
    return;
  }

  fbl::AutoLock lock(&mutex_);

  if (req->response.status == ZX_OK && req->response.actual > 0) {
    completed_reads_.push(UsbRequest(req, parent_req_size_));
    read_ready_.Signal();
  } else {
    usb_request_complete_callback_t complete = {
        .callback = [](void* ctx,
                       usb_request_t* req) { static_cast<UsbMidiSource*>(ctx)->ReadComplete(req); },
        .ctx = this,
    };
    usb_.RequestQueue(req, &complete);
  }
}

void UsbMidiSource::DdkUnbind(ddk::UnbindTxn txn) {
  if (binding_.has_value()) {
    Binding& binding = binding_.value();
    ZX_ASSERT(!binding.unbind_txn.has_value());
    binding.unbind_txn.emplace(std::move(txn));
    binding.binding.Unbind();
  } else {
    txn.Reply();
  }
}

void UsbMidiSource::DdkRelease() { delete this; }

void UsbMidiSource::OpenSession(OpenSessionRequestView request,
                                OpenSessionCompleter::Sync& completer) {
  if (binding_.has_value()) {
    request->session.Close(ZX_ERR_ALREADY_BOUND);
    return;
  }
  // queue up reads, including stale completed reads
  usb_request_complete_callback_t complete = {
      .callback = [](void* ctx,
                     usb_request_t* req) { static_cast<UsbMidiSource*>(ctx)->ReadComplete(req); },
      .ctx = this,
  };
  std::optional<UsbRequest> req;
  {
    fbl::AutoLock lock(&mutex_);
    while ((req = completed_reads_.pop()).has_value()) {
      usb_.RequestQueue(req->take(), &complete);
    }
    while ((req = free_read_reqs_.pop()).has_value()) {
      usb_.RequestQueue(req->take(), &complete);
    }
  }
  binding_ = Binding{
      .binding = fidl::BindServer(fdf::Dispatcher::GetCurrent()->async_dispatcher(),
                                  std::move(request->session), this,
                                  [](UsbMidiSource* self, fidl::UnbindInfo,
                                     fidl::ServerEnd<fuchsia_hardware_midi::Device>) {
                                    std::optional opt = std::exchange(self->binding_, {});
                                    ZX_ASSERT(opt.has_value());
                                    Binding& binding = opt.value();
                                    if (binding.unbind_txn.has_value()) {
                                      binding.unbind_txn.value().Reply();
                                    }
                                  }),
  };
}

zx_status_t UsbMidiSource::ReadInternal(void* data, size_t len, size_t* actual) {
  if (len < 3) {
    return ZX_ERR_BUFFER_TOO_SMALL;
  }

  fbl::AutoLock lock(&mutex_);

  // Block until read is ready.
  auto req = completed_reads_.pop();
  if (!req.has_value()) {
    read_ready_.Wait(&mutex_);

    req = completed_reads_.pop();
    ZX_ASSERT(req.has_value());
  }

  // MIDI events are 4 bytes. We can ignore the zeroth byte
  // TODO(https://fxbug.dev/42142118): Do something with this value.
  [[maybe_unused]] size_t not_sure_what_to_do_with_this = req->CopyFrom(data, 3, 1);
  *actual = get_midi_message_length(*(static_cast<uint8_t*>(data)));
  free_read_reqs_.push(std::move(*req));

  usb_request_complete_callback_t complete = {
      .callback = [](void* ctx,
                     usb_request_t* req) { static_cast<UsbMidiSource*>(ctx)->ReadComplete(req); },
      .ctx = this,
  };

  while ((req = free_read_reqs_.pop()).has_value()) {
    usb_.RequestQueue(req->take(), &complete);
  }

  return ZX_OK;
}

void UsbMidiSource::GetInfo(GetInfoCompleter::Sync& completer) {
  fuchsia_hardware_midi::wire::Info info = {
      .is_sink = false,
      .is_source = true,
  };
  completer.Reply(info);
}

void UsbMidiSource::Read(ReadCompleter::Sync& completer) {
  std::array<uint8_t, fuchsia_hardware_midi::wire::kReadSize> buffer;
  size_t actual = 0;
  auto status = ReadInternal(buffer.data(), buffer.size(), &actual);
  if (status == ZX_OK) {
    completer.ReplySuccess(fidl::VectorView<uint8_t>::FromExternal(buffer.data(), actual));
  } else {
    completer.ReplyError(status);
  }
}

void UsbMidiSource::Write(WriteRequestView request, WriteCompleter::Sync& completer) {
  completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}

zx_status_t UsbMidiSource::Create(zx_device_t* parent, const UsbDevice& usb, int index,
                                  const usb_interface_descriptor_t* intf,
                                  const usb_endpoint_descriptor_t* ep, const size_t req_size) {
  auto dev = std::make_unique<UsbMidiSource>(parent, usb, req_size);
  auto status = dev->Init(index, intf, ep);
  if (status != ZX_OK) {
    return status;
  }

  // devmgr is now in charge of the device.
  [[maybe_unused]] auto* _ = dev.release();
  return ZX_OK;
}

zx_status_t UsbMidiSource::Init(int index, const usb_interface_descriptor_t* intf,
                                const usb_endpoint_descriptor_t* ep) {
  int packet_size = usb_ep_max_packet(ep);
  if (intf->b_alternate_setting != 0) {
    usb_.SetInterface(intf->b_interface_number, intf->b_alternate_setting);
  }
  for (size_t i = 0; i < READ_REQ_COUNT; i++) {
    std::optional<UsbRequest> req;
    auto status = UsbRequest::Alloc(&req, packet_size, ep->b_endpoint_address, parent_req_size_);
    if (status != ZX_OK) {
      return status;
    }
    req->request()->header.length = packet_size;
    fbl::AutoLock al(&mutex_);
    free_read_reqs_.push(std::move(*req));
  }

  char name[ZX_DEVICE_NAME_MAX];
  snprintf(name, sizeof(name), "usb-midi-source-%d", index);

  return DdkAdd(name);
}

}  // namespace usb
}  // namespace audio
