// 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 'dart:ui' show PointerChange;

import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import 'mouse_tracker_test_utils.dart';

typedef MethodCallHandler = Future<dynamic> Function(MethodCall call);
typedef SimpleAnnotationFinder = Iterable<HitTestTarget> Function(Offset offset);

void main() {
  final TestMouseTrackerFlutterBinding _binding = TestMouseTrackerFlutterBinding();
  MethodCallHandler? _methodCallHandler;

  // Only one of `logCursors` and `cursorHandler` should be specified.
  void _setUpMouseTracker({
    required SimpleAnnotationFinder annotationFinder,
    List<_CursorUpdateDetails>? logCursors,
    MethodCallHandler? cursorHandler,
  }) {
    assert(logCursors == null || cursorHandler == null);
    _methodCallHandler = logCursors != null
      ? (MethodCall call) async {
        logCursors.add(_CursorUpdateDetails.wrap(call));
        return;
      }
      : cursorHandler;

    _binding.setHitTest((BoxHitTestResult result, Offset position) {
      for (final HitTestTarget target in annotationFinder(position)) {
        result.addWithRawTransform(
          transform: Matrix4.identity(),
          position: position,
          hitTest: (BoxHitTestResult result, Offset position) {
            result.add(HitTestEntry(target));
            return true;
          },
        );
      }
      return true;
    });
  }

  void dispatchRemoveDevice([int device = 0]) {
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.remove, Offset.zero, device: device),
    ]));
  }

  setUp(() {
    _binding.postFrameCallbacks.clear();
    _binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.mouseCursor, (MethodCall call) async {
      if (_methodCallHandler != null)
        return _methodCallHandler!(call);
    });
  });

  tearDown(() {
    _binding.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.mouseCursor, null);
  });

  test('Should work on platforms that does not support mouse cursor', () async {
    const TestAnnotationTarget annotation = TestAnnotationTarget(cursor: SystemMouseCursors.grabbing);

    _setUpMouseTracker(
      annotationFinder: (Offset position) => <TestAnnotationTarget>[annotation],
      cursorHandler: (MethodCall call) async {
        return null;
      },
    );

    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.add, Offset.zero),
    ]));
    addTearDown(dispatchRemoveDevice);

    // Passes if no errors are thrown
  });

  test('pointer is added and removed out of any annotations', () {
    final List<_CursorUpdateDetails> logCursors = <_CursorUpdateDetails>[];
    TestAnnotationTarget? annotation;
    _setUpMouseTracker(
      annotationFinder: (Offset position) => <TestAnnotationTarget>[if (annotation != null) annotation],
      logCursors: logCursors,
    );

    // Pointer is added outside of the annotation.
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.add, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.basic.kind),
    ]);
    logCursors.clear();

    // Pointer moves into the annotation
    annotation = const TestAnnotationTarget(cursor: SystemMouseCursors.grabbing);
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, const Offset(5.0, 0.0)),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.grabbing.kind),
    ]);
    logCursors.clear();

    // Pointer moves within the annotation
    annotation = const TestAnnotationTarget(cursor: SystemMouseCursors.grabbing);
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, const Offset(10.0, 0.0)),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[]);
    logCursors.clear();

    // Pointer moves out of the annotation
    annotation = null;
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.basic.kind),
    ]);
    logCursors.clear();

    // Pointer is removed outside of the annotation.
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.remove, Offset.zero),
    ]));

    expect(logCursors, const <_CursorUpdateDetails>[]);
  });

  test('pointer is added and removed in an annotation', () {
    final List<_CursorUpdateDetails> logCursors = <_CursorUpdateDetails>[];
    TestAnnotationTarget? annotation;
    _setUpMouseTracker(
      annotationFinder: (Offset position) => <TestAnnotationTarget>[if (annotation != null) annotation],
      logCursors: logCursors,
    );

    // Pointer is added in the annotation.
    annotation = const TestAnnotationTarget(cursor: SystemMouseCursors.grabbing);
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.add, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.grabbing.kind),
    ]);
    logCursors.clear();

    // Pointer moves out of the annotation
    annotation = null;
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, const Offset(5.0, 0.0)),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.basic.kind),
    ]);
    logCursors.clear();

    // Pointer moves around out of the annotation
    annotation = null;
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, const Offset(10.0, 0.0)),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[]);
    logCursors.clear();

    // Pointer moves back into the annotation
    annotation = const TestAnnotationTarget(cursor: SystemMouseCursors.grabbing);
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.grabbing.kind),
    ]);
    logCursors.clear();

    // Pointer is removed within the annotation.
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.remove, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[]);
  });

  test('pointer change caused by new frames', () {
    final List<_CursorUpdateDetails> logCursors = <_CursorUpdateDetails>[];
    TestAnnotationTarget? annotation;
    _setUpMouseTracker(
      annotationFinder: (Offset position) => <TestAnnotationTarget>[if (annotation != null) annotation],
      logCursors: logCursors,
    );

    // Pointer is added outside of the annotation.
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.add, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.basic.kind),
    ]);
    logCursors.clear();

    // Synthesize a new frame while changing annotation
    annotation = const TestAnnotationTarget(cursor: SystemMouseCursors.grabbing);
    _binding.scheduleMouseTrackerPostFrameCheck();
    _binding.flushPostFrameCallbacks(Duration.zero);

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.grabbing.kind),
    ]);
    logCursors.clear();

    // Synthesize a new frame without changing annotation
    annotation = const TestAnnotationTarget(cursor: SystemMouseCursors.grabbing);
    _binding.scheduleMouseTrackerPostFrameCheck();

    expect(logCursors, <_CursorUpdateDetails>[]);
    logCursors.clear();

    // Pointer is removed outside of the annotation.
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.remove, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[]);
  });

  test('The first annotation with non-deferring cursor is used', () {
    final List<_CursorUpdateDetails> logCursors = <_CursorUpdateDetails>[];
    late List<TestAnnotationTarget> annotations;
    _setUpMouseTracker(
      annotationFinder: (Offset position) sync* { yield* annotations; },
      logCursors: logCursors,
    );

    annotations = <TestAnnotationTarget>[
      const TestAnnotationTarget(),
      const TestAnnotationTarget(cursor: SystemMouseCursors.click),
      const TestAnnotationTarget(cursor: SystemMouseCursors.grabbing),
    ];
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.add, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.click.kind),
    ]);
    logCursors.clear();

    // Remove
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.remove, const Offset(5.0, 0.0)),
    ]));
  });

  test('Annotations with deferring cursors are ignored', () {
    final List<_CursorUpdateDetails> logCursors = <_CursorUpdateDetails>[];
    late List<TestAnnotationTarget> annotations;
    _setUpMouseTracker(
      annotationFinder: (Offset position) sync* { yield* annotations; },
      logCursors: logCursors,
    );

    annotations = <TestAnnotationTarget>[
      const TestAnnotationTarget(),
      const TestAnnotationTarget(),
      const TestAnnotationTarget(cursor: SystemMouseCursors.grabbing),
    ];
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.add, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.grabbing.kind),
    ]);
    logCursors.clear();

    // Remove
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.remove, const Offset(5.0, 0.0)),
    ]));
  });

  test('Finding no annotation is equivalent to specifying default cursor', () {
    final List<_CursorUpdateDetails> logCursors = <_CursorUpdateDetails>[];
    TestAnnotationTarget? annotation;
    _setUpMouseTracker(
      annotationFinder: (Offset position) => <TestAnnotationTarget>[if (annotation != null) annotation],
      logCursors: logCursors,
    );

    // Pointer is added outside of the annotation.
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.add, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.basic.kind),
    ]);
    logCursors.clear();

    // Pointer moved to an annotation specified with the default cursor
    annotation = const TestAnnotationTarget(cursor: SystemMouseCursors.basic);
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, const Offset(5.0, 0.0)),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[]);
    logCursors.clear();

    // Pointer moved to no annotations
    annotation = null;
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, Offset.zero),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[]);
    logCursors.clear();

    // Remove
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.remove, Offset.zero),
    ]));
  });

  test('Removing a pointer resets it back to the default cursor', () {
    final List<_CursorUpdateDetails> logCursors = <_CursorUpdateDetails>[];
    TestAnnotationTarget? annotation;
    _setUpMouseTracker(
      annotationFinder: (Offset position) => <TestAnnotationTarget>[if (annotation != null) annotation],
      logCursors: logCursors,
    );

    // Pointer is added to the annotation, then removed
    annotation = const TestAnnotationTarget(cursor: SystemMouseCursors.click);
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.add, Offset.zero),
      _pointerData(PointerChange.hover, const Offset(5.0, 0.0)),
      _pointerData(PointerChange.remove, const Offset(5.0, 0.0)),
    ]));

    logCursors.clear();

    // Pointer is added out of the annotation
    annotation = null;
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.add, Offset.zero),
    ]));
    addTearDown(dispatchRemoveDevice);

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 0, kind: SystemMouseCursors.basic.kind),
    ]);
    logCursors.clear();
  });

  test('Pointing devices display cursors separately', () {
    final List<_CursorUpdateDetails> logCursors = <_CursorUpdateDetails>[];
    _setUpMouseTracker(
      annotationFinder: (Offset position) sync* {
        if (position.dx > 200) {
          yield const TestAnnotationTarget(cursor: SystemMouseCursors.forbidden);
        } else if (position.dx > 100) {
          yield const TestAnnotationTarget(cursor: SystemMouseCursors.click);
        } else {}
      },
      logCursors: logCursors,
    );

    // Pointers are added outside of the annotation.
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.add, Offset.zero, device: 1),
      _pointerData(PointerChange.add, Offset.zero, device: 2),
    ]));
    addTearDown(() => dispatchRemoveDevice(1));
    addTearDown(() => dispatchRemoveDevice(2));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 1, kind: SystemMouseCursors.basic.kind),
      _CursorUpdateDetails.activateSystemCursor(device: 2, kind: SystemMouseCursors.basic.kind),
    ]);
    logCursors.clear();

    // Pointer 1 moved to cursor "click"
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, const Offset(101.0, 0.0), device: 1),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 1, kind: SystemMouseCursors.click.kind),
    ]);
    logCursors.clear();

    // Pointer 2 moved to cursor "click"
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, const Offset(102.0, 0.0), device: 2),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 2, kind: SystemMouseCursors.click.kind),
    ]);
    logCursors.clear();

    // Pointer 2 moved to cursor "forbidden"
    ui.window.onPointerDataPacket!(ui.PointerDataPacket(data: <ui.PointerData>[
      _pointerData(PointerChange.hover, const Offset(202.0, 0.0), device: 2),
    ]));

    expect(logCursors, <_CursorUpdateDetails>[
      _CursorUpdateDetails.activateSystemCursor(device: 2, kind: SystemMouseCursors.forbidden.kind),
    ]);
    logCursors.clear();
  });
}

ui.PointerData _pointerData(
  PointerChange change,
  Offset logicalPosition, {
  int device = 0,
  PointerDeviceKind kind = PointerDeviceKind.mouse,
}) {
  return ui.PointerData(
    change: change,
    physicalX: logicalPosition.dx * ui.window.devicePixelRatio,
    physicalY: logicalPosition.dy * ui.window.devicePixelRatio,
    kind: kind,
    device: device,
  );
}

class _CursorUpdateDetails extends MethodCall {
  const _CursorUpdateDetails(String method, Map<String, dynamic> arguments)
    : assert(arguments != null),
      super(method, arguments);

  _CursorUpdateDetails.wrap(MethodCall call)
    : super(call.method, Map<String, dynamic>.from(call.arguments as Map<dynamic, dynamic>));

  _CursorUpdateDetails.activateSystemCursor({
    required int device,
    required String kind,
  }) : this('activateSystemCursor', <String, dynamic>{'device': device, 'kind': kind});
  @override
  Map<String, dynamic> get arguments => super.arguments as Map<String, dynamic>;

  @override
  bool operator ==(dynamic other) {
    if (identical(other, this))
      return true;
    if (other.runtimeType != runtimeType)
      return false;
    return other is _CursorUpdateDetails
        && other.method == method
        && other.arguments.length == arguments.length
        && other.arguments.entries.every(
          (MapEntry<String, dynamic> entry) =>
            arguments.containsKey(entry.key) && arguments[entry.key] == entry.value,
        );
  }

  @override
  int get hashCode => hashValues(method, arguments);

  @override
  String toString() {
    return '_CursorUpdateDetails(method: $method, arguments: $arguments)';
  }
}
