// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/renderer/rasterizer/blitter/linear_gradient_cache.h"

#include <vector>

#include "cobalt/math/point_f.h"
#include "cobalt/render_tree/brush.h"
#include "cobalt/render_tree/color_rgba.h"
#include "starboard/blitter.h"

#include "testing/gtest/include/gtest/gtest.h"

#if SB_HAS(BLITTER)

using cobalt::math::PointF;
using cobalt::render_tree::ColorRGBA;
using cobalt::render_tree::ColorStop;
using cobalt::render_tree::ColorStopList;
using cobalt::render_tree::LinearGradientBrush;

namespace {
const int kDefaultSurfaceSizeInPixels = 64;

struct TestData {
  TestData(LinearGradientBrush brush_arg, SbBlitterSurface surface_arg)
      : brush(brush_arg), surface(surface_arg) {}

  LinearGradientBrush brush;
  SbBlitterSurface surface;
};

float GenerateRandomFloatBetween0and1() {
  return (std::rand() / static_cast<float>(RAND_MAX));
}

SbBlitterSurface GenerateRandomSurface(SbBlitterDevice device, int width,
                                       int height,
                                       SbBlitterPixelDataFormat pixel_format) {
  SbBlitterPixelData pixel_data =
      SbBlitterCreatePixelData(device, width, height, pixel_format);

  if (!SbBlitterIsPixelDataValid(pixel_data)) return kSbBlitterInvalidSurface;

  SbBlitterSurface surface =
      SbBlitterCreateSurfaceFromPixelData(device, pixel_data);
  return surface;
}

TestData GenerateRandomTestData(const SbBlitterDevice &device, int width,
                                int height,
                                SbBlitterPixelDataFormat pixel_format) {
  bool horizontal_brush = (height == 1);
  if (horizontal_brush) {
    DCHECK_EQ(height, 1);
  } else {
    DCHECK_EQ(width, 1);
  }
  PointF source(20.0f, 20.0f);
  PointF dest(0.0f, 0.0f);
  // Gradient size is randomly chosen between -5.0 and 5.0
  float gradient_size = 2.0 * (GenerateRandomFloatBetween0and1() - 0.5) * 5.0f;
  if (fabs(gradient_size) < 0.1f) {
    // Try not to generate 0s.
    gradient_size = 0.1f;
  }

  if (horizontal_brush) {
    dest.set_x(source.x() + gradient_size);
    dest.set_y(source.y());
  } else {
    dest.set_x(source.x());
    dest.set_y(source.y() + gradient_size);
  }
  ColorStopList stops;
  ColorRGBA color1(GenerateRandomFloatBetween0and1(),
                   GenerateRandomFloatBetween0and1(),
                   GenerateRandomFloatBetween0and1());
  ColorRGBA color2(GenerateRandomFloatBetween0and1(),
                   GenerateRandomFloatBetween0and1(),
                   GenerateRandomFloatBetween0and1());
  stops.push_back(ColorStop(0.0, color1));
  stops.push_back(ColorStop(1.0, color2));
  LinearGradientBrush brush(source, dest, stops);
  SbBlitterSurface random_surface(
      GenerateRandomSurface(device, width, height, pixel_format));
  return TestData(brush, random_surface);
}
}  // namespace

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace blitter {

class LinearGradientCacheFixture : public ::testing::Test {
 public:
  LinearGradientCacheFixture()
      : default_device(kSbBlitterInvalidDevice), pixel_format() {}

  virtual void SetUp() {
    pixel_format = kSbBlitterInvalidPixelDataFormat;
    switch (SB_PREFERRED_RGBA_BYTE_ORDER) {
      case SB_PREFERRED_RGBA_BYTE_ORDER_RGBA:
        pixel_format = kSbBlitterPixelDataFormatRGBA8;
        break;
      case SB_PREFERRED_RGBA_BYTE_ORDER_BGRA:
        pixel_format = kSbBlitterPixelDataFormatBGRA8;
        break;
      case SB_PREFERRED_RGBA_BYTE_ORDER_ARGB:
        pixel_format = kSbBlitterPixelDataFormatARGB8;
        break;
      default:
        NOTREACHED() << "Invalid SB_PREFERRED_RGBA_BYTE_ORDER_RGBA"
                     << SB_PREFERRED_RGBA_BYTE_ORDER_RGBA;
    }
    default_device = SbBlitterCreateDefaultDevice();
    ASSERT_TRUE(SbBlitterIsDeviceValid(default_device));
    ASSERT_TRUE(SbBlitterIsPixelFormatSupportedByPixelData(default_device,
                                                           pixel_format));
  }

  virtual void TearDown() {
    if (SbBlitterIsDeviceValid(default_device)) {
      SbBlitterDestroyDevice(default_device);
    }
  }

  TestData GenerateRandomTestData(bool horizontal_brush) {
    int width = 1;
    int height = 1;
    if (horizontal_brush) {
      width = kDefaultSurfaceSizeInPixels;
    } else {
      height = kDefaultSurfaceSizeInPixels;
    }

    return ::GenerateRandomTestData(default_device, width, height,
                                    pixel_format);
  }

  LinearGradientCache cache;
  SbBlitterDevice default_device;
  SbBlitterPixelDataFormat pixel_format;
};

TEST_F(LinearGradientCacheFixture, CheckConstructDestruct) {}

TEST_F(LinearGradientCacheFixture, DoNotCacheInvalidSurface) {
  math::PointF source(0.0f, 0.0f);
  math::PointF dest(15.0f, 20.0f);
  ColorStopList stops;
  ColorRGBA color1(0.8, 1.0, 0.5);
  ColorRGBA color2(0.6, 1.0, 0.5);
  stops.push_back(ColorStop(0.0, color1));
  stops.push_back(ColorStop(1.0, color2));
  LinearGradientBrush brush(source, dest, stops);
  SbBlitterSurface surface = kSbBlitterInvalidSurface;
  bool inserted_in_cache = cache.Put(brush, surface);
  EXPECT_FALSE(inserted_in_cache);
}

TEST_F(LinearGradientCacheFixture, PutSuccessful) {
  TestData test_data(GenerateRandomTestData(true));
  bool inserted_in_cache = cache.Put(test_data.brush, test_data.surface);
  EXPECT_TRUE(inserted_in_cache);
}

TEST_F(LinearGradientCacheFixture, ValidGet) {
  TestData test_data(GenerateRandomTestData(true));
  cache.Put(test_data.brush, test_data.surface);
  SbBlitterSurface surface = cache.Get(test_data.brush);
  EXPECT_TRUE(SbBlitterIsSurfaceValid(surface));
}

TEST_F(LinearGradientCacheFixture, InvalidGet) {
  TestData test_data_1(GenerateRandomTestData(true));
  TestData test_data_2(GenerateRandomTestData(false));
  cache.Put(test_data_1.brush, test_data_1.surface);
  SbBlitterSurface surface = cache.Get(test_data_2.brush);
  SbBlitterDestroySurface(test_data_2.surface);
  EXPECT_FALSE(SbBlitterIsSurfaceValid(surface));
}

TEST_F(LinearGradientCacheFixture, FetchTwoItems) {
  TestData test_data_1(GenerateRandomTestData(true));
  cache.Put(test_data_1.brush, test_data_1.surface);
  TestData test_data_2(GenerateRandomTestData(false));
  cache.Put(test_data_2.brush, test_data_2.surface);

  SbBlitterSurface surface1 = cache.Get(test_data_1.brush);
  EXPECT_TRUE(SbBlitterIsSurfaceValid(surface1));
  SbBlitterSurface surface2 = cache.Get(test_data_2.brush);
  EXPECT_TRUE(SbBlitterIsSurfaceValid(surface2));
}

TEST_F(LinearGradientCacheFixture, GetSameSizeGradientInSameDirection) {
  TestData test_data_1(GenerateRandomTestData(true));
  cache.Put(test_data_1.brush, test_data_1.surface);

  PointF source(test_data_1.brush.source());
  source.set_x(source.x() + 20);
  source.set_y(source.y() + 10);
  PointF dest(test_data_1.brush.dest());
  dest.set_x(dest.x() + 20);
  dest.set_y(dest.y() + 10);
  LinearGradientBrush similar_brush(source, dest,
                                    test_data_1.brush.color_stops());

  SbBlitterSurface surface1 = cache.Get(similar_brush);

  EXPECT_TRUE(SbBlitterIsSurfaceValid(surface1));
  EXPECT_TRUE(surface1 == test_data_1.surface);
}

}  // namespace blitter
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt

#endif  // SB_HAS(BLITTER)
