// 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/lib/ui/painting/picture.h"

#include <memory>

#include "flutter/fml/make_copyable.h"
#include "flutter/lib/ui/painting/canvas.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_args.h"
#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/dart_library_natives.h"
#include "third_party/tonic/dart_persistent_value.h"
#include "third_party/tonic/logging/dart_invoke.h"

namespace flutter {

IMPLEMENT_WRAPPERTYPEINFO(ui, Picture);

#define FOR_EACH_BINDING(V) \
  V(Picture, toImage)       \
  V(Picture, dispose)       \
  V(Picture, GetAllocationSize)

DART_BIND_ALL(Picture, FOR_EACH_BINDING)

fml::RefPtr<Picture> Picture::Create(
    Dart_Handle dart_handle,
    flutter::SkiaGPUObject<SkPicture> picture) {
  auto canvas_picture = fml::MakeRefCounted<Picture>(std::move(picture));

  canvas_picture->AssociateWithDartWrapper(dart_handle);
  return canvas_picture;
}

fml::RefPtr<Picture> Picture::Create(
    Dart_Handle dart_handle,
    flutter::SkiaGPUObject<DisplayList> display_list) {
  auto canvas_picture = fml::MakeRefCounted<Picture>(std::move(display_list));

  canvas_picture->AssociateWithDartWrapper(dart_handle);
  return canvas_picture;
}

Picture::Picture(flutter::SkiaGPUObject<SkPicture> picture)
    : picture_(std::move(picture)) {}

Picture::Picture(flutter::SkiaGPUObject<DisplayList> display_list)
    : display_list_(std::move(display_list)) {}

Picture::~Picture() = default;

Dart_Handle Picture::toImage(uint32_t width,
                             uint32_t height,
                             Dart_Handle raw_image_callback) {
  if (display_list_.skia_object()) {
    return RasterizeToImage(
        [display_list = display_list_.skia_object()](SkCanvas* canvas) {
          display_list->RenderTo(canvas);
        },
        width, height, raw_image_callback);
  } else {
    if (!picture_.skia_object()) {
      return tonic::ToDart("Picture is null");
    }
    return RasterizeToImage(picture_.skia_object(), width, height,
                            raw_image_callback);
  }
}

void Picture::dispose() {
  picture_.reset();
  display_list_.reset();
  ClearDartWrapper();
}

size_t Picture::GetAllocationSize() const {
  if (auto picture = picture_.skia_object()) {
    return picture->approximateBytesUsed() + sizeof(Picture);
  } else if (auto display_list = display_list_.skia_object()) {
    return display_list->bytes() + sizeof(Picture);
  } else {
    return sizeof(Picture);
  }
}

Dart_Handle Picture::RasterizeToImage(sk_sp<SkPicture> picture,
                                      uint32_t width,
                                      uint32_t height,
                                      Dart_Handle raw_image_callback) {
  return RasterizeToImage(
      [picture](SkCanvas* canvas) { canvas->drawPicture(picture); }, width,
      height, raw_image_callback);
}

Dart_Handle Picture::RasterizeToImage(
    std::function<void(SkCanvas*)> draw_callback,
    uint32_t width,
    uint32_t height,
    Dart_Handle raw_image_callback) {
  if (Dart_IsNull(raw_image_callback) || !Dart_IsClosure(raw_image_callback)) {
    return tonic::ToDart("Image callback was invalid");
  }

  if (width == 0 || height == 0) {
    return tonic::ToDart("Image dimensions for scene were invalid.");
  }

  auto* dart_state = UIDartState::Current();
  auto image_callback = std::make_unique<tonic::DartPersistentValue>(
      dart_state, raw_image_callback);
  auto unref_queue = dart_state->GetSkiaUnrefQueue();
  auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner();
  auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner();
  auto snapshot_delegate = dart_state->GetSnapshotDelegate();

  // We can't create an image on this task runner because we don't have a
  // graphics context. Even if we did, it would be slow anyway. Also, this
  // thread owns the sole reference to the layer tree. So we flatten the layer
  // tree into a picture and use that as the thread transport mechanism.

  auto picture_bounds = SkISize::Make(width, height);

  auto ui_task =
      fml::MakeCopyable([image_callback = std::move(image_callback),
                         unref_queue](sk_sp<SkImage> raster_image) mutable {
        auto dart_state = image_callback->dart_state().lock();
        if (!dart_state) {
          // The root isolate could have died in the meantime.
          return;
        }
        tonic::DartState::Scope scope(dart_state);

        if (!raster_image) {
          tonic::DartInvoke(image_callback->Get(), {Dart_Null()});
          return;
        }

        auto dart_image = CanvasImage::Create();
        dart_image->set_image(DlImageGPU::Make(
            {std::move(raster_image), std::move(unref_queue)}));
        auto* raw_dart_image = tonic::ToDart(std::move(dart_image));

        // All done!
        tonic::DartInvoke(image_callback->Get(), {raw_dart_image});

        // image_callback is associated with the Dart isolate and must be
        // deleted on the UI thread.
        image_callback.reset();
      });

  // Kick things off on the raster rask runner.
  fml::TaskRunner::RunNowOrPostTask(
      raster_task_runner, [ui_task_runner, snapshot_delegate, draw_callback,
                           picture_bounds, ui_task] {
        sk_sp<SkImage> raster_image = snapshot_delegate->MakeRasterSnapshot(
            draw_callback, picture_bounds);

        fml::TaskRunner::RunNowOrPostTask(
            ui_task_runner,
            [ui_task, raster_image]() { ui_task(raster_image); });
      });

  return Dart_Null();
}

}  // namespace flutter
