// 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/graphics_2d_resource.h"

#include "ppapi/c/pp_bool.h"
#include "ppapi/c/pp_point.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/c/pp_size.h"
#include "ppapi/c/ppb_graphics_2d.h"
#include "ppapi/proxy/dispatch_reply_message.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/tracked_callback.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_image_data_api.h"

namespace ppapi {
namespace proxy {

Graphics2DResource::Graphics2DResource(Connection connection,
                                       PP_Instance instance,
                                       const PP_Size& size,
                                       PP_Bool is_always_opaque)
    : PluginResource(connection, instance),
      size_(size),
      is_always_opaque_(is_always_opaque),
      scale_(1.0f) {
  // These checks are copied from PPB_ImageData_Impl::Init to make tests passed.
  // Let's remove/refactor this when start to refactor ImageData.
  bool bad_args = size.width <= 0 || size.height <= 0 ||
      static_cast<int64>(size.width) * static_cast<int64>(size.height) >=
          std::numeric_limits<int32>::max() / 4;
  if (!bad_args && !sent_create_to_renderer()) {
    SendCreate(RENDERER,
        PpapiHostMsg_Graphics2D_Create(size, is_always_opaque));
  }
}

Graphics2DResource::~Graphics2DResource() {
}

PP_Bool Graphics2DResource::Describe(PP_Size* size, PP_Bool* is_always_opaque) {
  *size = size_;
  *is_always_opaque = is_always_opaque_;
  return PP_TRUE;
}

thunk::PPB_Graphics2D_API* Graphics2DResource::AsPPB_Graphics2D_API() {
  return this;
}

void Graphics2DResource::PaintImageData(PP_Resource image_data,
                                        const PP_Point* top_left,
                                        const PP_Rect* src_rect) {
  Resource* image_object =
      PpapiGlobals::Get()->GetResourceTracker()->GetResource(image_data);
  if (!image_object || pp_instance() != image_object->pp_instance()) {
    Log(PP_LOGLEVEL_ERROR,
        "Graphics2DResource.PaintImageData: Bad image resource.");
    return;
  }

  PP_Rect dummy;
  memset(&dummy, 0, sizeof(PP_Rect));
  Post(RENDERER, PpapiHostMsg_Graphics2D_PaintImageData(
      image_object->host_resource(), *top_left,
      !!src_rect, src_rect ? *src_rect : dummy));
}

void Graphics2DResource::Scroll(const PP_Rect* clip_rect,
                                const PP_Point* amount) {
  PP_Rect dummy;
  memset(&dummy, 0, sizeof(PP_Rect));
  Post(RENDERER, PpapiHostMsg_Graphics2D_Scroll(
      !!clip_rect, clip_rect ? *clip_rect : dummy, *amount));
}

void Graphics2DResource::ReplaceContents(PP_Resource image_data) {
  thunk::EnterResourceNoLock<thunk::PPB_ImageData_API> enter_image(
      image_data, true);
  if (enter_image.failed())
    return;

  // Check that the PP_Instance matches.
  Resource* image_object =
      PpapiGlobals::Get()->GetResourceTracker()->GetResource(image_data);
  if (!image_object || pp_instance() != image_object->pp_instance()) {
    Log(PP_LOGLEVEL_ERROR,
        "Graphics2DResource.PaintImageData: Bad image resource.");
    return;
  }
  enter_image.object()->SetIsCandidateForReuse();

  Post(RENDERER, PpapiHostMsg_Graphics2D_ReplaceContents(
      image_object->host_resource()));
}

PP_Bool Graphics2DResource::SetScale(float scale) {
  if (scale <= 0.0f)
    return PP_FALSE;
  Post(RENDERER, PpapiHostMsg_Graphics2D_SetScale(scale));
  scale_ = scale;
  return PP_TRUE;
}

float Graphics2DResource::GetScale() {
  return scale_;
}

int32_t Graphics2DResource::Flush(scoped_refptr<TrackedCallback> callback) {
  // If host is not even created, return failure immediately.  This can happen
  // when failed to initialize (in constructor).
  if (!sent_create_to_renderer())
    return PP_ERROR_FAILED;

  if (TrackedCallback::IsPending(current_flush_callback_))
    return PP_ERROR_INPROGRESS;  // Can't have >1 flush pending.
  current_flush_callback_ = callback;

  Call<PpapiPluginMsg_Graphics2D_FlushAck>(
      RENDERER,
      PpapiHostMsg_Graphics2D_Flush(),
      base::Bind(&Graphics2DResource::OnPluginMsgFlushACK, this));
  return PP_OK_COMPLETIONPENDING;
}

bool Graphics2DResource::ReadImageData(PP_Resource image,
                                       const PP_Point* top_left) {
  if (!top_left)
    return false;
  int32_t result = SyncCall<PpapiPluginMsg_Graphics2D_ReadImageDataAck>(
      RENDERER,
      PpapiHostMsg_Graphics2D_ReadImageData(image, *top_left));
  return result == PP_OK;
}

void Graphics2DResource::OnPluginMsgFlushACK(
    const ResourceMessageReplyParams& params) {
  current_flush_callback_->Run(params.result());
}

}  // namespace proxy
}  // namespace ppapi
