// Copyright 2015 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 <stdarg.h>
#include <stdint.h>
#include <string.h>

#include <sstream>
#include <utility>

#include "base/strings/stringprintf.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/graphics_2d.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"

namespace {

void DummyCompletionCallback(void*, int32_t) {}

// This is a simple C++ Pepper plugin for Blink layout tests.
//
// Layout tests can instantiate this plugin by requesting the mime type
// application/x-blink-test-plugin. When possible, tests should use the
// startAfterLoadAndFinish() helper in resources/plugin.js to perform work
// after the plugin has loaded.
//
// The plugin also exposes several other features for testing convenience:
// - On first paint, the plugin posts a 'loaded' message to its owner element.
// - On subsequent paints, the plugin posts a 'painted' message instead.
// - Keyboard and mouse input events are logged to the console.
class BlinkTestInstance : public pp::Instance {
 public:
  explicit BlinkTestInstance(PP_Instance instance)
      : pp::Instance(instance), first_paint_(true) {}
  ~BlinkTestInstance() override {}

  bool Init(uint32_t argc, const char* argn[], const char* argv[]) override {
    // It's hard / impossible for some layout tests to listen for a message from
    // the plugin. For example, a plugin in PluginDocuments is unreachable from
    // a cross-origin parent frame, since the actual plugin element is in a
    // different Document. To help with this case, the plugin logs a message
    // that can be captured indirectly in test expectations.
    LogMessage("initializing");
    // Used by layout tests that want to inspect the args the plugin is
    // instantiated with.
    for (uint32_t i = 0; i < argc; ++i) {
      if (!strcmp(argn[i], "logargs")) {
        LogMessage("plugin args:");
        for (uint32_t j = 0; j < argc; ++j)
          LogMessage("  name = %s, value = %s", argn[j], argv[j]);
      }
    }
    return RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
                                       PP_INPUTEVENT_CLASS_KEYBOARD) == PP_OK;
  }

  void DidChangeView(const pp::View& view) override {
    view_ = view;
    device_context_ = pp::Graphics2D(this, view_.GetRect().size(), true);
    if (!BindGraphics(device_context_))
      return;

    // Since we draw a static image, we only need to make a new frame when
    // the device is initialized or the view size changes.
    Paint();
  }

  void DidChangeFocus(bool has_focus) override {
    LogMessage("DidChangeFocus(%s)", has_focus ? "true" : "false");
  }

  bool HandleInputEvent(const pp::InputEvent& event) override {
    switch (event.GetType()) {
      case PP_INPUTEVENT_TYPE_MOUSEDOWN:
        LogMouseEvent("Down", event);
        break;
      case PP_INPUTEVENT_TYPE_MOUSEUP:
        LogMouseEvent("Up", event);
        break;
      case PP_INPUTEVENT_TYPE_KEYDOWN:
        LogKeyboardEvent("Down", event);
        break;
      case PP_INPUTEVENT_TYPE_KEYUP:
        LogKeyboardEvent("Up", event);
        break;
      case PP_INPUTEVENT_TYPE_MOUSEMOVE:
      case PP_INPUTEVENT_TYPE_MOUSEENTER:
      case PP_INPUTEVENT_TYPE_MOUSELEAVE:
      case PP_INPUTEVENT_TYPE_RAWKEYDOWN:
      case PP_INPUTEVENT_TYPE_CHAR:
        // Just swallow these events without any logging.
        return true;
      default:
        LogMessage("Unexpected input event with type = %d", event.GetType());
        return false;
    }
    return true;
  }

 private:
  void Paint() {
    pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                        view_.GetRect().size(), true);
    if (image.is_null())
      return;

    // Draw blue and green checkerboard pattern to show "interesting" keyframe.
    const int kSquareSizePixels = 8;
    for (int y = 0; y < view_.GetRect().size().height(); ++y) {
      for (int x = 0; x < view_.GetRect().size().width(); ++x) {
        int x_square = x / kSquareSizePixels;
        int y_square = y / kSquareSizePixels;
        uint32_t color = ((x_square + y_square) % 2) ? 0xFF0000FF : 0xFF00FF00;
        *image.GetAddr32(pp::Point(x, y)) = color;
      }
    }

    device_context_.ReplaceContents(&image);
    device_context_.Flush(
        pp::CompletionCallback(&DummyCompletionCallback, nullptr));

    // TODO(dcheng): In theory, this should wait for the flush to complete
    // before claiming that it's painted. In practice, this is difficult: when
    // running layout tests, a frame is typically only generated at the end of
    // the layout test. Sending the completion message in the callback results
    // in a deadlock: the test wants to wait for the plugin to paint, but the
    // plugin won't paint until the test completes. This seems to be Good
    // Enough™ for now.
    if (first_paint_) {
      first_paint_ = false;
      PostMessage(pp::Var("loaded"));
    } else {
      PostMessage(pp::Var("painted"));
    }
  }

  void LogMouseEvent(const char* type, const pp::InputEvent& event) {
    pp::MouseInputEvent mouse_event(event);
    pp::Point mouse_position = mouse_event.GetPosition();
    LogMessage("Mouse%s at (%d,%d)", type, mouse_position.x(),
               mouse_position.y());
  }

  void LogKeyboardEvent(const char* type, const pp::InputEvent& event) {
    pp::KeyboardInputEvent keyboard_event(event);
    LogMessage("Key%s '%s'", type, keyboard_event.GetCode().AsString().c_str());
  }

  void LogMessage(const char* format...) {
    va_list args;
    va_start(args, format);
    LogToConsoleWithSource(PP_LOGLEVEL_LOG, pp::Var("Blink Test Plugin"),
                           pp::Var(base::StringPrintV(format, args)));
    va_end(args);
  }

  bool first_paint_;
  pp::View view_;
  pp::Graphics2D device_context_;
};

class BlinkTestModule : public pp::Module {
 public:
  BlinkTestModule() {}
  virtual ~BlinkTestModule() {}

  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new BlinkTestInstance(instance);
  }
};

}  // namespace

namespace pp {

Module* CreateModule() {
  return new BlinkTestModule();
}

}  // namespace pp
