// 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:ui' as ui;

import 'assertions.dart';
import 'constants.dart';
import 'diagnostics.dart';

const bool _kMemoryAllocations = bool.fromEnvironment('flutter.memory_allocations');

/// If true, Flutter objects dispatch the memory allocation events.
///
/// By default, the constant is true for debug mode and false
/// for profile and release modes.
/// To enable the dispatching for release mode, pass the compilation flag
/// `--dart-define=flutter.memory_allocations=true`.
const bool kFlutterMemoryAllocationsEnabled = _kMemoryAllocations || kDebugMode;

const String _dartUiLibrary = 'dart:ui';

class _FieldNames {
  static const String eventType = 'eventType';
  static const String libraryName = 'libraryName';
  static const String className = 'className';
}

/// A lifecycle event of an object.
abstract class ObjectEvent{
  /// Creates an instance of [ObjectEvent].
  ObjectEvent({
    required this.object,
  });

  /// Reference to the object.
  ///
  /// The reference should not be stored in any
  /// long living place as it will prevent garbage collection.
  final Object object;

  /// The representation of the event in a form, acceptible by a
  /// pure dart library, that cannot depend on Flutter.
  ///
  /// The method enables code like:
  /// ```dart
  /// void myDartMethod(Map<Object, Map<String, Object>> event) {}
  /// MemoryAllocations.instance
  ///   .addListener((ObjectEvent event) => myDartMethod(event.toMap()));
  /// ```
  Map<Object, Map<String, Object>> toMap();
}

/// A listener of [ObjectEvent].
typedef ObjectEventListener = void Function(ObjectEvent);

/// An event that describes creation of an object.
class ObjectCreated extends ObjectEvent {
  /// Creates an instance of [ObjectCreated].
  ObjectCreated({
    required this.library,
    required this.className,
    required super.object,
  });

  /// Name of the instrumented library.
  final String library;

  /// Name of the instrumented class.
  final String className;

  @override
  Map<Object, Map<String, Object>> toMap() {
    return <Object, Map<String, Object>>{object: <String, Object>{
      _FieldNames.libraryName: library,
      _FieldNames.className: className,
      _FieldNames.eventType: 'created',
    }};
  }
}

/// An event that describes disposal of an object.
class ObjectDisposed extends ObjectEvent {
  /// Creates an instance of [ObjectDisposed].
  ObjectDisposed({
    required super.object,
  });

  @override
  Map<Object, Map<String, Object>> toMap() {
    return <Object, Map<String, Object>>{object: <String, Object>{
      _FieldNames.eventType: 'disposed',
    }};
  }
}

/// An interface for listening to object lifecycle events.
///
/// If [kFlutterMemoryAllocationsEnabled] is true,
/// [MemoryAllocations] listens to creation and disposal events
/// for disposable objects in Flutter Framework.
/// To dispatch events for other objects, invoke
/// [MemoryAllocations.dispatchObjectEvent].
///
/// Use this class with condition `kFlutterMemoryAllocationsEnabled`,
/// to make sure not to increase size of the application by the code
/// of the class, if memory allocations are disabled.
///
/// The class is optimized for massive event flow and small number of
/// added or removed listeners.
class MemoryAllocations {
  MemoryAllocations._();

  /// The shared instance of [MemoryAllocations].
  ///
  /// Only call this when [kFlutterMemoryAllocationsEnabled] is true.
  static final MemoryAllocations instance = MemoryAllocations._();

  /// List of listeners.
  ///
  /// The elements are nullable, because the listeners should be removable
  /// while iterating through the list.
  List<ObjectEventListener?>? _listeners;

  /// Register a listener that is called every time an object event is
  /// dispatched.
  ///
  /// Listeners can be removed with [removeListener].
  ///
  /// Only call this when [kFlutterMemoryAllocationsEnabled] is true.
  void addListener(ObjectEventListener listener){
    if (!kFlutterMemoryAllocationsEnabled) {
      return;
    }
    if (_listeners == null) {
      _listeners = <ObjectEventListener?>[];
      _subscribeToSdkObjects();
    }
    _listeners!.add(listener);
  }

  /// Number of active notification loops.
  ///
  /// When equal to zero, we can delete listeners from the list,
  /// otherwise should null them.
  int _activeDispatchLoops = 0;

  /// If true, listeners were nulled by [removeListener].
  bool _listenersContainNulls = false;

  /// Stop calling the given listener every time an object event is
  /// dispatched.
  ///
  /// Listeners can be added with [addListener].
  ///
  /// Only call this when [kFlutterMemoryAllocationsEnabled] is true.
  void removeListener(ObjectEventListener listener){
    if (!kFlutterMemoryAllocationsEnabled) {
      return;
    }
    final List<ObjectEventListener?>? listeners = _listeners;
    if (listeners == null) {
      return;
    }

    if (_activeDispatchLoops > 0) {
      // If there are active dispatch loops, listeners.remove
      // should not be invoked, as it will
      // break the dispatch loops correctness.
      for (int i = 0; i < listeners.length; i++) {
        if (listeners[i] == listener) {
          listeners[i] = null;
          _listenersContainNulls = true;
        }
      }
    } else {
      listeners.removeWhere((ObjectEventListener? l) => l == listener);
      _checkListenersForEmptiness();
    }
  }

  void _tryDefragmentListeners() {
    if (_activeDispatchLoops > 0 || !_listenersContainNulls) {
      return;
    }
    _listeners?.removeWhere((ObjectEventListener? e) => e == null);
    _listenersContainNulls = false;
    _checkListenersForEmptiness();
  }

  void _checkListenersForEmptiness() {
    if (_listeners?.isEmpty ?? false) {
      _listeners = null;
      _unSubscribeFromSdkObjects();
    }
  }

  /// Return true if there are listeners.
  ///
  /// If there is no listeners, the app can save on creating the event object.
  ///
  /// Only call this when [kFlutterMemoryAllocationsEnabled] is true.
  bool get hasListeners {
    if (!kFlutterMemoryAllocationsEnabled) {
      return false;
    }
    if (_listenersContainNulls) {
      return _listeners?.firstWhere((ObjectEventListener? l) => l != null) != null;
    }
    return _listeners?.isNotEmpty ?? false;
  }

  /// Dispatch a new object event to listeners.
  ///
  /// Exceptions thrown by listeners will be caught and reported using
  /// [FlutterError.reportError].
  ///
  /// Listeners added during an event dispatching, will start being invoked
  /// for next events, but will be skipped for this event.
  ///
  /// Listeners, removed during an event dispatching, will not be invoked
  /// after the removal.
  ///
  /// Only call this when [kFlutterMemoryAllocationsEnabled] is true.
  void dispatchObjectEvent(ObjectEvent event) {
    if (!kFlutterMemoryAllocationsEnabled) {
      return;
    }
    final List<ObjectEventListener?>? listeners = _listeners;
    if (listeners == null || listeners.isEmpty) {
      return;
    }

    _activeDispatchLoops++;
    final int end = listeners.length;
    for (int i = 0; i < end; i++) {
      try {
        listeners[i]?.call(event);
      } catch (exception, stack) {
        final String type = event.object.runtimeType.toString();
        FlutterError.reportError(FlutterErrorDetails(
          exception: exception,
          stack: stack,
          library: 'foundation library',
          context: ErrorDescription('MemoryAllocations while '
          'dispatching notifications for $type'),
          informationCollector: () => <DiagnosticsNode>[
            DiagnosticsProperty<Object>(
              'The $type sending notification was',
              event.object,
              style: DiagnosticsTreeStyle.errorProperty,
            ),
          ],
        ));
      }
    }
    _activeDispatchLoops--;
    _tryDefragmentListeners();
  }

  /// Create [ObjectCreated] and invoke [dispatchObjectEvent] if there are listeners.
  ///
  /// This method is more efficient than [dispatchObjectEvent] if the event object is not created yet.
  void dispatchObjectCreated({
    required String library,
    required String className,
    required Object object,
  }) {
    if (!hasListeners) {
      return;
    }
    dispatchObjectEvent(ObjectCreated(
      library: library,
      className: className,
      object: object,
    ));
  }

  /// Create [ObjectDisposed] and invoke [dispatchObjectEvent] if there are listeners.
  ///
  /// This method is more efficient than [dispatchObjectEvent] if the event object is not created yet.
  void dispatchObjectDisposed({required Object object}) {
    if (!hasListeners) {
      return;
    }
    dispatchObjectEvent(ObjectDisposed(object: object));
  }

  void _subscribeToSdkObjects() {
    assert(ui.Image.onCreate == null);
    assert(ui.Image.onDispose == null);
    assert(ui.Picture.onCreate == null);
    assert(ui.Picture.onDispose == null);
    ui.Image.onCreate = _imageOnCreate;
    ui.Image.onDispose = _imageOnDispose;
    ui.Picture.onCreate = _pictureOnCreate;
    ui.Picture.onDispose = _pictureOnDispose;
  }

  void _unSubscribeFromSdkObjects() {
    assert(ui.Image.onCreate == _imageOnCreate);
    assert(ui.Image.onDispose == _imageOnDispose);
    assert(ui.Picture.onCreate == _pictureOnCreate);
    assert(ui.Picture.onDispose == _pictureOnDispose);
    ui.Image.onCreate = null;
    ui.Image.onDispose = null;
    ui.Picture.onCreate = null;
    ui.Picture.onDispose = null;
  }

  void _imageOnCreate(ui.Image image) {
    dispatchObjectEvent(ObjectCreated(
      library: _dartUiLibrary,
      className: '${ui.Image}',
      object: image,
    ));
  }

  void _pictureOnCreate(ui.Picture picture) {
    dispatchObjectEvent(ObjectCreated(
      library: _dartUiLibrary,
      className: '${ui.Picture}',
      object: picture,
    ));
  }

  void _imageOnDispose(ui.Image image) {
    dispatchObjectEvent(ObjectDisposed(
      object: image,
    ));
  }

  void _pictureOnDispose(ui.Picture picture) {
    dispatchObjectEvent(ObjectDisposed(
      object: picture,
    ));
  }
}
