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


import 'dart:typed_data' show Uint8List;
import 'dart:ui' as ui show instantiateImageCodec, Codec;
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart' show ServicesBinding;

import 'image_cache.dart';
import 'shader_warm_up.dart';

/// Binding for the painting library.
///
/// Hooks into the cache eviction logic to clear the image cache.
///
/// Requires the [ServicesBinding] to be mixed in earlier.
mixin PaintingBinding on BindingBase, ServicesBinding {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    _imageCache = createImageCache();
    shaderWarmUp?.execute();
  }

  /// The current [PaintingBinding], if one has been created.
  static PaintingBinding? get instance => _instance;
  static PaintingBinding? _instance;

  /// [ShaderWarmUp] instance to be executed during [initInstances].
  ///
  /// Defaults to `null`, meaning no shader warm-up is done. Some platforms may
  /// not support shader warm-up before at least one frame has been displayed.
  ///
  /// If the application has scenes that require the compilation of complex
  /// shaders, it may cause jank in the middle of an animation or interaction.
  /// In that case, setting [shaderWarmUp] to a custom [ShaderWarmUp] before
  /// creating the binding (usually before [runApp] for normal Flutter apps, and
  /// before [enableFlutterDriverExtension] for Flutter driver tests) may help
  /// if that object paints the difficult scene in its
  /// [ShaderWarmUp.warmUpOnCanvas] method, as this allows Flutter to
  /// pre-compile and cache the required shaders during startup.
  ///
  /// Currently the warm-up happens synchronously on the raster thread which
  /// means the rendering of the first frame on the raster thread will be
  /// postponed until the warm-up is finished.
  ///
  /// The warm up is only costly (100ms-200ms, depending on the shaders to
  /// compile) during the first run after the installation or a data wipe. The
  /// warm up does not block the platform thread so there should be no
  /// "Application Not Responding" warning.
  ///
  /// If this is null, no shader warm-up is executed.
  ///
  /// See also:
  ///
  ///  * [ShaderWarmUp], the interface for implementing custom warm-up scenes.
  ///  * <https://flutter.dev/docs/perf/rendering/shader>
  static ShaderWarmUp? shaderWarmUp;

  /// The singleton that implements the Flutter framework's image cache.
  ///
  /// The cache is used internally by [ImageProvider] and should generally not
  /// be accessed directly.
  ///
  /// The image cache is created during startup by the [createImageCache]
  /// method.
  ImageCache? get imageCache => _imageCache;
  ImageCache? _imageCache;

  /// Creates the [ImageCache] singleton (accessible via [imageCache]).
  ///
  /// This method can be overridden to provide a custom image cache.
  @protected
  ImageCache createImageCache() => ImageCache();

  /// Calls through to [dart:ui.instantiateImageCodec] from [ImageCache].
  ///
  /// The `cacheWidth` and `cacheHeight` parameters, when specified, indicate
  /// the size to decode the image to.
  ///
  /// Both `cacheWidth` and `cacheHeight` must be positive values greater than
  /// or equal to 1, or null. It is valid to specify only one of `cacheWidth`
  /// and `cacheHeight` with the other remaining null, in which case the omitted
  /// dimension will be scaled to maintain the aspect ratio of the original
  /// dimensions. When both are null or omitted, the image will be decoded at
  /// its native resolution.
  ///
  /// The `allowUpscaling` parameter determines whether the `cacheWidth` or
  /// `cacheHeight` parameters are clamped to the intrinsic width and height of
  /// the original image. By default, the dimensions are clamped to avoid
  /// unnecessary memory usage for images. Callers that wish to display an image
  /// above its native resolution should prefer scaling the canvas the image is
  /// drawn into.
  Future<ui.Codec> instantiateImageCodec(
    Uint8List bytes, {
    int? cacheWidth,
    int? cacheHeight,
    bool allowUpscaling = false,
  }) {
    assert(cacheWidth == null || cacheWidth > 0);
    assert(cacheHeight == null || cacheHeight > 0);
    assert(allowUpscaling != null);
    return ui.instantiateImageCodec(
      bytes,
      targetWidth: cacheWidth,
      targetHeight: cacheHeight,
      allowUpscaling: allowUpscaling,
    );
  }

  @override
  void evict(String asset) {
    super.evict(asset);
    imageCache!.clear();
    imageCache!.clearLiveImages();
  }

  @override
  void handleMemoryPressure() {
    super.handleMemoryPressure();
    imageCache?.clear();
  }

  /// Listenable that notifies when the available fonts on the system have
  /// changed.
  ///
  /// System fonts can change when the system installs or removes new font. To
  /// correctly reflect the change, it is important to relayout text related
  /// widgets when this happens.
  ///
  /// Objects that show text and/or measure text (e.g. via [TextPainter] or
  /// [Paragraph]) should listen to this and redraw/remeasure.
  Listenable get systemFonts => _systemFonts;
  final _SystemFontsNotifier _systemFonts = _SystemFontsNotifier();

  @override
  Future<void> handleSystemMessage(Object systemMessage) async {
    await super.handleSystemMessage(systemMessage);
    final Map<String, dynamic> message = systemMessage as Map<String, dynamic>;
    final String type = message['type'] as String;
    switch (type) {
      case 'fontsChange':
        _systemFonts.notifyListeners();
        break;
    }
    return;
  }
}

class _SystemFontsNotifier extends Listenable {
  final Set<VoidCallback> _systemFontsCallbacks = <VoidCallback>{};

  void notifyListeners () {
    for (final VoidCallback callback in _systemFontsCallbacks) {
      callback();
    }
  }

  @override
  void addListener(VoidCallback listener) {
    _systemFontsCallbacks.add(listener);
  }
  @override
  void removeListener(VoidCallback listener) {
    _systemFontsCallbacks.remove(listener);
  }
}

/// The singleton that implements the Flutter framework's image cache.
///
/// The cache is used internally by [ImageProvider] and should generally not be
/// accessed directly.
///
/// The image cache is created during startup by the [PaintingBinding]'s
/// [PaintingBinding.createImageCache] method.
ImageCache? get imageCache => PaintingBinding.instance!.imageCache;
