// 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 'package:flutter/gestures.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:vector_math/vector_math_64.dart';

class TestPointerSignalListener {
  TestPointerSignalListener(this.event);

  final PointerSignalEvent event;
  bool callbackRan = false;

  void callback(PointerSignalEvent event) {
    expect(event, equals(this.event));
    expect(callbackRan, isFalse);
    callbackRan = true;
  }
}

class PointerSignalTester {
  final PointerSignalResolver resolver = PointerSignalResolver();
  PointerSignalEvent event = const PointerScrollEvent();

  TestPointerSignalListener addListener() {
    final TestPointerSignalListener listener = TestPointerSignalListener(event);
    resolver.register(event, listener.callback);
    return listener;
  }

  /// Simulates a new event dispatch cycle by resolving the current event and
  /// setting a new event to use for future calls.
  void resolve() {
    resolver.resolve(event);
    event = const PointerScrollEvent();
  }
}

void main() {
  test('Resolving with no entries should be a no-op', () {
    final PointerSignalTester tester = PointerSignalTester();
    tester.resolver.resolve(tester.event);
  });

  test('First entry should always win', () {
    final PointerSignalTester tester = PointerSignalTester();
    final TestPointerSignalListener first = tester.addListener();
    final TestPointerSignalListener second = tester.addListener();
    tester.resolve();
    expect(first.callbackRan, isTrue);
    expect(second.callbackRan, isFalse);
  });

  test('Re-use after resolve should work', () {
    final PointerSignalTester tester = PointerSignalTester();
    final TestPointerSignalListener first = tester.addListener();
    final TestPointerSignalListener second = tester.addListener();
    tester.resolve();
    expect(first.callbackRan, isTrue);
    expect(second.callbackRan, isFalse);

    final TestPointerSignalListener newEventListener = tester.addListener();
    tester.resolve();
    expect(newEventListener.callbackRan, isTrue);
    // Nothing should have changed for the previous event's listeners.
    expect(first.callbackRan, isTrue);
    expect(second.callbackRan, isFalse);
  });

  test('works with transformed events', () {
    final PointerSignalResolver resolver = PointerSignalResolver();
    const PointerScrollEvent originalEvent = PointerScrollEvent();
    final PointerSignalEvent transformedEvent = originalEvent
        .transformed(Matrix4.translationValues(10.0, 20.0, 0.0));
    final PointerSignalEvent anotherTransformedEvent = originalEvent
        .transformed(Matrix4.translationValues(30.0, 50.0, 0.0));

    expect(originalEvent, isNot(same(transformedEvent)));
    expect(transformedEvent.original, same(originalEvent));

    expect(originalEvent, isNot(same(anotherTransformedEvent)));
    expect(anotherTransformedEvent.original, same(originalEvent));

    final List<PointerSignalEvent> events = <PointerSignalEvent>[];
    resolver.register(transformedEvent, (PointerSignalEvent event) {
      events.add(event);
    });

    // Registering a second transformed event should not throw an assertion.
    expect(() {
      resolver.register(anotherTransformedEvent, (PointerSignalEvent event) {
        // This shouldn't be called because only the first registered callback is
        // invoked.
        events.add(event);
      });
    }, returnsNormally);

    resolver.resolve(originalEvent);

    expect(events.single, same(transformedEvent));
  });
}
