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

#include <stdio.h>
#include <string.h>
#include <string>

#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/ppb_fullscreen.h"
#include "ppapi/cpp/image_data.h"
#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/point.h"
#include "ppapi/tests/test_utils.h"
#include "ppapi/tests/testing_instance.h"

REGISTER_TEST_CASE(Fullscreen);

namespace {

const ColorPremul kOpaqueWhite = { 0xFF, 0xFF, 0xFF, 0xFF };
const ColorPremul kSheerRed = { 0x88, 0x88, 0x00, 0x00 };
const ColorPremul kSheerBlue = { 0x88, 0x00, 0x00, 0x88 };
const ColorPremul kOpaqueYellow = { 0xFF, 0xFF, 0xFF, 0x00 };
const int kBytesPerPixel = sizeof(uint32_t);  // 4 bytes for BGRA or RGBA.

uint32_t FormatColor(PP_ImageDataFormat format, ColorPremul color) {
  if (format == PP_IMAGEDATAFORMAT_BGRA_PREMUL)
    return (color.A << 24) | (color.R << 16) | (color.G << 8) | (color.B);
  else if (format == PP_IMAGEDATAFORMAT_RGBA_PREMUL)
    return (color.A << 24) | (color.B << 16) | (color.G << 8) | (color.R);
  else
    return 0;
}

bool HasMidScreen(const pp::Rect& position, const pp::Size& screen_size) {
  static int32_t mid_x = screen_size.width() / 2;
  static int32_t mid_y = screen_size.height() / 2;
  return (position.Contains(mid_x, mid_y));
}

void FlushCallbackCheckImageData(void* data, int32_t result) {
  static_cast<TestFullscreen*>(data)->CheckPluginPaint();
}

}  // namespace

TestFullscreen::TestFullscreen(TestingInstance* instance)
    : TestCase(instance),
      error_(),
      screen_mode_(instance),
      painted_color_(0),
      fullscreen_pending_(false),
      normal_pending_(false),
      fullscreen_event_(instance->pp_instance()),
      normal_event_(instance->pp_instance()) {
  screen_mode_.GetScreenSize(&screen_size_);
}

bool TestFullscreen::Init() {
  if (screen_size_.IsEmpty()) {
    instance_->AppendError("Failed to initialize screen_size_");
    return false;
  }
  graphics2d_ = pp::Graphics2D(instance_, screen_size_, true);
  if (!instance_->BindGraphics(graphics2d_)) {
    instance_->AppendError("Failed to initialize graphics2d_");
    return false;
  }
  return CheckTestingInterface();
}

void TestFullscreen::RunTests(const std::string& filter) {
  RUN_TEST(GetScreenSize, filter);
  RUN_TEST(NormalToFullscreenToNormal, filter);
}

bool TestFullscreen::GotError() {
  return !error_.empty();
}

std::string TestFullscreen::Error() {
  std::string last_error = error_;
  error_.clear();
  return last_error;
}

// TODO(polina): consider adding custom logic to JS for this test to
// get screen.width and screen.height and postMessage those to this code,
// so the dimensions can be checked exactly.
std::string TestFullscreen::TestGetScreenSize() {
  if (screen_size_.width() < 320 || screen_size_.width() > 2560)
    return ReportError("screen_size.width()", screen_size_.width());
  if (screen_size_.height() < 200 || screen_size_.height() > 2048)
    return ReportError("screen_size.height()", screen_size_.height());
  PASS();
}

std::string TestFullscreen::TestNormalToFullscreenToNormal() {
  // 0. Start in normal mode.
  if (screen_mode_.IsFullscreen())
    return ReportError("IsFullscreen() at start", true);

  // 1. Switch to fullscreen.
  // This is only allowed within a context of a user gesture (e.g. mouse click).
  if (screen_mode_.SetFullscreen(true))
    return ReportError("SetFullscreen(true) outside of user gesture", true);
  // Trigger another call to SetFullscreen(true) from HandleInputEvent().
  // The transition is asynchronous and ends at the next DidChangeView().
  instance_->RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
  SimulateUserGesture();
  // DidChangeView() will call the callback once in fullscreen mode.
  fullscreen_event_.Wait();
  if (GotError())
    return Error();
  if (fullscreen_pending_)
    return "fullscreen_pending_ has not been reset";
  if (!screen_mode_.IsFullscreen())
    return ReportError("IsFullscreen() in fullscreen", false);

  // 2. Stay in fullscreen. No change.
  if (screen_mode_.SetFullscreen(true))
    return ReportError("SetFullscreen(true) in fullscreen", true);
  if (!screen_mode_.IsFullscreen())
    return ReportError("IsFullscreen() in fullscreen^2", false);

  // 3. Switch to normal.
  // The transition is asynchronous and ends at DidChangeView().
  // No graphics devices can be bound while in transition.
  normal_pending_ = true;
  if (!screen_mode_.SetFullscreen(false))
    return ReportError("SetFullscreen(false) in fullscreen", false);
  // DidChangeView() will signal once out of fullscreen mode.
  normal_event_.Wait();
  if (GotError())
    return Error();
  if (normal_pending_)
    return "normal_pending_ has not been reset";
  if (screen_mode_.IsFullscreen())
    return ReportError("IsFullscreen() in normal", true);

  // 4. Stay in normal. No change.
  if (screen_mode_.SetFullscreen(false))
    return ReportError("SetFullscreen(false) in normal", true);
  if (screen_mode_.IsFullscreen())
    return ReportError("IsFullscreen() in normal^2", true);

  PASS();
}

void TestFullscreen::SimulateUserGesture() {
  pp::Point plugin_center(
      normal_position_.x() + normal_position_.width() / 2,
      normal_position_.y() + normal_position_.height() / 2);
  pp::Point mouse_movement;
  pp::MouseInputEvent input_event(
      instance_,
      PP_INPUTEVENT_TYPE_MOUSEDOWN,
      0,  // time_stamp
      0,  // modifiers
      PP_INPUTEVENT_MOUSEBUTTON_LEFT,
      plugin_center,
      1,  // click_count
      mouse_movement);

  testing_interface_->SimulateInputEvent(instance_->pp_instance(),
                                         input_event.pp_resource());
}

void TestFullscreen::FailFullscreenTest(const std::string& error) {
  error_ = error;
  fullscreen_event_.Signal();
}

void TestFullscreen::FailNormalTest(const std::string& error) {
  error_ = error;
  normal_event_.Signal();
}

void TestFullscreen::PassFullscreenTest() {
  fullscreen_event_.Signal();
}

void TestFullscreen::PassNormalTest() {
  normal_event_.Signal();
}

// Transition to fullscreen can only happen when processing a user gesture.
bool TestFullscreen::HandleInputEvent(const pp::InputEvent& event) {
  // We only let mouse events through and only mouse clicks count.
  if (event.GetType() != PP_INPUTEVENT_TYPE_MOUSEDOWN &&
      event.GetType() != PP_INPUTEVENT_TYPE_MOUSEUP)
    return false;
  // We got the gesture. No need to handle any more events.
  instance_->ClearInputEventRequest(PP_INPUTEVENT_CLASS_MOUSE);
  if (screen_mode_.IsFullscreen()) {
    FailFullscreenTest(
        ReportError("IsFullscreen() before fullscreen transition", true));
    return false;
  }
  fullscreen_pending_ = true;
  if (!screen_mode_.SetFullscreen(true)) {
    FailFullscreenTest(ReportError("SetFullscreen(true) in normal", false));
    return false;
  }
  // DidChangeView() will complete the transition to fullscreen.
  return false;
}

bool TestFullscreen::PaintPlugin(pp::Size size, ColorPremul color) {
  painted_size_ = size;
  PP_ImageDataFormat image_format = pp::ImageData::GetNativeImageDataFormat();
  painted_color_ = FormatColor(image_format, color);
  if (painted_color_ == 0)
    return false;
  pp::Point origin(0, 0);

  pp::ImageData image(instance_, image_format, size, false);
  if (image.is_null())
    return false;
  uint32_t* pixels = static_cast<uint32_t*>(image.data());
  int num_pixels = image.stride() / kBytesPerPixel * image.size().height();
  for (int i = 0; i < num_pixels; i++)
    pixels[i] = painted_color_;
  graphics2d_.PaintImageData(image, origin);
  pp::CompletionCallback cc(FlushCallbackCheckImageData, this);
  if (graphics2d_.Flush(cc) != PP_OK_COMPLETIONPENDING)
    return false;

  return true;
}

void TestFullscreen::CheckPluginPaint() {
  PP_ImageDataFormat image_format = pp::ImageData::GetNativeImageDataFormat();
  pp::ImageData readback(instance_, image_format, painted_size_, false);
  pp::Point origin(0, 0);
  if (readback.is_null() ||
      PP_TRUE != testing_interface_->ReadImageData(graphics2d_.pp_resource(),
                                                   readback.pp_resource(),
                                                   &origin.pp_point())) {
    error_ = "Can't read plugin image";
    return;
  }
  for (int y = 0; y < painted_size_.height(); y++) {
    for (int x = 0; x < painted_size_.width(); x++) {
      uint32_t* readback_color = readback.GetAddr32(pp::Point(x, y));
      if (painted_color_ != *readback_color) {
        error_ = "Plugin image contains incorrect pixel value";
        return;
      }
    }
  }
  if (screen_mode_.IsFullscreen())
    PassFullscreenTest();
  else
    PassNormalTest();
}

// Transitions to/from fullscreen is asynchronous ending at DidChangeView.
// The number of calls to DidChangeView during fullscreen / normal transitions
// isn't specified by the API. The test waits until it the screen has
// transitioned to the desired state.
//
// WebKit does not change the plugin size, but Pepper does explicitly set
// it to screen width and height when SetFullscreen(true) is called and
// resets it back when ViewChanged is received indicating that we exited
// fullscreen.
//
// NOTE: The number of DidChangeView calls for <object> might be different.
// TODO(bbudge) Figure out how to test that the plugin positon eventually
// changes to normal_position_.
void TestFullscreen::DidChangeView(const pp::View& view) {
  pp::Rect position = view.GetRect();
  pp::Rect clip = view.GetClipRect();

  if (normal_position_.IsEmpty())
    normal_position_ = position;

  bool is_fullscreen = screen_mode_.IsFullscreen();
  if (fullscreen_pending_ && is_fullscreen) {
    fullscreen_pending_ = false;
    if (!HasMidScreen(position, screen_size_))
      FailFullscreenTest("DidChangeView is not in the middle of the screen");
    else if (position.size() != screen_size_)
      FailFullscreenTest("DidChangeView does not have screen size");
    // NOTE: we cannot reliably test for clip size being equal to the screen
    // because it might be affected by JS console, info bars, etc.
    else if (!instance_->BindGraphics(graphics2d_))
      FailFullscreenTest("Failed to BindGraphics() in fullscreen");
    else if (!PaintPlugin(position.size(), kOpaqueYellow))
      FailFullscreenTest("Failed to paint plugin image in fullscreen");
  } else if (normal_pending_ && !is_fullscreen) {
    normal_pending_ = false;
    if (screen_mode_.IsFullscreen())
      FailNormalTest("DidChangeview is in fullscreen");
    else if (!instance_->BindGraphics(graphics2d_))
      FailNormalTest("Failed to BindGraphics() in normal");
    else if (!PaintPlugin(position.size(), kSheerBlue))
      FailNormalTest("Failed to paint plugin image in normal");
  }
}
