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

@Tags(<String>['reduced-test-set'])

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  final Offset basicOffset = Offset(CupertinoMagnifier.kDefaultSize.width / 2,
       CupertinoMagnifier.kDefaultSize.height - CupertinoMagnifier.kMagnifierAboveFocalPoint);
  const Rect reasonableTextField = Rect.fromLTRB(0, 100, 200, 200);
  final MagnifierController magnifierController = MagnifierController();

  // Make sure that your gesture in magnifierInfo is within the line in magnifierInfo,
  // or else the magnifier status will stay hidden and this will not complete.
  Future<void> showCupertinoMagnifier(
    BuildContext context,
    WidgetTester tester,
    ValueNotifier<MagnifierInfo> magnifierInfo,
  ) async {
    final Future<void> magnifierShown = magnifierController.show(
        context: context,
        builder: (_) => CupertinoTextMagnifier(
              controller: magnifierController,
              magnifierInfo: magnifierInfo,
            ));

    WidgetsBinding.instance.scheduleFrame();
    await tester.pumpAndSettle();

    await magnifierShown;
  }

  tearDown(() async {
      magnifierController.removeFromOverlay();
  });

  group('CupertinoTextEditingMagnifier', () {
    group('position', () {
      Offset getMagnifierPosition(WidgetTester tester) {
        final AnimatedPositioned animatedPositioned =
            tester.firstWidget(find.byType(AnimatedPositioned));
        return Offset(
            animatedPositioned.left ?? 0, animatedPositioned.top ?? 0);
      }

      testWidgets('should be at gesture position if does not violate any positioning rules', (WidgetTester tester) async {
        final Key fakeTextFieldKey = UniqueKey();
        final Key outerKey = UniqueKey();

        await tester.pumpWidget(
          Container(
            key: outerKey,
            color: const Color.fromARGB(255, 0, 255, 179),
            child: MaterialApp(
              home: Center(
                child: Container(
                  key: fakeTextFieldKey,
                  width: 10,
                  height: 10,
                  color: Colors.red,
                  child: const Placeholder(),
                ),
              ),
            ),
          ),
        );
        final BuildContext context = tester.element(find.byType(Placeholder));

        // Magnifier should be positioned directly over the red square.
        final RenderBox tapPointRenderBox =
            tester.firstRenderObject(find.byKey(fakeTextFieldKey)) as RenderBox;
        final Rect fakeTextFieldRect =
            tapPointRenderBox.localToGlobal(Offset.zero) & tapPointRenderBox.size;

        final ValueNotifier<MagnifierInfo> magnifier =
            ValueNotifier<MagnifierInfo>(
          MagnifierInfo(
            currentLineBoundaries: fakeTextFieldRect,
            fieldBounds: fakeTextFieldRect,
            caretRect: fakeTextFieldRect,
            // The tap position is dragBelow units below the text field.
            globalGesturePosition: fakeTextFieldRect.center,
          ),
        );

        await showCupertinoMagnifier(context, tester, magnifier);

        // Should show two red squares; original, and one in the magnifier,
        // directly ontop of one another.
        await expectLater(
          find.byKey(outerKey),
          matchesGoldenFile('cupertino_magnifier.position.default.png'),
        );
      });

      testWidgets('should never horizontally be outside of Screen Padding', (WidgetTester tester) async {
        await tester.pumpWidget(
          const MaterialApp(
            color: Color.fromARGB(7, 0, 129, 90),
            home: Placeholder(),
          ),
        );

        final BuildContext context = tester.firstElement(find.byType(Placeholder));

        await showCupertinoMagnifier(
          context,
          tester,
          ValueNotifier<MagnifierInfo>(
            MagnifierInfo(
              currentLineBoundaries: reasonableTextField,
              fieldBounds: reasonableTextField,
              caretRect: reasonableTextField,
              // The tap position is far out of the right side of the app.
              globalGesturePosition:
                  Offset(MediaQuery.of(context).size.width + 100, 0),
            ),
          ),
        );

        // Should be less than the right edge, since we have padding.
        expect(getMagnifierPosition(tester).dx,
            lessThan(MediaQuery.of(context).size.width));
      });

      testWidgets('should have some vertical drag', (WidgetTester tester) async {
        final double dragPositionBelowTextField = reasonableTextField.center.dy + 30;

        await tester.pumpWidget(
          const MaterialApp(
            color: Color.fromARGB(7, 0, 129, 90),
            home: Placeholder(),
          ),
        );

        final BuildContext context =
            tester.firstElement(find.byType(Placeholder));

        await showCupertinoMagnifier(
          context,
          tester,
          ValueNotifier<MagnifierInfo>(
            MagnifierInfo(
              currentLineBoundaries: reasonableTextField,
              fieldBounds: reasonableTextField,
              caretRect: reasonableTextField,
              // The tap position is dragBelow units below the text field.
              globalGesturePosition: Offset(
                  MediaQuery.of(context).size.width / 2,
                  dragPositionBelowTextField),
            ),
          ),
        );

        // The magnifier Y should be greater than the text field, since we "dragged" it down.
        expect(getMagnifierPosition(tester).dy + basicOffset.dy,
            greaterThan(reasonableTextField.center.dy));
        expect(getMagnifierPosition(tester).dy + basicOffset.dy,
            lessThan(dragPositionBelowTextField));
      });
    });

    group('status', () {
      testWidgets('should hide if gesture is far below the text field', (WidgetTester tester) async {
        await tester.pumpWidget(
          const MaterialApp(
            color: Color.fromARGB(7, 0, 129, 90),
            home: Placeholder(),
          ),
        );

        final BuildContext context =
            tester.firstElement(find.byType(Placeholder));

        final ValueNotifier<MagnifierInfo> magnifierinfo =
            ValueNotifier<MagnifierInfo>(
          MagnifierInfo(
            currentLineBoundaries: reasonableTextField,
            fieldBounds: reasonableTextField,
            caretRect: reasonableTextField,
            // The tap position is dragBelow units below the text field.
            globalGesturePosition: Offset(
                MediaQuery.of(context).size.width / 2, reasonableTextField.top),
          ),
        );

        // Show the magnifier initally, so that we get it in a not hidden state.
        await showCupertinoMagnifier(context, tester, magnifierinfo);

        // Move the gesture to one that should hide it.
        magnifierinfo.value = MagnifierInfo(
            currentLineBoundaries: reasonableTextField,
            fieldBounds: reasonableTextField,
            caretRect: reasonableTextField,
            globalGesturePosition: magnifierinfo.value.globalGesturePosition + const Offset(0, 100),
        );
        await tester.pumpAndSettle();

        expect(magnifierController.shown, false);
        expect(magnifierController.overlayEntry, isNotNull);
      });

      testWidgets('should re-show if gesture moves back up',
          (WidgetTester tester) async {
        await tester.pumpWidget(
          const MaterialApp(
            color: Color.fromARGB(7, 0, 129, 90),
            home: Placeholder(),
          ),
        );

        final BuildContext context =
            tester.firstElement(find.byType(Placeholder));

        final ValueNotifier<MagnifierInfo> magnifierInfo =
            ValueNotifier<MagnifierInfo>(
          MagnifierInfo(
            currentLineBoundaries: reasonableTextField,
            fieldBounds: reasonableTextField,
            caretRect: reasonableTextField,
            // The tap position is dragBelow units below the text field.
            globalGesturePosition: Offset(MediaQuery.of(context).size.width / 2, reasonableTextField.top),
          ),
        );

        // Show the magnifier initally, so that we get it in a not hidden state.
        await showCupertinoMagnifier(context, tester, magnifierInfo);

        // Move the gesture to one that should hide it.
        magnifierInfo.value = MagnifierInfo(
            currentLineBoundaries: reasonableTextField,
            fieldBounds: reasonableTextField,
            caretRect: reasonableTextField,
            globalGesturePosition:
                magnifierInfo.value.globalGesturePosition + const Offset(0, 100));
        await tester.pumpAndSettle();

        expect(magnifierController.shown, false);
        expect(magnifierController.overlayEntry, isNotNull);

        // Return the gesture to one that shows it.
        magnifierInfo.value = MagnifierInfo(
            currentLineBoundaries: reasonableTextField,
            fieldBounds: reasonableTextField,
            caretRect: reasonableTextField,
            globalGesturePosition: Offset(MediaQuery.of(context).size.width / 2,
                reasonableTextField.top));
        await tester.pumpAndSettle();

        expect(magnifierController.shown, true);
        expect(magnifierController.overlayEntry, isNotNull);
      });
    });
  });
}
