// 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.

#include "flutter/display_list/testing/dl_test_surface_metal.h"
#include "flutter/impeller/display_list/dl_dispatcher.h"
#include "flutter/impeller/display_list/dl_image_impeller.h"
#include "flutter/impeller/typographer/backends/skia/typographer_context_skia.h"

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

namespace flutter {
namespace testing {

class DlMetalSurfaceInstance : public DlSurfaceInstance {
 public:
  explicit DlMetalSurfaceInstance(
      std::unique_ptr<TestMetalSurface> metal_surface)
      : metal_surface_(std::move(metal_surface)) {}
  ~DlMetalSurfaceInstance() = default;

  sk_sp<SkSurface> sk_surface() const override {
    return metal_surface_->GetSurface();
  }

 private:
  std::unique_ptr<TestMetalSurface> metal_surface_;
};

bool DlMetalSurfaceProvider::InitializeSurface(size_t width,
                                               size_t height,
                                               PixelFormat format) {
  if (format != kN32PremulPixelFormat) {
    return false;
  }
  metal_context_ = std::make_unique<TestMetalContext>();
  metal_surface_ = MakeOffscreenSurface(width, height, format);
  return true;
}

std::shared_ptr<DlSurfaceInstance> DlMetalSurfaceProvider::GetPrimarySurface()
    const {
  if (!metal_surface_) {
    return nullptr;
  }
  return metal_surface_;
}

std::shared_ptr<DlSurfaceInstance> DlMetalSurfaceProvider::MakeOffscreenSurface(
    size_t width,
    size_t height,
    PixelFormat format) const {
  auto surface =
      TestMetalSurface::Create(*metal_context_, SkISize::Make(width, height));
  surface->GetSurface()->getCanvas()->clear(SK_ColorTRANSPARENT);
  return std::make_shared<DlMetalSurfaceInstance>(std::move(surface));
}

class DlMetalPixelData : public DlPixelData {
 public:
  explicit DlMetalPixelData(
      std::unique_ptr<impeller::testing::Screenshot> screenshot)
      : screenshot_(std::move(screenshot)),
        addr_(reinterpret_cast<const uint32_t*>(screenshot_->GetBytes())),
        ints_per_row_(screenshot_->GetBytesPerRow() / 4) {
    FML_DCHECK(screenshot_->GetBytesPerRow() == ints_per_row_ * 4);
  }
  ~DlMetalPixelData() override = default;

  const uint32_t* addr32(int x, int y) const override {
    return addr_ + (y * ints_per_row_) + x;
  }
  size_t width() const override { return screenshot_->GetWidth(); }
  size_t height() const override { return screenshot_->GetHeight(); }
  void write(const std::string& path) const override {
    screenshot_->WriteToPNG(path);
  }

 private:
  std::unique_ptr<impeller::testing::Screenshot> screenshot_;
  const uint32_t* addr_;
  const uint32_t ints_per_row_;
};

sk_sp<DlPixelData> DlMetalSurfaceProvider::ImpellerSnapshot(
    const sk_sp<DisplayList>& list,
    int width,
    int height) const {
  InitScreenShotter();
  impeller::DlDispatcher dispatcher;
  dispatcher.drawColor(flutter::DlColor::kTransparent(),
                       flutter::DlBlendMode::kSrc);
  list->Dispatch(dispatcher);
  auto picture = dispatcher.EndRecordingAsPicture();
  return sk_make_sp<DlMetalPixelData>(snapshotter_->MakeScreenshot(
      *aiks_context_, picture, {width, height}, false));
}

sk_sp<DlImage> DlMetalSurfaceProvider::MakeImpellerImage(
    const sk_sp<DisplayList>& list,
    int width,
    int height) const {
  InitScreenShotter();
  impeller::DlDispatcher dispatcher;
  dispatcher.drawColor(flutter::DlColor::kTransparent(),
                       flutter::DlBlendMode::kSrc);
  list->Dispatch(dispatcher);
  auto picture = dispatcher.EndRecordingAsPicture();
  std::shared_ptr<impeller::Image> image =
      picture.ToImage(*aiks_context_, {width, height});
  std::shared_ptr<impeller::Texture> texture = image->GetTexture();
  return impeller::DlImageImpeller::Make(texture);
}

void DlMetalSurfaceProvider::InitScreenShotter() const {
  if (!snapshotter_) {
    snapshotter_.reset(new MetalScreenshotter(/*enable_wide_gamut=*/false));
    auto typographer = impeller::TypographerContextSkia::Make();
    aiks_context_.reset(new impeller::AiksContext(
        snapshotter_->GetPlayground().GetContext(), typographer));
  }
}

}  // namespace testing
}  // namespace flutter
