// 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/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

// Only check the initial lines of the message, since the message walks the
// entire widget tree back, and any changes to the widget tree break these
// tests if we check the entire message.
void _expectStartsWith(List<String?> actual, List<String?> matcher) {
  expect(actual.sublist(0, matcher.length), equals(matcher));
}

void main() {
  final _MockLiveTestWidgetsFlutterBinding binding = _MockLiveTestWidgetsFlutterBinding();

  testWidgets('Should print message on pointer events', (WidgetTester tester) async {
    final List<String?> printedMessages = <String?>[];

    int invocations = 0;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: GestureDetector(
            onTap: () {
              invocations++;
            },
            child: const Text('Test'),
          ),
        ),
      ),
    );

    final Size windowCenter = tester.view.physicalSize /
        tester.view.devicePixelRatio /
        2;
    final double windowCenterX = windowCenter.width;
    final double windowCenterY = windowCenter.height;

    final Offset widgetCenter = tester.getRect(find.byType(Text)).center;
    expect(widgetCenter.dx, windowCenterX);
    expect(widgetCenter.dy, windowCenterY);

    await binding.collectDebugPrints(printedMessages, () async {
      await tester.tap(find.byType(Text));
    });
    await tester.pump();
    expect(invocations, 0);

    _expectStartsWith(printedMessages, '''
Some possible finders for the widgets at Offset(400.0, 300.0):
  find.text('Test')
'''.trim().split('\n'));
    printedMessages.clear();

    await binding.collectDebugPrints(printedMessages, () async {
      await tester.tapAt(const Offset(1, 1));
    });
    expect(printedMessages, equals('''
No widgets found at Offset(1.0, 1.0).
'''.trim().split('\n')));
  });

  testWidgets('Should print message on pointer events with setSurfaceSize', (WidgetTester tester) async {
    final List<String?> printedMessages = <String?>[];

    int invocations = 0;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child:GestureDetector(
            onTap: () {
              invocations++;
            },
            child: const Text('Test'),
          ),
        ),
      ),
    );

    final Size originalSize = tester.binding.createViewConfiguration().size;
    await tester.binding.setSurfaceSize(const Size(2000, 1800));
    try {
      await tester.pump();

      final Offset widgetCenter = tester.getRect(find.byType(Text)).center;
      expect(widgetCenter.dx, 1000);
      expect(widgetCenter.dy, 900);

      await binding.collectDebugPrints(printedMessages, () async {
        await tester.tap(find.byType(Text));
      });
      await tester.pump();
      expect(invocations, 0);

      _expectStartsWith(printedMessages, '''
Some possible finders for the widgets at Offset(1000.0, 900.0):
  find.text('Test')
'''.trim().split('\n'));
      printedMessages.clear();

      await binding.collectDebugPrints(printedMessages, () async {
        await tester.tapAt(const Offset(1, 1));
      });
      expect(printedMessages, equals('''
No widgets found at Offset(1.0, 1.0).
'''.trim().split('\n')));
    } finally {
      await tester.binding.setSurfaceSize(originalSize);
    }
  });
}

class _MockLiveTestWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding {
  @override
  void handlePointerEventForSource(
    PointerEvent event, {
    TestBindingEventSource source = TestBindingEventSource.device,
  }) {
    // In this test we use `WidgetTester.tap` to simulate real device touches.
    // `WidgetTester.tap` sends events in the local coordinate system, while
    // real devices touches sends event in the global coordinate system.
    // See the documentation of [handlePointerEventForSource] for details.
    if (source == TestBindingEventSource.test) {
      final PointerEvent globalEvent = event.copyWith(position: localToGlobal(event.position));
      return super.handlePointerEventForSource(globalEvent);
    }
    return super.handlePointerEventForSource(event, source: source);
  }

  List<String?>? _storeDebugPrints;

  @override
  DebugPrintCallback get debugPrintOverride {
    return _storeDebugPrints == null
        ? super.debugPrintOverride
        : ((String? message, { int? wrapWidth }) => _storeDebugPrints!.add(message));
  }

  // Execute `task` while redirecting [debugPrint] to appending to `store`.
  Future<void> collectDebugPrints(List<String?>? store, AsyncValueGetter<void> task) async {
    _storeDebugPrints = store;
    try {
      await task();
    } finally {
      _storeDebugPrints = null;
    }
  }
}
