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

#ifndef FLUTTER_LIB_UI_PAINTING_IMAGE_DESCRIPTOR_H_
#define FLUTTER_LIB_UI_PAINTING_IMAGE_DESCRIPTOR_H_

#include <cstdint>
#include <memory>
#include <optional>

#include "flutter/fml/macros.h"
#include "flutter/lib/ui/dart_wrapper.h"
#include "flutter/lib/ui/painting/image_generator_registry.h"
#include "flutter/lib/ui/painting/immutable_buffer.h"
#include "third_party/skia/include/codec/SkCodec.h"
#include "third_party/skia/include/core/SkImageGenerator.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/src/codec/SkCodecImageGenerator.h"
#include "third_party/tonic/dart_library_natives.h"

namespace flutter {

/// @brief  Creates an image descriptor for encoded or decoded image data,
///         describing the width, height, and bytes per pixel for that image.
///         This class will hold a reference on the underlying image data, and
///         in the case of compressed data, an `ImageGenerator` for the data.
///         The Codec initialization actually happens in initEncoded, making
///         `initstantiateCodec` a lightweight operation.
/// @see    `ImageGenerator`
class ImageDescriptor : public RefCountedDartWrappable<ImageDescriptor> {
 public:
  ~ImageDescriptor() override = default;

  // This must be kept in sync with the enum in painting.dart
  enum PixelFormat {
    kRGBA8888,
    kBGRA8888,
  };

  /// @brief  Asynchronously initlializes an ImageDescriptor for an encoded
  ///         image, as long as the format is recognized by an encoder installed
  ///         in the `ImageGeneratorRegistry`. Calling this method will create
  ///         an `ImageGenerator` and read EXIF corrected dimensions from the
  ///         image data.
  /// @see    `ImageGeneratorRegistry`
  static void initEncoded(Dart_NativeArguments args);

  /// @brief  Synchronously initializes an `ImageDescriptor` for decompressed
  ///         image data as specified by the `PixelFormat`.
  static void initRaw(Dart_Handle descriptor_handle,
                      fml::RefPtr<ImmutableBuffer> data,
                      int width,
                      int height,
                      int row_bytes,
                      PixelFormat pixel_format);

  /// @brief  Associates a flutter::Codec object with the dart.ui Codec handle.
  void instantiateCodec(Dart_Handle codec, int target_width, int target_height);

  /// @brief  The width of this image, EXIF oriented if applicable.
  int width() const { return image_info_.width(); }

  /// @brief  The height of this image. EXIF oriented if applicable.
  int height() const { return image_info_.height(); }

  /// @brief  The bytes per pixel of the image.
  int bytesPerPixel() const { return image_info_.bytesPerPixel(); }

  /// @brief  The byte length of the first row of the image.
  ///         Defaults to width() * 4.
  int row_bytes() const {
    return row_bytes_.value_or(
        static_cast<size_t>(image_info_.width() * image_info_.bytesPerPixel()));
  }

  /// @brief  Whether the given `target_width` or `target_height` differ from
  ///         `width()` and `height()` respectively.
  bool should_resize(int target_width, int target_height) const {
    return target_width != width() || target_height != height();
  }

  /// @brief  The underlying buffer for this image.
  sk_sp<SkData> data() const { return buffer_; }

  sk_sp<SkImage> image() const;

  /// @brief  Whether this descriptor represents compressed (encoded) data or
  ///         not.
  bool is_compressed() const { return !!generator_; }

  /// @brief  The orientation corrected image info for this image.
  const SkImageInfo& image_info() const { return image_info_; }

  /// @brief  Gets the scaled dimensions of this image, if backed by an
  ///         `ImageGenerator` that can perform efficient subpixel scaling.
  /// @see    `ImageGenerator::GetScaledDimensions`
  SkISize get_scaled_dimensions(float scale) {
    if (generator_) {
      return generator_->GetScaledDimensions(scale);
    }
    return image_info_.dimensions();
  }

  /// @brief  Gets pixels for this image transformed based on the EXIF
  ///         orientation tag, if applicable.
  bool get_pixels(const SkPixmap& pixmap) const;

  void dispose() {
    buffer_.reset();
    generator_.reset();
    ClearDartWrapper();
  }

  size_t GetAllocationSize() const override {
    return sizeof(ImageDescriptor) + sizeof(SkImageInfo) + buffer_->size();
  }

  static void RegisterNatives(tonic::DartLibraryNatives* natives);

 private:
  ImageDescriptor(sk_sp<SkData> buffer,
                  const SkImageInfo& image_info,
                  std::optional<size_t> row_bytes);
  ImageDescriptor(sk_sp<SkData> buffer,
                  std::shared_ptr<ImageGenerator> generator);

  sk_sp<SkData> buffer_;
  std::shared_ptr<ImageGenerator> generator_;
  const SkImageInfo image_info_;
  std::optional<size_t> row_bytes_;

  const SkImageInfo CreateImageInfo() const;

  DEFINE_WRAPPERTYPEINFO();
  FML_FRIEND_MAKE_REF_COUNTED(ImageDescriptor);
  FML_DISALLOW_COPY_AND_ASSIGN(ImageDescriptor);

  friend class ImageDecoderFixtureTest;
};

}  // namespace flutter

#endif  // FLUTTER_LIB_UI_PAINTING_IMAGE_DESCRIPTOR_H_
