// Copyright 2014 The Chromium 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 "media/midi/midi_manager_usb.h"

#include <memory>
#include <utility>

#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "media/midi/midi_service.h"
#include "media/midi/task_service.h"
#include "media/midi/usb_midi_descriptor_parser.h"

namespace midi {

using mojom::PortState;
using mojom::Result;

MidiManagerUsb::MidiManagerUsb(MidiService* service,
                               std::unique_ptr<UsbMidiDevice::Factory> factory)
    : MidiManager(service), device_factory_(std::move(factory)) {}

MidiManagerUsb::~MidiManagerUsb() {
  // TODO(toyoshim): Remove following DCHECKs once the dynamic instantiation
  // mode is enabled by default.
  base::AutoLock lock(lock_);
  DCHECK(initialize_callback_.is_null());
  DCHECK(device_factory_);
  DCHECK(devices_.empty());
  DCHECK(output_streams_.empty());
  DCHECK(!input_stream_);
  DCHECK(input_jack_dictionary_.empty());
}

void MidiManagerUsb::StartInitialization() {
  bool result = service()->task_service()->BindInstance();
  DCHECK(result);

  Initialize(base::BindOnce(&MidiManager::CompleteInitialization,
                            base::Unretained(this)));
}

void MidiManagerUsb::Finalize() {
  bool result = service()->task_service()->UnbindInstance();
  DCHECK(result);

  // TODO(toyoshim): Remove following code once the dynamic instantiation mode
  // is enabled by default.
  base::AutoLock lock(lock_);
  initialize_callback_ = Callback();
  devices_.clear();
  output_streams_.clear();
  input_stream_.reset();
  input_jack_dictionary_.clear();

  // Do not reset |device_factory_| here because it is set on the thread on
  // which the constructor runs.
}

void MidiManagerUsb::Initialize(Callback callback) {
  initialize_callback_ = std::move(callback);

  // This is safe because EnumerateDevices cancels the operation on destruction.
  device_factory_->EnumerateDevices(
      this, base::BindOnce(&MidiManagerUsb::OnEnumerateDevicesDone,
                           base::Unretained(this)));
}

void MidiManagerUsb::DispatchSendMidiData(MidiManagerClient* client,
                                          uint32_t port_index,
                                          const std::vector<uint8_t>& data,
                                          base::TimeTicks timestamp) {
  if (port_index >= output_streams_.size()) {
    // |port_index| is provided by a renderer so we can't believe that it is
    // in the valid range.
    return;
  }
  base::TimeDelta delay = MidiService::TimestampToTimeDeltaDelay(timestamp);

  // output_streams_[port_index] is alive unless MidiManagerUsb is deleted.
  service()->task_service()->PostBoundDelayedTask(
      TaskService::kDefaultRunnerId,
      base::BindOnce(&UsbMidiOutputStream::Send,
                     base::Unretained(output_streams_[port_index].get()), data),
      delay);
  service()->task_service()->PostBoundDelayedTask(
      TaskService::kDefaultRunnerId,
      base::BindOnce(&MidiManager::AccumulateMidiBytesSent,
                     base::Unretained(this), client, data.size()),
      delay);
}

void MidiManagerUsb::ReceiveUsbMidiData(UsbMidiDevice* device,
                                        int endpoint_number,
                                        const uint8_t* data,
                                        size_t size,
                                        base::TimeTicks time) {
  if (!input_stream_)
    return;
  input_stream_->OnReceivedData(device,
                                endpoint_number,
                                data,
                                size,
                                time);
}

void MidiManagerUsb::OnDeviceAttached(std::unique_ptr<UsbMidiDevice> device) {
  int device_id = static_cast<int>(devices_.size());
  devices_.push_back(std::move(device));
  AddPorts(devices_.back().get(), device_id);
}

void MidiManagerUsb::OnDeviceDetached(size_t index) {
  if (index >= devices_.size()) {
    return;
  }
  UsbMidiDevice* device = devices_[index].get();
  for (size_t i = 0; i < output_streams_.size(); ++i) {
    if (output_streams_[i]->jack().device == device) {
      SetOutputPortState(static_cast<uint32_t>(i), PortState::DISCONNECTED);
    }
  }
  const std::vector<UsbMidiJack>& input_jacks = input_stream_->jacks();
  for (size_t i = 0; i < input_jacks.size(); ++i) {
    if (input_jacks[i].device == device) {
      SetInputPortState(static_cast<uint32_t>(i), PortState::DISCONNECTED);
    }
  }
}

void MidiManagerUsb::OnReceivedData(size_t jack_index,
                                    const uint8_t* data,
                                    size_t size,
                                    base::TimeTicks time) {
  ReceiveMidiData(static_cast<uint32_t>(jack_index), data, size, time);
}


void MidiManagerUsb::OnEnumerateDevicesDone(bool result,
                                            UsbMidiDevice::Devices* devices) {
  if (!result) {
    std::move(initialize_callback_).Run(Result::INITIALIZATION_ERROR);
    return;
  }
  input_stream_.reset(new UsbMidiInputStream(this));
  devices->swap(devices_);
  for (size_t i = 0; i < devices_.size(); ++i) {
    if (!AddPorts(devices_[i].get(), static_cast<int>(i))) {
      std::move(initialize_callback_).Run(Result::INITIALIZATION_ERROR);
      return;
    }
  }
  std::move(initialize_callback_).Run(Result::OK);
}

bool MidiManagerUsb::AddPorts(UsbMidiDevice* device, int device_id) {
  UsbMidiDescriptorParser parser;
  std::vector<uint8_t> descriptor = device->GetDescriptors();
  const uint8_t* data = descriptor.size() > 0 ? &descriptor[0] : NULL;
  std::vector<UsbMidiJack> jacks;
  bool parse_result = parser.Parse(device,
                                   data,
                                   descriptor.size(),
                                   &jacks);
  if (!parse_result)
    return false;

  std::string manufacturer(device->GetManufacturer());
  std::string product_name(device->GetProductName());
  std::string version(device->GetDeviceVersion());

  for (size_t j = 0; j < jacks.size(); ++j) {
    // Port ID must be unique in a MIDI manager. This ID setting is
    // sufficiently unique although there is no user-friendly meaning.
    // TODO(yhirano): Use a hashed string as ID.
    std::string id(
        base::StringPrintf("usb:port-%d-%ld", device_id, static_cast<long>(j)));
    if (jacks[j].direction() == UsbMidiJack::DIRECTION_OUT) {
      output_streams_.push_back(
          std::make_unique<UsbMidiOutputStream>(jacks[j]));
      AddOutputPort(MidiPortInfo(id, manufacturer, product_name, version,
                                 PortState::OPENED));
    } else {
      DCHECK_EQ(jacks[j].direction(), UsbMidiJack::DIRECTION_IN);
      input_stream_->Add(jacks[j]);
      AddInputPort(MidiPortInfo(id, manufacturer, product_name, version,
                                PortState::OPENED));
    }
  }
  return true;
}

}  // namespace midi
