// Copyright (c) 2013 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 "content/renderer/media/midi_message_filter.h"

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/media/midi_messages.h"
#include "content/renderer/render_thread_impl.h"
#include "ipc/ipc_logging.h"

using media::MIDIPortInfoList;
using base::AutoLock;

// The maximum number of bytes which we're allowed to send to the browser
// before getting acknowledgement back from the browser that they've been
// successfully sent.
static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024;  // 10 MB.

namespace content {

MIDIMessageFilter::MIDIMessageFilter(
    const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
    : channel_(NULL),
      io_message_loop_(io_message_loop),
      main_message_loop_(base::MessageLoopProxy::current()),
      next_available_id_(0),
      unacknowledged_bytes_sent_(0) {
}

MIDIMessageFilter::~MIDIMessageFilter() {}

void MIDIMessageFilter::Send(IPC::Message* message) {
  DCHECK(io_message_loop_->BelongsToCurrentThread());
  if (!channel_) {
    delete message;
  } else {
    channel_->Send(message);
  }
}

bool MIDIMessageFilter::OnMessageReceived(const IPC::Message& message) {
  DCHECK(io_message_loop_->BelongsToCurrentThread());
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(MIDIMessageFilter, message)
    IPC_MESSAGE_HANDLER(MIDIMsg_SessionStarted, OnSessionStarted)
    IPC_MESSAGE_HANDLER(MIDIMsg_DataReceived, OnDataReceived)
    IPC_MESSAGE_HANDLER(MIDIMsg_AcknowledgeSentData, OnAcknowledgeSentData)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void MIDIMessageFilter::OnFilterAdded(IPC::Channel* channel) {
  DCHECK(io_message_loop_->BelongsToCurrentThread());
  channel_ = channel;
}

void MIDIMessageFilter::OnFilterRemoved() {
  DCHECK(io_message_loop_->BelongsToCurrentThread());

  // Once removed, a filter will not be used again.  At this time all
  // delegates must be notified so they release their reference.
  OnChannelClosing();
}

void MIDIMessageFilter::OnChannelClosing() {
  DCHECK(io_message_loop_->BelongsToCurrentThread());
  channel_ = NULL;
}

void MIDIMessageFilter::StartSession(WebKit::WebMIDIAccessorClient* client) {
  // Generate and keep track of a "client id" which is sent to the browser
  // to ask permission to talk to MIDI hardware.
  // This id is handed back when we receive the answer in OnAccessApproved().
  if (clients_.find(client) == clients_.end()) {
    int client_id = next_available_id_++;
    clients_[client] = client_id;

    io_message_loop_->PostTask(FROM_HERE,
        base::Bind(&MIDIMessageFilter::StartSessionOnIOThread, this,
                   client_id));
  }
}

void MIDIMessageFilter::StartSessionOnIOThread(int client_id) {
  Send(new MIDIHostMsg_StartSession(client_id));
}

void MIDIMessageFilter::RemoveClient(WebKit::WebMIDIAccessorClient* client) {
  ClientsMap::iterator i = clients_.find(client);
  if (i != clients_.end())
    clients_.erase(i);
}

// Received from browser.

void MIDIMessageFilter::OnSessionStarted(
    int client_id,
    bool success,
    MIDIPortInfoList inputs,
    MIDIPortInfoList outputs) {
  // Handle on the main JS thread.
  main_message_loop_->PostTask(
      FROM_HERE,
      base::Bind(&MIDIMessageFilter::HandleSessionStarted, this,
                 client_id, success, inputs, outputs));
}

void MIDIMessageFilter::HandleSessionStarted(
    int client_id,
    bool success,
    MIDIPortInfoList inputs,
    MIDIPortInfoList outputs) {
  WebKit::WebMIDIAccessorClient* client = GetClientFromId(client_id);
  if (!client)
    return;

  if (success) {
    // Add the client's input and output ports.
    for (size_t i = 0; i < inputs.size(); ++i) {
      client->didAddInputPort(
          UTF8ToUTF16(inputs[i].id),
          UTF8ToUTF16(inputs[i].manufacturer),
          UTF8ToUTF16(inputs[i].name),
          UTF8ToUTF16(inputs[i].version));
    }

    for (size_t i = 0; i < outputs.size(); ++i) {
      client->didAddOutputPort(
          UTF8ToUTF16(outputs[i].id),
          UTF8ToUTF16(outputs[i].manufacturer),
          UTF8ToUTF16(outputs[i].name),
          UTF8ToUTF16(outputs[i].version));
    }
  }
  client->didStartSession(success);
}

WebKit::WebMIDIAccessorClient*
MIDIMessageFilter::GetClientFromId(int client_id) {
  // Iterating like this seems inefficient, but in practice there generally
  // will be very few clients (usually one).  Additionally, this lookup
  // usually happens one time during page load. So the performance hit is
  // negligible.
  for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i) {
    if ((*i).second == client_id)
      return (*i).first;
  }
  return NULL;
}

void MIDIMessageFilter::OnDataReceived(uint32 port,
                                       const std::vector<uint8>& data,
                                       double timestamp) {
  TRACE_EVENT0("midi", "MIDIMessageFilter::OnDataReceived");

  main_message_loop_->PostTask(
      FROM_HERE,
      base::Bind(&MIDIMessageFilter::HandleDataReceived, this,
                 port, data, timestamp));
}

void MIDIMessageFilter::OnAcknowledgeSentData(size_t bytes_sent) {
  DCHECK_GE(unacknowledged_bytes_sent_, bytes_sent);
  if (unacknowledged_bytes_sent_ >= bytes_sent)
    unacknowledged_bytes_sent_ -= bytes_sent;
}

void MIDIMessageFilter::HandleDataReceived(uint32 port,
                                           const std::vector<uint8>& data,
                                           double timestamp) {
  DCHECK(!data.empty());
  TRACE_EVENT0("midi", "MIDIMessageFilter::HandleDataReceived");

  for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i)
    (*i).first->didReceiveMIDIData(port, &data[0], data.size(), timestamp);
}

void MIDIMessageFilter::SendMIDIData(uint32 port,
                                     const uint8* data,
                                     size_t length,
                                     double timestamp) {
  if (length > kMaxUnacknowledgedBytesSent) {
    // TODO(crogers): buffer up the data to send at a later time.
    // For now we're just dropping these bytes on the floor.
    return;
  }

  std::vector<uint8> v(data, data + length);
  io_message_loop_->PostTask(FROM_HERE,
      base::Bind(&MIDIMessageFilter::SendMIDIDataOnIOThread, this,
                 port, v, timestamp));
}

void MIDIMessageFilter::SendMIDIDataOnIOThread(uint32 port,
                                               const std::vector<uint8>& data,
                                               double timestamp) {
  size_t n = data.size();
  if (n > kMaxUnacknowledgedBytesSent ||
      unacknowledged_bytes_sent_ > kMaxUnacknowledgedBytesSent ||
      n + unacknowledged_bytes_sent_ > kMaxUnacknowledgedBytesSent) {
    // TODO(crogers): buffer up the data to send at a later time.
    // For now we're just dropping these bytes on the floor.
    return;
  }

  unacknowledged_bytes_sent_ += n;

  // Send to the browser.
  Send(new MIDIHostMsg_SendData(port, data, timestamp));
}

}  // namespace content
