// Copyright (c) 2012 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 "ppapi/proxy/video_capture_resource.h"

#include "ppapi/c/dev/ppp_video_capture_dev.h"
#include "ppapi/proxy/dispatch_reply_message.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/plugin_globals.h"
#include "ppapi/proxy/plugin_resource_tracker.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_buffer_proxy.h"
#include "ppapi/proxy/resource_message_params.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/tracked_callback.h"

namespace ppapi {
namespace proxy {

VideoCaptureResource::VideoCaptureResource(
    Connection connection,
    PP_Instance instance,
    PluginDispatcher* dispatcher)
    : PluginResource(connection, instance),
      open_state_(BEFORE_OPEN),
      enumeration_helper_(this) {
  SendCreate(RENDERER, PpapiHostMsg_VideoCapture_Create());

  ppp_video_capture_impl_ = static_cast<const PPP_VideoCapture_Dev*>(
      dispatcher->local_get_interface()(PPP_VIDEO_CAPTURE_DEV_INTERFACE));
}

VideoCaptureResource::~VideoCaptureResource() {
}

void VideoCaptureResource::OnReplyReceived(
    const ResourceMessageReplyParams& params,
    const IPC::Message& msg) {
  if (enumeration_helper_.HandleReply(params, msg))
    return;

  if (params.sequence()) {
    PluginResource::OnReplyReceived(params, msg);
    return;
  }

  PPAPI_BEGIN_MESSAGE_MAP(VideoCaptureResource, msg)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_VideoCapture_OnDeviceInfo,
        OnPluginMsgOnDeviceInfo)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_VideoCapture_OnStatus,
        OnPluginMsgOnStatus)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_VideoCapture_OnError,
        OnPluginMsgOnError)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
        PpapiPluginMsg_VideoCapture_OnBufferReady,
        OnPluginMsgOnBufferReady)
    PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(NOTREACHED())
  PPAPI_END_MESSAGE_MAP()
}

int32_t VideoCaptureResource::EnumerateDevices(
    const PP_ArrayOutput& output,
    scoped_refptr<TrackedCallback> callback) {
  return enumeration_helper_.EnumerateDevices(output, callback);
}

int32_t VideoCaptureResource::MonitorDeviceChange(
    PP_MonitorDeviceChangeCallback callback,
    void* user_data) {
  return enumeration_helper_.MonitorDeviceChange(callback, user_data);
}

int32_t VideoCaptureResource::Open(
    const std::string& device_id,
    const PP_VideoCaptureDeviceInfo_Dev& requested_info,
    uint32_t buffer_count,
    scoped_refptr<TrackedCallback> callback) {
  if (open_state_ != BEFORE_OPEN)
    return PP_ERROR_FAILED;

  if (TrackedCallback::IsPending(open_callback_))
    return PP_ERROR_INPROGRESS;

  open_callback_ = callback;

  Call<PpapiPluginMsg_VideoCapture_OpenReply>(
      RENDERER,
      PpapiHostMsg_VideoCapture_Open(device_id, requested_info, buffer_count),
      base::Bind(&VideoCaptureResource::OnPluginMsgOpenReply, this));
  return PP_OK_COMPLETIONPENDING;
}

int32_t VideoCaptureResource::StartCapture() {
  if (open_state_ != OPENED)
    return PP_ERROR_FAILED;

  Post(RENDERER, PpapiHostMsg_VideoCapture_StartCapture());
  return PP_OK;
}

int32_t VideoCaptureResource::ReuseBuffer(uint32_t buffer) {
  if (buffer >= buffer_in_use_.size() || !buffer_in_use_[buffer])
    return PP_ERROR_BADARGUMENT;
  Post(RENDERER, PpapiHostMsg_VideoCapture_ReuseBuffer(buffer));
  return PP_OK;
}

int32_t VideoCaptureResource::StopCapture() {
  if (open_state_ != OPENED)
    return PP_ERROR_FAILED;

  Post(RENDERER, PpapiHostMsg_VideoCapture_StopCapture());
  return PP_OK;
}

void VideoCaptureResource::Close() {
  if (open_state_ == CLOSED)
    return;

  Post(RENDERER, PpapiHostMsg_VideoCapture_Close());

  open_state_ = CLOSED;

  if (TrackedCallback::IsPending(open_callback_))
    open_callback_->PostAbort();
}

int32_t VideoCaptureResource::EnumerateDevicesSync(
    const PP_ArrayOutput& devices) {
  return enumeration_helper_.EnumerateDevicesSync(devices);
}

void VideoCaptureResource::LastPluginRefWasDeleted() {
  enumeration_helper_.LastPluginRefWasDeleted();
}

void VideoCaptureResource::OnPluginMsgOnDeviceInfo(
    const ResourceMessageReplyParams& params,
    const struct PP_VideoCaptureDeviceInfo_Dev& info,
    const std::vector<HostResource>& buffers,
    uint32_t buffer_size) {
  if (!ppp_video_capture_impl_)
    return;

  std::vector<base::SharedMemoryHandle> handles;
  params.TakeAllSharedMemoryHandles(&handles);
  CHECK(handles.size() == buffers.size());

  PluginResourceTracker* tracker =
      PluginGlobals::Get()->plugin_resource_tracker();
  scoped_ptr<PP_Resource[]> resources(new PP_Resource[buffers.size()]);
  for (size_t i = 0; i < buffers.size(); ++i) {
    // We assume that the browser created a new set of resources.
    DCHECK(!tracker->PluginResourceForHostResource(buffers[i]));
    resources[i] = ppapi::proxy::PPB_Buffer_Proxy::AddProxyResource(
        buffers[i], handles[i], buffer_size);
  }

  buffer_in_use_ = std::vector<bool>(buffers.size());

  CallWhileUnlocked(ppp_video_capture_impl_->OnDeviceInfo,
                    pp_instance(),
                    pp_resource(),
                    &info,
                    static_cast<uint32_t>(buffers.size()),
                    resources.get());

  for (size_t i = 0; i < buffers.size(); ++i)
    tracker->ReleaseResource(resources[i]);
}

void VideoCaptureResource::OnPluginMsgOnStatus(
    const ResourceMessageReplyParams& params,
    uint32_t status) {
  switch (status) {
    case PP_VIDEO_CAPTURE_STATUS_STARTING:
    case PP_VIDEO_CAPTURE_STATUS_STOPPING:
      // Those states are not sent by the browser.
      NOTREACHED();
      break;
  }
  if (ppp_video_capture_impl_) {
    CallWhileUnlocked(ppp_video_capture_impl_->OnStatus,
                      pp_instance(),
                      pp_resource(),
                      status);
  }
}

void VideoCaptureResource::OnPluginMsgOnError(
    const ResourceMessageReplyParams& params,
    uint32_t error_code) {
  open_state_ = CLOSED;
  if (ppp_video_capture_impl_) {
    CallWhileUnlocked(ppp_video_capture_impl_->OnError,
                      pp_instance(),
                      pp_resource(),
                      error_code);
  }
}

void VideoCaptureResource::OnPluginMsgOnBufferReady(
    const ResourceMessageReplyParams& params,
    uint32_t buffer) {
  SetBufferInUse(buffer);
  if (ppp_video_capture_impl_) {
    CallWhileUnlocked(ppp_video_capture_impl_->OnBufferReady,
                      pp_instance(),
                      pp_resource(),
                      buffer);
  }
}

void VideoCaptureResource::OnPluginMsgOpenReply(
    const ResourceMessageReplyParams& params) {
  if (open_state_ == BEFORE_OPEN && params.result() == PP_OK)
    open_state_ = OPENED;

  // The callback may have been aborted by Close().
  if (TrackedCallback::IsPending(open_callback_))
    open_callback_->Run(params.result());
}

void VideoCaptureResource::SetBufferInUse(uint32_t buffer_index) {
  CHECK(buffer_index < buffer_in_use_.size());
  buffer_in_use_[buffer_index] = true;
}

}  // namespace proxy
}  // namespace ppapi
