// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#define FML_USED_ON_EMBEDDER

#include <limits>
#include <utility>

#include "flutter/shell/platform/embedder/tests/embedder_test_backingstore_producer.h"
#include "flutter/shell/platform/embedder/tests/embedder_unittests_util.h"

#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkSurface.h"

namespace flutter {
namespace testing {

sk_sp<SkSurface> CreateRenderSurface(const FlutterLayer& layer,
                                     GrDirectContext* context) {
  const auto image_info =
      SkImageInfo::MakeN32Premul(layer.size.width, layer.size.height);
  auto surface = context ? SkSurface::MakeRenderTarget(
                               context,                   // context
                               skgpu::Budgeted::kNo,      // budgeted
                               image_info,                // image info
                               1,                         // sample count
                               kTopLeft_GrSurfaceOrigin,  // surface origin
                               nullptr,                   // surface properties
                               false                      // mipmaps

                               )
                         : SkSurface::MakeRaster(image_info);
  FML_CHECK(surface != nullptr);
  return surface;
}

// Normalizes the color-space, color-type and alpha-type for comparison.
static sk_sp<SkData> NormalizeImage(const sk_sp<SkImage>& image) {
  // To avoid clipping, convert to a very wide gamut, and a high bit depth.
  sk_sp<SkColorSpace> norm_colorspace = SkColorSpace::MakeRGB(
      SkNamedTransferFn::kRec2020, SkNamedGamut::kRec2020);
  SkImageInfo norm_image_info =
      SkImageInfo::Make(image->width(), image->height(),
                        SkColorType::kR16G16B16A16_unorm_SkColorType,
                        SkAlphaType::kUnpremul_SkAlphaType, norm_colorspace);
  size_t row_bytes = norm_image_info.minRowBytes();
  size_t size = norm_image_info.computeByteSize(row_bytes);
  sk_sp<SkData> data = SkData::MakeUninitialized(size);
  if (!data) {
    FML_CHECK(false) << "Unable to allocate data.";
  }

  bool success = image->readPixels(norm_image_info, data->writable_data(),
                                   row_bytes, 0, 0);
  if (!success) {
    FML_CHECK(false) << "Unable to read pixels.";
  }

  return data;
}

bool RasterImagesAreSame(const sk_sp<SkImage>& a, const sk_sp<SkImage>& b) {
  if (!a || !b) {
    return false;
  }

  FML_CHECK(!a->isTextureBacked());
  FML_CHECK(!b->isTextureBacked());

  sk_sp<SkData> normalized_a = NormalizeImage(a);
  sk_sp<SkData> normalized_b = NormalizeImage(b);

  return normalized_a->equals(normalized_b.get());
}

std::string FixtureNameForBackend(EmbedderTestContextType backend,
                                  const std::string& name) {
  switch (backend) {
    case EmbedderTestContextType::kVulkanContext:
      return "vk_" + name;
    default:
      return name;
  }
}

EmbedderTestBackingStoreProducer::RenderTargetType GetRenderTargetFromBackend(
    EmbedderTestContextType backend,
    bool opengl_framebuffer) {
  switch (backend) {
    case EmbedderTestContextType::kVulkanContext:
      return EmbedderTestBackingStoreProducer::RenderTargetType::kVulkanImage;
    case EmbedderTestContextType::kOpenGLContext:
      if (opengl_framebuffer) {
        return EmbedderTestBackingStoreProducer::RenderTargetType::
            kOpenGLFramebuffer;
      }
      return EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLTexture;
    case EmbedderTestContextType::kMetalContext:
      return EmbedderTestBackingStoreProducer::RenderTargetType::kMetalTexture;
    case EmbedderTestContextType::kSoftwareContext:
      return EmbedderTestBackingStoreProducer::RenderTargetType::
          kSoftwareBuffer;
  }
}

void ConfigureBackingStore(FlutterBackingStore& backing_store,
                           EmbedderTestContextType backend,
                           bool opengl_framebuffer) {
  switch (backend) {
    case EmbedderTestContextType::kVulkanContext:
      backing_store.type = kFlutterBackingStoreTypeVulkan;
      break;
    case EmbedderTestContextType::kOpenGLContext:
      if (opengl_framebuffer) {
        backing_store.type = kFlutterBackingStoreTypeOpenGL;
        backing_store.open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
      } else {
        backing_store.type = kFlutterBackingStoreTypeOpenGL;
        backing_store.open_gl.type = kFlutterOpenGLTargetTypeTexture;
      }
      break;
    case EmbedderTestContextType::kMetalContext:
      backing_store.type = kFlutterBackingStoreTypeMetal;
      break;
    case EmbedderTestContextType::kSoftwareContext:
      backing_store.type = kFlutterBackingStoreTypeSoftware;
      break;
  }
}

bool WriteImageToDisk(const fml::UniqueFD& directory,
                      const std::string& name,
                      const sk_sp<SkImage>& image) {
  if (!image) {
    return false;
  }

  auto data = image->encodeToData();

  if (!data) {
    return false;
  }

  fml::NonOwnedMapping mapping(static_cast<const uint8_t*>(data->data()),
                               data->size());
  return WriteAtomically(directory, name.c_str(), mapping);
}

bool ImageMatchesFixture(const std::string& fixture_file_name,
                         const sk_sp<SkImage>& scene_image) {
  fml::FileMapping fixture_image_mapping(OpenFixture(fixture_file_name));

  FML_CHECK(fixture_image_mapping.GetSize() != 0u)
      << "Could not find fixture: " << fixture_file_name;

  auto encoded_image = SkData::MakeWithoutCopy(
      fixture_image_mapping.GetMapping(), fixture_image_mapping.GetSize());
  auto fixture_image =
      SkImages::DeferredFromEncodedData(std::move(encoded_image))
          ->makeRasterImage();

  FML_CHECK(fixture_image) << "Could not create image from fixture: "
                           << fixture_file_name;

  FML_CHECK(scene_image) << "Invalid scene image.";

  auto scene_image_subset = scene_image->makeSubset(
      SkIRect::MakeWH(fixture_image->width(), fixture_image->height()));

  FML_CHECK(scene_image_subset)
      << "Could not create image subset for fixture comparison: "
      << scene_image_subset;

  const auto images_are_same =
      RasterImagesAreSame(scene_image_subset, fixture_image);

  // If the images are not the same, this predicate is going to indicate test
  // failure. Dump both the actual image and the expectation to disk to the
  // test author can figure out what went wrong.
  if (!images_are_same) {
    const auto fixtures_path = GetFixturesPath();

    const auto actual_file_name = "actual_" + fixture_file_name;
    const auto expect_file_name = "expectation_" + fixture_file_name;

    auto fixtures_fd = OpenFixturesDirectory();

    FML_CHECK(
        WriteImageToDisk(fixtures_fd, actual_file_name, scene_image_subset))
        << "Could not write file to disk: " << actual_file_name;

    FML_CHECK(WriteImageToDisk(fixtures_fd, expect_file_name, fixture_image))
        << "Could not write file to disk: " << expect_file_name;

    FML_LOG(ERROR) << "Image did not match expectation." << std::endl
                   << "Expected:"
                   << fml::paths::JoinPaths({fixtures_path, expect_file_name})
                   << std::endl
                   << "Got:"
                   << fml::paths::JoinPaths({fixtures_path, actual_file_name})
                   << std::endl;
  }
  return images_are_same;
}

bool ImageMatchesFixture(const std::string& fixture_file_name,
                         std::future<sk_sp<SkImage>>& scene_image) {
  return ImageMatchesFixture(fixture_file_name, scene_image.get());
}

bool SurfacePixelDataMatchesBytes(SkSurface* surface,
                                  const std::vector<uint8_t>& bytes) {
  SkPixmap pixmap;
  auto ok = surface->peekPixels(&pixmap);
  if (!ok) {
    return false;
  }

  auto matches = (pixmap.rowBytes() == bytes.size()) &&
                 (memcmp(bytes.data(), pixmap.addr(), bytes.size()) == 0);

  if (!matches) {
    FML_LOG(ERROR) << "SkImage pixel data didn't match bytes.";

    {
      const uint8_t* addr = static_cast<const uint8_t*>(pixmap.addr());
      std::stringstream stream;
      for (size_t i = 0; i < pixmap.computeByteSize(); ++i) {
        stream << "0x" << std::setfill('0') << std::setw(2) << std::uppercase
               << std::hex << static_cast<int>(addr[i]);
        if (i != pixmap.computeByteSize() - 1) {
          stream << ", ";
        }
      }
      FML_LOG(ERROR) << "  Actual:   " << stream.str();
    }
    {
      std::stringstream stream;
      for (auto b = bytes.begin(); b != bytes.end(); ++b) {
        stream << "0x" << std::setfill('0') << std::setw(2) << std::uppercase
               << std::hex << static_cast<int>(*b);
        if (b != bytes.end() - 1) {
          stream << ", ";
        }
      }
      FML_LOG(ERROR) << "  Expected: " << stream.str();
    }
  }

  return matches;
}

bool SurfacePixelDataMatchesBytes(std::future<SkSurface*>& surface_future,
                                  const std::vector<uint8_t>& bytes) {
  return SurfacePixelDataMatchesBytes(surface_future.get(), bytes);
}

void FilterMutationsByType(
    const FlutterPlatformViewMutation** mutations,
    size_t count,
    FlutterPlatformViewMutationType type,
    const std::function<void(const FlutterPlatformViewMutation& mutation)>&
        handler) {
  if (mutations == nullptr) {
    return;
  }

  for (size_t i = 0; i < count; ++i) {
    const FlutterPlatformViewMutation* mutation = mutations[i];
    if (mutation->type != type) {
      continue;
    }

    handler(*mutation);
  }
}

void FilterMutationsByType(
    const FlutterPlatformView* view,
    FlutterPlatformViewMutationType type,
    const std::function<void(const FlutterPlatformViewMutation& mutation)>&
        handler) {
  return FilterMutationsByType(view->mutations, view->mutations_count, type,
                               handler);
}

SkMatrix GetTotalMutationTransformationMatrix(
    const FlutterPlatformViewMutation** mutations,
    size_t count) {
  SkMatrix collected;

  FilterMutationsByType(
      mutations, count, kFlutterPlatformViewMutationTypeTransformation,
      [&](const auto& mutation) {
        collected.preConcat(SkMatrixMake(mutation.transformation));
      });

  return collected;
}

SkMatrix GetTotalMutationTransformationMatrix(const FlutterPlatformView* view) {
  return GetTotalMutationTransformationMatrix(view->mutations,
                                              view->mutations_count);
}

}  // namespace testing
}  // namespace flutter
