// 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 <utility>

#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "media/midi/midi_scheduler.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() {
  base::AutoLock auto_lock(scheduler_lock_);
  CHECK(!scheduler_);
}

void MidiManagerUsb::StartInitialization() {
  Initialize(
      base::Bind(&MidiManager::CompleteInitialization, base::Unretained(this)));
}

void MidiManagerUsb::Finalize() {
  // Destruct MidiScheduler on Chrome_IOThread.
  base::AutoLock auto_lock(scheduler_lock_);
  scheduler_.reset();
}

void MidiManagerUsb::Initialize(base::Callback<void(Result result)> callback) {
  initialize_callback_ = callback;

  {
    base::AutoLock auto_lock(scheduler_lock_);
    scheduler_.reset(new MidiScheduler(this));
  }

  // This is safe because EnumerateDevices cancels the operation on destruction.
  device_factory_->EnumerateDevices(
      this,
      base::Bind(&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;
  }
  // output_streams_[port_index] is alive unless MidiManagerUsb is deleted.
  // The task posted to the MidiScheduler will be disposed safely on deleting
  // the scheduler.
  scheduler_->PostSendDataTask(
      client, data.size(), timestamp,
      base::Bind(&UsbMidiOutputStream::Send,
                 base::Unretained(output_streams_[port_index]), data));
}

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(), device_id);
}

void MidiManagerUsb::OnDeviceDetached(size_t index) {
  if (index >= devices_.size()) {
    return;
  }
  UsbMidiDevice* device = devices_[index];
  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) {
    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], static_cast<int>(i))) {
      initialize_callback_.Run(Result::INITIALIZATION_ERROR);
      return;
    }
  }
  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(new 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
