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

// This library intentionally uses the LinkedHashMap constructor to declare that
// entries will be ordered. Using collection literals for this requires casting the
// resulting map, which has a runtime cost.
// ignore_for_file: prefer_collection_literals

import 'dart:collection' show LinkedHashMap;
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';

import 'object.dart';

export 'package:flutter/services.dart' show
  MouseCursor,
  SystemMouseCursors;

/// Signature for searching for [MouseTrackerAnnotation]s at the given offset.
///
/// It is used by the [MouseTracker] to fetch annotations for the mouse
/// position.
typedef MouseDetectorAnnotationFinder = HitTestResult Function(Offset offset);

// Various states of a connected mouse device used by [MouseTracker].
class _MouseState {
  _MouseState({
    required PointerEvent initialEvent,
  }) : assert(initialEvent != null),
       _latestEvent = initialEvent;

  // The list of annotations that contains this device.
  //
  // It uses [LinkedHashMap] to keep the insertion order.
  LinkedHashMap<MouseTrackerAnnotation, Matrix4> get annotations => _annotations;
  LinkedHashMap<MouseTrackerAnnotation, Matrix4> _annotations = LinkedHashMap<MouseTrackerAnnotation, Matrix4>();

  LinkedHashMap<MouseTrackerAnnotation, Matrix4> replaceAnnotations(LinkedHashMap<MouseTrackerAnnotation, Matrix4> value) {
    assert(value != null);
    final LinkedHashMap<MouseTrackerAnnotation, Matrix4> previous = _annotations;
    _annotations = value;
    return previous;
  }

  // The most recently processed mouse event observed from this device.
  PointerEvent get latestEvent => _latestEvent;
  PointerEvent _latestEvent;

  PointerEvent replaceLatestEvent(PointerEvent value) {
    assert(value != null);
    assert(value.device == _latestEvent.device);
    final PointerEvent previous = _latestEvent;
    _latestEvent = value;
    return previous;
  }

  int get device => latestEvent.device;

  @override
  String toString() {
    final String describeLatestEvent = 'latestEvent: ${describeIdentity(latestEvent)}';
    final String describeAnnotations = 'annotations: [list of ${annotations.length}]';
    return '${describeIdentity(this)}($describeLatestEvent, $describeAnnotations)';
  }
}

// The information in `MouseTracker._handleDeviceUpdate` to provide the details
// of an update of a mouse device.
//
// This class contains the information needed to handle the update that might
// change the state of a mouse device, or the [MouseTrackerAnnotation]s that
// the mouse device is hovering.
@immutable
class _MouseTrackerUpdateDetails with Diagnosticable {
  /// When device update is triggered by a new frame.
  ///
  /// All parameters are required.
  const _MouseTrackerUpdateDetails.byNewFrame({
    required this.lastAnnotations,
    required this.nextAnnotations,
    required PointerEvent this.previousEvent,
  }) : assert(previousEvent != null),
       assert(lastAnnotations != null),
       assert(nextAnnotations != null),
       triggeringEvent = null;

  /// When device update is triggered by a pointer event.
  ///
  /// The [lastAnnotations], [nextAnnotations], and [triggeringEvent] are
  /// required.
  const _MouseTrackerUpdateDetails.byPointerEvent({
    required this.lastAnnotations,
    required this.nextAnnotations,
    this.previousEvent,
    required PointerEvent this.triggeringEvent,
  }) : assert(triggeringEvent != null),
       assert(lastAnnotations != null),
       assert(nextAnnotations != null);

  /// The annotations that the device is hovering before the update.
  ///
  /// It is never null.
  final LinkedHashMap<MouseTrackerAnnotation, Matrix4> lastAnnotations;

  /// The annotations that the device is hovering after the update.
  ///
  /// It is never null.
  final LinkedHashMap<MouseTrackerAnnotation, Matrix4> nextAnnotations;

  /// The last event that the device observed before the update.
  ///
  /// If the update is triggered by a frame, the [previousEvent] is never null,
  /// since the pointer must have been added before.
  ///
  /// If the update is triggered by a pointer event, the [previousEvent] is not
  /// null except for cases where the event is the first event observed by the
  /// pointer (which is not necessarily a [PointerAddedEvent]).
  final PointerEvent? previousEvent;

  /// The event that triggered this update.
  ///
  /// It is non-null if and only if the update is triggered by a pointer event.
  final PointerEvent? triggeringEvent;

  /// The pointing device of this update.
  int get device {
    final int result = (previousEvent ?? triggeringEvent)!.device;
    assert(result != null);
    return result;
  }

  /// The last event that the device observed after the update.
  ///
  /// The [latestEvent] is never null.
  PointerEvent get latestEvent {
    final PointerEvent result = triggeringEvent ?? previousEvent!;
    assert(result != null);
    return result;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(IntProperty('device', device));
    properties.add(DiagnosticsProperty<PointerEvent>('previousEvent', previousEvent));
    properties.add(DiagnosticsProperty<PointerEvent>('triggeringEvent', triggeringEvent));
    properties.add(DiagnosticsProperty<Map<MouseTrackerAnnotation, Matrix4>>('lastAnnotations', lastAnnotations));
    properties.add(DiagnosticsProperty<Map<MouseTrackerAnnotation, Matrix4>>('nextAnnotations', nextAnnotations));
  }
}

/// Tracks the relationship between mouse devices and annotations, and
/// triggers mouse events and cursor changes accordingly.
///
/// The [MouseTracker] tracks the relationship between mouse devices and
/// [MouseTrackerAnnotation], notified by [updateWithEvent] and
/// [updateAllDevices]. At every update, [MouseTracker] triggers the following
/// changes if applicable:
///
///  * Dispatches mouse-related pointer events (pointer enter, hover, and exit).
///  * Changes mouse cursors.
///  * Notifies when [mouseIsConnected] changes.
///
/// This class is a [ChangeNotifier] that notifies its listeners if the value of
/// [mouseIsConnected] changes.
///
/// An instance of [MouseTracker] is owned by the global singleton
/// [RendererBinding].
class MouseTracker extends ChangeNotifier {
  final MouseCursorManager _mouseCursorMixin = MouseCursorManager(
    SystemMouseCursors.basic,
  );

  // Tracks the state of connected mouse devices.
  //
  // It is the source of truth for the list of connected mouse devices, and
  // consists of two parts:
  //
  //  * The mouse devices that are connected.
  //  * In which annotations each device is contained.
  final Map<int, _MouseState> _mouseStates = <int, _MouseState>{};

  // Used to wrap any procedure that might change `mouseIsConnected`.
  //
  // This method records `mouseIsConnected`, runs `task`, and calls
  // [notifyListeners] at the end if the `mouseIsConnected` has changed.
  void _monitorMouseConnection(VoidCallback task) {
    final bool mouseWasConnected = mouseIsConnected;
    task();
    if (mouseWasConnected != mouseIsConnected) {
      notifyListeners();
    }
  }

  bool _debugDuringDeviceUpdate = false;
  // Used to wrap any procedure that might call `_handleDeviceUpdate`.
  //
  // In debug mode, this method uses `_debugDuringDeviceUpdate` to prevent
  // `_deviceUpdatePhase` being recursively called.
  void _deviceUpdatePhase(VoidCallback task) {
    assert(!_debugDuringDeviceUpdate);
    assert(() {
      _debugDuringDeviceUpdate = true;
      return true;
    }());
    task();
    assert(() {
      _debugDuringDeviceUpdate = false;
      return true;
    }());
  }

  // Whether an observed event might update a device.
  static bool _shouldMarkStateDirty(_MouseState? state, PointerEvent event) {
    if (state == null) {
      return true;
    }
    assert(event != null);
    final PointerEvent lastEvent = state.latestEvent;
    assert(event.device == lastEvent.device);
    // An Added can only follow a Removed, and a Removed can only be followed
    // by an Added.
    assert((event is PointerAddedEvent) == (lastEvent is PointerRemovedEvent));

    // Ignore events that are unrelated to mouse tracking.
    if (event is PointerSignalEvent) {
      return false;
    }
    return lastEvent is PointerAddedEvent
      || event is PointerRemovedEvent
      || lastEvent.position != event.position;
  }

  LinkedHashMap<MouseTrackerAnnotation, Matrix4> _hitTestResultToAnnotations(HitTestResult result) {
    assert(result != null);
    final LinkedHashMap<MouseTrackerAnnotation, Matrix4> annotations = LinkedHashMap<MouseTrackerAnnotation, Matrix4>();
    for (final HitTestEntry entry in result.path) {
      final Object target = entry.target;
      if (target is MouseTrackerAnnotation) {
        annotations[target] = entry.transform!;
      }
    }
    return annotations;
  }

  // Find the annotations that is hovered by the device of the `state`, and
  // their respective global transform matrices.
  //
  // If the device is not connected or not a mouse, an empty map is returned
  // without calling `hitTest`.
  LinkedHashMap<MouseTrackerAnnotation, Matrix4> _findAnnotations(_MouseState state, MouseDetectorAnnotationFinder hitTest) {
    assert(state != null);
    assert(hitTest != null);
    final Offset globalPosition = state.latestEvent.position;
    final int device = state.device;
    if (!_mouseStates.containsKey(device)) {
      return LinkedHashMap<MouseTrackerAnnotation, Matrix4>();
    }

    return _hitTestResultToAnnotations(hitTest(globalPosition));
  }

  // A callback that is called on the update of a device.
  //
  // An event (not necessarily a pointer event) that might change the
  // relationship between mouse devices and [MouseTrackerAnnotation]s is called
  // a _device update_. This method should be called at each such update.
  //
  // The update can be caused by two kinds of triggers:
  //
  //  * Triggered by the addition, movement, or removal of a pointer. Such calls
  //    occur during the handler of the event, indicated by
  //    `details.triggeringEvent` being non-null.
  //  * Triggered by the appearance, movement, or disappearance of an annotation.
  //    Such calls occur after each new frame, during the post-frame callbacks,
  //    indicated by `details.triggeringEvent` being null.
  //
  // Calls of this method must be wrapped in `_deviceUpdatePhase`.
  void _handleDeviceUpdate(_MouseTrackerUpdateDetails details) {
    assert(_debugDuringDeviceUpdate);
    _handleDeviceUpdateMouseEvents(details);
    _mouseCursorMixin.handleDeviceCursorUpdate(
      details.device,
      details.triggeringEvent,
      details.nextAnnotations.keys.map((MouseTrackerAnnotation annotation) => annotation.cursor),
    );
  }

  /// Whether or not at least one mouse is connected and has produced events.
  bool get mouseIsConnected => _mouseStates.isNotEmpty;

  /// Trigger a device update with a new event and its corresponding hit test
  /// result.
  ///
  /// The [updateWithEvent] indicates that an event has been observed, and is
  /// called during the handler of the event. It is typically called by
  /// [RendererBinding], and should be called with all events received, and let
  /// [MouseTracker] filter which to react to.
  ///
  /// The `getResult` is a function to return the hit test result at the
  /// position of the event. It should not simply return cached hit test
  /// result, because the cache does not change throughout a tap sequence.
  void updateWithEvent(PointerEvent event, ValueGetter<HitTestResult> getResult) {
    if (event.kind != PointerDeviceKind.mouse) {
      return;
    }
    if (event is PointerSignalEvent) {
      return;
    }
    final HitTestResult result = event is PointerRemovedEvent ? HitTestResult() : getResult();
    final int device = event.device;
    final _MouseState? existingState = _mouseStates[device];
    if (!_shouldMarkStateDirty(existingState, event)) {
      return;
    }

    _monitorMouseConnection(() {
      _deviceUpdatePhase(() {
        // Update mouseState to the latest devices that have not been removed,
        // so that [mouseIsConnected], which is decided by `_mouseStates`, is
        // correct during the callbacks.
        if (existingState == null) {
          if (event is PointerRemovedEvent) {
            return;
          }
          _mouseStates[device] = _MouseState(initialEvent: event);
        } else {
          assert(event is! PointerAddedEvent);
          if (event is PointerRemovedEvent) {
            _mouseStates.remove(event.device);
          }
        }
        final _MouseState targetState = _mouseStates[device] ?? existingState!;

        final PointerEvent lastEvent = targetState.replaceLatestEvent(event);
        final LinkedHashMap<MouseTrackerAnnotation, Matrix4> nextAnnotations = event is PointerRemovedEvent ?
            LinkedHashMap<MouseTrackerAnnotation, Matrix4>() :
            _hitTestResultToAnnotations(result);
        final LinkedHashMap<MouseTrackerAnnotation, Matrix4> lastAnnotations = targetState.replaceAnnotations(nextAnnotations);

        _handleDeviceUpdate(_MouseTrackerUpdateDetails.byPointerEvent(
          lastAnnotations: lastAnnotations,
          nextAnnotations: nextAnnotations,
          previousEvent: lastEvent,
          triggeringEvent: event,
        ));
      });
    });
  }

  /// Trigger a device update for all detected devices.
  ///
  /// The [updateAllDevices] is typically called during the post frame phase,
  /// indicating a frame has passed and all objects have potentially moved. The
  /// `hitTest` is a function that acquires the hit test result at a given
  /// position, and must not be empty.
  ///
  /// For each connected device, the [updateAllDevices] will make a hit test on
  /// the device's last seen position, and check if necessary changes need to be
  /// made.
  void updateAllDevices(MouseDetectorAnnotationFinder hitTest) {
    _deviceUpdatePhase(() {
      for (final _MouseState dirtyState in _mouseStates.values) {
        final PointerEvent lastEvent = dirtyState.latestEvent;
        final LinkedHashMap<MouseTrackerAnnotation, Matrix4> nextAnnotations = _findAnnotations(dirtyState, hitTest);
        final LinkedHashMap<MouseTrackerAnnotation, Matrix4> lastAnnotations = dirtyState.replaceAnnotations(nextAnnotations);

        _handleDeviceUpdate(_MouseTrackerUpdateDetails.byNewFrame(
          lastAnnotations: lastAnnotations,
          nextAnnotations: nextAnnotations,
          previousEvent: lastEvent,
        ));
      }
    });
  }

  /// Returns the active mouse cursor for a device.
  ///
  /// The return value is the last [MouseCursor] activated onto this device, even
  /// if the activation failed.
  ///
  /// This function is only active when asserts are enabled. In release builds,
  /// it always returns null.
  @visibleForTesting
  MouseCursor? debugDeviceActiveCursor(int device) {
    return _mouseCursorMixin.debugDeviceActiveCursor(device);
  }

  // Handles device update and dispatches mouse event callbacks.
  static void _handleDeviceUpdateMouseEvents(_MouseTrackerUpdateDetails details) {
    final PointerEvent latestEvent = details.latestEvent;

    final LinkedHashMap<MouseTrackerAnnotation, Matrix4> lastAnnotations = details.lastAnnotations;
    final LinkedHashMap<MouseTrackerAnnotation, Matrix4> nextAnnotations = details.nextAnnotations;

    // Order is important for mouse event callbacks. The
    // `_hitTestResultToAnnotations` returns annotations in the visual order
    // from front to back, called the "hit-test order". The algorithm here is
    // explained in https://github.com/flutter/flutter/issues/41420

    // Send exit events to annotations that are in last but not in next, in
    // hit-test order.
    final PointerExitEvent baseExitEvent = PointerExitEvent.fromMouseEvent(latestEvent);
    lastAnnotations.forEach((MouseTrackerAnnotation annotation, Matrix4 transform) {
      if (!nextAnnotations.containsKey(annotation)) {
        if (annotation.validForMouseTracker && annotation.onExit != null) {
          annotation.onExit!(baseExitEvent.transformed(lastAnnotations[annotation]));
        }
      }
    });

    // Send enter events to annotations that are not in last but in next, in
    // reverse hit-test order.
    final List<MouseTrackerAnnotation> enteringAnnotations = nextAnnotations.keys.where(
      (MouseTrackerAnnotation annotation) => !lastAnnotations.containsKey(annotation),
    ).toList();
    final PointerEnterEvent baseEnterEvent = PointerEnterEvent.fromMouseEvent(latestEvent);
    for (final MouseTrackerAnnotation annotation in enteringAnnotations.reversed) {
      if (annotation.validForMouseTracker && annotation.onEnter != null) {
        annotation.onEnter!(baseEnterEvent.transformed(nextAnnotations[annotation]));
      }
    }
  }
}
