// 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/shell/platform/android/android_image_generator.h"

#include <memory>

#include <android/bitmap.h>
#include <android/hardware_buffer.h>

#include "flutter/fml/platform/android/jni_util.h"

namespace flutter {

static fml::jni::ScopedJavaGlobalRef<jclass>* g_flutter_jni_class = nullptr;
static jmethodID g_decode_image_method = nullptr;

AndroidImageGenerator::~AndroidImageGenerator() = default;

AndroidImageGenerator::AndroidImageGenerator(sk_sp<SkData> data)
    : data_(data), image_info_(SkImageInfo::MakeUnknown(-1, -1)) {}

const SkImageInfo& AndroidImageGenerator::GetInfo() {
  header_decoded_latch_.Wait();
  return image_info_;
}

unsigned int AndroidImageGenerator::GetFrameCount() const {
  return 1;
}

unsigned int AndroidImageGenerator::GetPlayCount() const {
  return 1;
}

const ImageGenerator::FrameInfo AndroidImageGenerator::GetFrameInfo(
    unsigned int frame_index) const {
  return {.required_frame = std::nullopt,
          .duration = 0,
          .disposal_method = SkCodecAnimation::DisposalMethod::kKeep};
}

SkISize AndroidImageGenerator::GetScaledDimensions(float desired_scale) {
  return GetInfo().dimensions();
}

bool AndroidImageGenerator::GetPixels(const SkImageInfo& info,
                                      void* pixels,
                                      size_t row_bytes,
                                      unsigned int frame_index,
                                      std::optional<unsigned int> prior_frame) {
  fully_decoded_latch_.Wait();

  if (kRGBA_8888_SkColorType != info.colorType()) {
    return false;
  }

  switch (info.alphaType()) {
    case kOpaque_SkAlphaType:
      if (kOpaque_SkAlphaType != GetInfo().alphaType()) {
        return false;
      }
      break;
    case kPremul_SkAlphaType:
      break;
    default:
      return false;
  }

  // TODO(bdero): Override `GetImage()` to use `SkImage::FromAHardwareBuffer` on
  // API level 30+ once it's updated to do symbol lookups and not get
  // preprocessed out in Skia. This will allow for avoiding this copy in
  // cases where the result image doesn't need to be resized.
  memcpy(pixels, software_decoded_data_->data(),
         software_decoded_data_->size());
  return true;
}

void AndroidImageGenerator::DecodeImage() {
  DoDecodeImage();

  header_decoded_latch_.Signal();
  fully_decoded_latch_.Signal();
}

void AndroidImageGenerator::DoDecodeImage() {
  FML_DCHECK(g_flutter_jni_class);
  FML_DCHECK(g_decode_image_method);

  // Call FlutterJNI.decodeImage

  JNIEnv* env = fml::jni::AttachCurrentThread();

  fml::jni::ScopedJavaLocalRef<jobject> direct_buffer(
      env, env->NewDirectByteBuffer(const_cast<void*>(data_->data()),
                                    data_->size()));

  auto bitmap = std::make_unique<fml::jni::ScopedJavaGlobalRef<jobject>>(
      env, env->CallStaticObjectMethod(
               g_flutter_jni_class->obj(), g_decode_image_method,
               direct_buffer.obj(), reinterpret_cast<long>(this)));
  FML_CHECK(fml::jni::CheckException(env));

  if (bitmap->is_null()) {
    return;
  }

  AndroidBitmapInfo info;
  [[maybe_unused]] int status;
  if ((status = AndroidBitmap_getInfo(env, bitmap->obj(), &info)) < 0) {
    FML_DLOG(ERROR) << "Failed to get bitmap info, status=" << status;
    return;
  }
  FML_DCHECK(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888);

  // Lock the android buffer in a shared pointer

  void* pixel_lock;
  if ((status = AndroidBitmap_lockPixels(env, bitmap->obj(), &pixel_lock)) <
      0) {
    FML_DLOG(ERROR) << "Failed to lock pixels, error=" << status;
    return;
  }

  SkData::ReleaseProc on_release = [](const void* ptr, void* context) -> void {
    fml::jni::ScopedJavaGlobalRef<jobject>* bitmap =
        reinterpret_cast<fml::jni::ScopedJavaGlobalRef<jobject>*>(context);
    auto env = fml::jni::AttachCurrentThread();
    AndroidBitmap_unlockPixels(env, bitmap->obj());
    delete bitmap;
  };

  software_decoded_data_ = SkData::MakeWithProc(
      pixel_lock, info.width * info.height * sizeof(uint32_t), on_release,
      bitmap.release());
}

bool AndroidImageGenerator::Register(JNIEnv* env) {
  g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
      env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
  FML_DCHECK(!g_flutter_jni_class->is_null());

  g_decode_image_method = env->GetStaticMethodID(
      g_flutter_jni_class->obj(), "decodeImage",
      "(Ljava/nio/ByteBuffer;J)Landroid/graphics/Bitmap;");
  FML_DCHECK(g_decode_image_method);

  static const JNINativeMethod header_decoded_method = {
      .name = "nativeImageHeaderCallback",
      .signature = "(JII)V",
      .fnPtr = reinterpret_cast<void*>(
          &AndroidImageGenerator::NativeImageHeaderCallback),
  };
  if (env->RegisterNatives(g_flutter_jni_class->obj(), &header_decoded_method,
                           1) != 0) {
    FML_LOG(ERROR)
        << "Failed to register FlutterJNI.nativeImageHeaderCallback method";
    return false;
  }

  return true;
}

std::shared_ptr<ImageGenerator> AndroidImageGenerator::MakeFromData(
    sk_sp<SkData> data,
    fml::RefPtr<fml::TaskRunner> task_runner) {
  std::shared_ptr<AndroidImageGenerator> generator(
      new AndroidImageGenerator(std::move(data)));

  fml::TaskRunner::RunNowOrPostTask(
      task_runner, [generator]() { generator->DecodeImage(); });

  if (generator->IsValidImageData()) {
    return generator;
  }

  return nullptr;
}

void AndroidImageGenerator::NativeImageHeaderCallback(JNIEnv* env,
                                                      jclass jcaller,
                                                      jlong generator_address,
                                                      int width,
                                                      int height) {
  AndroidImageGenerator* generator =
      reinterpret_cast<AndroidImageGenerator*>(generator_address);

  generator->image_info_ = SkImageInfo::Make(
      width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  generator->header_decoded_latch_.Signal();
}

bool AndroidImageGenerator::IsValidImageData() {
  // The generator kicks off an IO task to decode everything, and calls to
  // "GetInfo()" block until either the header has been decoded or decoding has
  // failed, whichever is sooner. The decoder is initialized with a width and
  // height of -1 and will update the dimensions if the image is able to be
  // decoded.
  return GetInfo().height() != -1;
}

}  // namespace flutter
