// 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 <Cocoa/Cocoa.h>
#include <stddef.h>

#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_util_mac.h"
#include "ui/gfx/image/image_unittest_util.h"

namespace {

// Returns true if the structure of |ns_image| matches the structure
// described by |width|, |height|, and |scales|.
// The structure matches if:
// - |ns_image| is not nil.
// - |ns_image| has NSImageReps of |scales|.
// - Each of the NSImageReps has a pixel size of [|ns_image| size] *
//   scale.
bool NSImageStructureMatches(
    NSImage* ns_image,
    int width,
    int height,
    const std::vector<float>& scales) {
  if (!ns_image ||
      [ns_image size].width != width ||
      [ns_image size].height != height ||
      [ns_image representations].count != scales.size()) {
    return false;
  }

  for (size_t i = 0; i < scales.size(); ++i) {
    float scale = scales[i];
    bool found_match = false;
    for (size_t j = 0; j < [ns_image representations].count; ++j) {
      NSImageRep* ns_image_rep = [ns_image representations][j];
      if (ns_image_rep &&
          [ns_image_rep pixelsWide] == width * scale &&
          [ns_image_rep pixelsHigh] == height * scale) {
        found_match = true;
        break;
      }
    }
    if (!found_match)
      return false;
  }
  return true;
}

void BitmapImageRep(int width, int height,
     NSBitmapImageRep** image_rep) {
  *image_rep = [[[NSBitmapImageRep alloc]
      initWithBitmapDataPlanes:NULL
                    pixelsWide:width
                   pixelsHigh:height
                bitsPerSample:8
              samplesPerPixel:3
                     hasAlpha:NO
                     isPlanar:NO
               colorSpaceName:NSDeviceRGBColorSpace
                 bitmapFormat:0
                  bytesPerRow:0
                 bitsPerPixel:0]
      autorelease];
  unsigned char* image_rep_data = [*image_rep bitmapData];
  for (int i = 0; i < width * height * 3; ++i)
    image_rep_data[i] = 255;
}

class ImageMacTest : public testing::Test {
 public:
  ImageMacTest() {
    gfx::ImageSkia::SetSupportedScales(gfx::test::Get1xAnd2xScales());
  }

  ImageMacTest(const ImageMacTest&) = delete;
  ImageMacTest& operator=(const ImageMacTest&) = delete;
};

namespace gt = gfx::test;

TEST_F(ImageMacTest, MultiResolutionNSImageToImageSkia) {
  const int kWidth1x = 10;
  const int kHeight1x = 12;
  const int kWidth2x = 20;
  const int kHeight2x = 24;

  NSBitmapImageRep* ns_image_rep1;
  BitmapImageRep(kWidth1x, kHeight1x, &ns_image_rep1);
  NSBitmapImageRep* ns_image_rep2;
  BitmapImageRep(kWidth2x, kHeight2x, &ns_image_rep2);
  base::scoped_nsobject<NSImage> ns_image(
      [[NSImage alloc] initWithSize:NSMakeSize(kWidth1x, kHeight1x)]);
  [ns_image addRepresentation:ns_image_rep1];
  [ns_image addRepresentation:ns_image_rep2];

  gfx::Image image(ns_image);

  EXPECT_EQ(1u, image.RepresentationCount());

  const gfx::ImageSkia* image_skia = image.ToImageSkia();

  std::vector<float> scales;
  scales.push_back(1.0f);
  scales.push_back(2.0f);
  EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
                                            scales));

  // ToImageSkia should create a second representation.
  EXPECT_EQ(2u, image.RepresentationCount());
}

// Test that convertng to an ImageSkia from an NSImage with scale factors
// other than 1x and 2x results in an ImageSkia with scale factors 1x and
// 2x;
TEST_F(ImageMacTest, UnalignedMultiResolutionNSImageToImageSkia) {
  const int kWidth1x = 10;
  const int kHeight1x= 12;
  const int kWidth4x = 40;
  const int kHeight4x = 48;

  NSBitmapImageRep* ns_image_rep4;
  BitmapImageRep(kWidth4x, kHeight4x, &ns_image_rep4);
  base::scoped_nsobject<NSImage> ns_image(
      [[NSImage alloc] initWithSize:NSMakeSize(kWidth1x, kHeight1x)]);
  [ns_image addRepresentation:ns_image_rep4];

  gfx::Image image(ns_image);

  EXPECT_EQ(1u, image.RepresentationCount());

  const gfx::ImageSkia* image_skia = image.ToImageSkia();

  std::vector<float> scales;
  scales.push_back(1.0f);
  scales.push_back(2.0f);
  EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
                                            scales));

  // ToImageSkia should create a second representation.
  EXPECT_EQ(2u, image.RepresentationCount());
}

TEST_F(ImageMacTest, MultiResolutionImageSkiaToNSImage) {
  const int kWidth1x = 10;
  const int kHeight1x= 12;
  const int kWidth2x = 20;
  const int kHeight2x = 24;

  gfx::ImageSkia image_skia;
  image_skia.AddRepresentation(gfx::ImageSkiaRep(
      gt::CreateBitmap(kWidth1x, kHeight1x), 1.0f));
  image_skia.AddRepresentation(gfx::ImageSkiaRep(
      gt::CreateBitmap(kWidth2x, kHeight2x), 2.0f));

  gfx::Image image(image_skia);

  EXPECT_EQ(1u, image.RepresentationCount());
  EXPECT_EQ(2u, image.ToImageSkia()->image_reps().size());

  NSImage* ns_image = image.ToNSImage();

  std::vector<float> scales;
  scales.push_back(1.0f);
  scales.push_back(2.0f);
  EXPECT_TRUE(NSImageStructureMatches(ns_image, kWidth1x, kHeight1x, scales));

  // Request for NSImage* should create a second representation.
  EXPECT_EQ(2u, image.RepresentationCount());
}

TEST_F(ImageMacTest, MultiResolutionPNGToNSImage) {
  const int kSize1x = 25;
  const int kSize2x = 50;

  scoped_refptr<base::RefCountedMemory> bytes1x = gt::CreatePNGBytes(kSize1x);
  scoped_refptr<base::RefCountedMemory> bytes2x = gt::CreatePNGBytes(kSize2x);
  std::vector<gfx::ImagePNGRep> image_png_reps;
  image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, 1.0f));
  image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, 2.0f));

  gfx::Image image(image_png_reps);

  NSImage* ns_image = image.ToNSImage();
  std::vector<float> scales;
  scales.push_back(1.0f);
  scales.push_back(2.0f);
  EXPECT_TRUE(NSImageStructureMatches(ns_image, kSize1x, kSize1x, scales));

  // Converting from PNG to NSImage should not go through ImageSkia.
  EXPECT_FALSE(image.HasRepresentation(gfx::Image::kImageRepSkia));

  // Convert to ImageSkia to check pixel contents of NSImageReps.
  gfx::ImageSkia image_skia = gfx::ImageSkiaFromNSImage(ns_image);
  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
      *bytes1x, image_skia.GetRepresentation(1.0f).GetBitmap(),
      gt::MaxColorSpaceConversionColorShift()));
  EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
      *bytes2x, image_skia.GetRepresentation(2.0f).GetBitmap(),
      gt::MaxColorSpaceConversionColorShift()));
}

} // namespace
