// 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/message_loop/message_loop.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,
                                          double 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
