// 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 <stddef.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();
  std::unique_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
