// Copyright (c) 2011 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/native_client/tests/ppapi_test_lib/test_interface.h"

#include <string.h>
#include <map>
#include <new>

#include "native_client/src/include/nacl_macros.h"
#include "native_client/src/shared/platform/nacl_check.h"

#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_module.h"
#include "ppapi/c/pp_size.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb_core.h"
#include "ppapi/c/ppb_graphics_2d.h"
#include "ppapi/c/ppb_image_data.h"
#include "ppapi/c/ppb_instance.h"
#include "ppapi/c/ppb_messaging.h"
#include "ppapi/c/ppb_var.h"
#include "ppapi/c/private/ppb_testing_private.h"

#include "ppapi/native_client/tests/ppapi_test_lib/get_browser_interface.h"
#include "ppapi/native_client/tests/ppapi_test_lib/internal_utils.h"

void PostTestMessage(nacl::string test_name, nacl::string message) {
  nacl::string test_message = test_name;
  test_message += ":";
  test_message += message;
  PP_Var post_var = PPBVar()->VarFromUtf8(test_message.c_str(),
                                          test_message.size());
  PPBMessaging()->PostMessage(pp_instance(), post_var);
  PPBVar()->Release(post_var);
}

PP_Var PP_MakeString(const char* s) {
  return PPBVar()->VarFromUtf8(s, strlen(s));
}

nacl::string StringifyVar(const PP_Var& var) {
  uint32_t dummy_size;
  switch (var.type) {
    default:
     return "<UNKNOWN>" +  toString(var.type);
    case  PP_VARTYPE_NULL:
      return "<NULL>";
    case  PP_VARTYPE_BOOL:
     return "<BOOL>" + toString(var.value.as_bool);
    case  PP_VARTYPE_INT32:
     return "<INT32>" + toString(var.value.as_int);
    case  PP_VARTYPE_DOUBLE:
     return "<DOUBLE>" + toString(var.value.as_double);
    case PP_VARTYPE_STRING:
     return "<STRING>" + nacl::string(PPBVar()->VarToUtf8(var, &dummy_size));
  }
}

////////////////////////////////////////////////////////////////////////////////
// Test registration
////////////////////////////////////////////////////////////////////////////////

namespace {

class TestTable {
 public:
  // Return singleton intsance.
  static TestTable* Get() {
    static TestTable table;
    return &table;
  }

  void AddTest(nacl::string test_name, TestFunction test_function) {
    test_map_[test_name] = test_function;
  }
  void RunTest(nacl::string test_name);

 private:
  NACL_DISALLOW_COPY_AND_ASSIGN(TestTable);

  TestTable() {}

  typedef std::map<nacl::string, TestFunction> TestMap;
  TestMap test_map_;
};

void TestTable::RunTest(nacl::string test_name) {
  TestMap::iterator it = test_map_.find(test_name);
  if (it == test_map_.end()) {
    PostTestMessage(test_name, "NOTFOUND");
    return;
  }
  CHECK(it->second != NULL);
  TestFunction test_function = it->second;
  return test_function();
}

}  // namespace

void RegisterTest(nacl::string test_name, TestFunction test_func) {
  TestTable::Get()->AddTest(test_name, test_func);
}

void RunTest(nacl::string test_name) {
  TestTable::Get()->RunTest(test_name);
}

////////////////////////////////////////////////////////////////////////////////
// Testable callback support
////////////////////////////////////////////////////////////////////////////////

namespace {

struct CallbackInfo {
  nacl::string callback_name;
  PP_CompletionCallback user_callback;
};

void ReportCallbackInvocationToJS(const char* callback_name) {
  PP_Var callback_var = PPBVar()->VarFromUtf8(callback_name,
                                              strlen(callback_name));
  // Report using postmessage for async tests.
  PPBMessaging()->PostMessage(pp_instance(), callback_var);
  PPBVar()->Release(callback_var);
}

void CallbackWrapper(void* user_data, int32_t result) {
  CallbackInfo* callback_info = reinterpret_cast<CallbackInfo*>(user_data);
  PP_RunCompletionCallback(&callback_info->user_callback, result);
  ReportCallbackInvocationToJS(callback_info->callback_name.c_str());
  delete callback_info;
}

}  // namespace

PP_CompletionCallback MakeTestableCompletionCallback(
    const char* callback_name,  // Tested for by JS harness.
    PP_CompletionCallback_Func func,
    void* user_data) {
  CHECK(callback_name != NULL && strlen(callback_name) > 0);
  CHECK(func != NULL);

  CallbackInfo* callback_info = new(std::nothrow) CallbackInfo;
  CHECK(callback_info != NULL);
  callback_info->callback_name = callback_name;
  callback_info->user_callback =
    PP_MakeOptionalCompletionCallback(func, user_data);

  return PP_MakeOptionalCompletionCallback(CallbackWrapper, callback_info);
}

PP_CompletionCallback MakeTestableCompletionCallback(
    const char* callback_name,  // Tested for by JS harness.
    PP_CompletionCallback_Func func) {
  return MakeTestableCompletionCallback(callback_name, func, NULL);
}


////////////////////////////////////////////////////////////////////////////////
// PPAPI Helpers
////////////////////////////////////////////////////////////////////////////////

bool IsSizeInRange(PP_Size size, PP_Size min_size, PP_Size max_size) {
  return (min_size.width <= size.width && size.width <= max_size.width &&
          min_size.height <= size.height && size.height <= max_size.height);
}

bool IsSizeEqual(PP_Size size, PP_Size expected) {
  return (size.width == expected.width && size.height == expected.height);
}

bool IsRectEqual(PP_Rect position, PP_Rect expected) {
  return (position.point.x == expected.point.x &&
          position.point.y == expected.point.y &&
          IsSizeEqual(position.size, expected.size));
}

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
    NACL_NOTREACHED();
}

PP_Resource CreateImageData(PP_Size size, ColorPremul pixel_color, void** bmp) {
  PP_ImageDataFormat image_format = PPBImageData()->GetNativeImageDataFormat();
  uint32_t formatted_pixel_color = FormatColor(image_format, pixel_color);
  PP_Resource image_data = PPBImageData()->Create(
      pp_instance(), image_format, &size, PP_TRUE /*init_to_zero*/);
  CHECK(image_data != kInvalidResource);
  PP_ImageDataDesc image_desc;
  CHECK(PPBImageData()->Describe(image_data, &image_desc) == PP_TRUE);
  *bmp = NULL;
  *bmp = PPBImageData()->Map(image_data);
  CHECK(*bmp != NULL);
  uint32_t* bmp_words = static_cast<uint32_t*>(*bmp);
  int num_pixels = image_desc.stride / kBytesPerPixel * image_desc.size.height;
  for (int i = 0; i < num_pixels; i++)
    bmp_words[i] = formatted_pixel_color;
  return image_data;
}

bool IsImageRectOnScreen(PP_Resource graphics2d,
                         PP_Point origin,
                         PP_Size size,
                         ColorPremul color) {
  PP_Size size2d;
  PP_Bool dummy;
  CHECK(PP_TRUE == PPBGraphics2D()->Describe(graphics2d, &size2d, &dummy));

  void* bitmap = NULL;
  PP_Resource image = CreateImageData(size2d, kOpaqueBlack, &bitmap);

  PP_ImageDataDesc image_desc;
  CHECK(PP_TRUE == PPBImageData()->Describe(image, &image_desc));
  int32_t stride = image_desc.stride / kBytesPerPixel;  // width + padding.
  uint32_t expected_color = FormatColor(image_desc.format, color);
  CHECK(origin.x >= 0 && origin.y >= 0 &&
        (origin.x + size.width) <= stride &&
        (origin.y + size.height) <= image_desc.size.height);

  CHECK(PP_TRUE == PPBTestingPrivate()->ReadImageData(
      graphics2d, image, &kOrigin));
  bool found_error = false;
  for (int y = origin.y; y < origin.y + size.height && !found_error; y++) {
    for (int x = origin.x; x < origin.x + size.width && !found_error; x++) {
      uint32_t pixel_color = static_cast<uint32_t*>(bitmap)[stride * y + x];
      found_error = (pixel_color != expected_color);
    }
  }

  PPBCore()->ReleaseResource(image);
  return !found_error;
}
