// 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'])
library;

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

void main() {
  final MagnifierController magnifierController = MagnifierController();
  const Rect reasonableTextField = Rect.fromLTRB(50, 100, 200, 100);
  final Offset basicOffset = Offset(Magnifier.kDefaultMagnifierSize.width / 2,
      Magnifier.kStandardVerticalFocalPointShift + Magnifier.kDefaultMagnifierSize.height);

  Offset getMagnifierPosition(WidgetTester tester, [bool animated = false]) {
    if (animated) {
      final AnimatedPositioned animatedPositioned =
          tester.firstWidget(find.byType(AnimatedPositioned));
      return Offset(animatedPositioned.left ?? 0, animatedPositioned.top ?? 0);
    } else {
      final Positioned positioned = tester.firstWidget(find.byType(Positioned));
      return Offset(positioned.left ?? 0, positioned.top ?? 0);
    }
  }

  Future<void> showMagnifier(
    BuildContext context,
    WidgetTester tester,
    ValueNotifier<MagnifierInfo> magnifierInfo,
  ) async {
    final Future<void> magnifierShown = magnifierController.show(
        context: context,
        builder: (_) => TextMagnifier(
              magnifierInfo: magnifierInfo,
            ));

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

    // Verify that the magnifier is shown.
    await magnifierShown;
  }

  tearDown(() {
    magnifierController.removeFromOverlay();
    magnifierController.animationController = null;
  });

  group('adaptiveMagnifierControllerBuilder', () {
    testWidgets('should return a TextEditingMagnifier on Android',
        (WidgetTester tester) async {
      await tester.pumpWidget(const MaterialApp(
        home: Placeholder(),
      ));

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

      final ValueNotifier<MagnifierInfo> magnifierPositioner = ValueNotifier<MagnifierInfo>(MagnifierInfo.empty);
      addTearDown(magnifierPositioner.dispose);

      final Widget? builtWidget = TextMagnifier.adaptiveMagnifierConfiguration.magnifierBuilder(
        context,
        MagnifierController(),
        magnifierPositioner,
      );

      expect(builtWidget, isA<TextMagnifier>());
    }, variant: TargetPlatformVariant.only(TargetPlatform.android));

    testWidgets('should return a CupertinoMagnifier on iOS',
        (WidgetTester tester) async {
      await tester.pumpWidget(const MaterialApp(
        home: Placeholder(),
      ));

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

      final ValueNotifier<MagnifierInfo> magnifierPositioner = ValueNotifier<MagnifierInfo>(MagnifierInfo.empty);
      addTearDown(magnifierPositioner.dispose);

      final Widget? builtWidget = TextMagnifier.adaptiveMagnifierConfiguration.magnifierBuilder(
        context,
        MagnifierController(),
        magnifierPositioner,
      );

      expect(builtWidget, isA<CupertinoTextMagnifier>());
    }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));

    testWidgets('should return null on all platforms not Android, iOS',
        (WidgetTester tester) async {
      await tester.pumpWidget(const MaterialApp(
        home: Placeholder(),
      ));

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

      final ValueNotifier<MagnifierInfo> magnifierPositioner = ValueNotifier<MagnifierInfo>(MagnifierInfo.empty);
      addTearDown(magnifierPositioner.dispose);

      final Widget? builtWidget = TextMagnifier.adaptiveMagnifierConfiguration.magnifierBuilder(
        context,
        MagnifierController(),
        magnifierPositioner,
      );

      expect(builtWidget, isNull);
    },
      variant: TargetPlatformVariant.all(
        excluding: <TargetPlatform>{
          TargetPlatform.iOS,
          TargetPlatform.android
        }),
      );
  });

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

        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

        await tester.pumpWidget(
          ColoredBox(
            color: const Color.fromARGB(255, 0, 255, 179),
            child: MaterialApp(
              home: Center(
                child: Container(
                  key: textField,
                  width: 10,
                  height: 10,
                  color: Colors.red,
                  child: const Placeholder(),
                ),
              ),
            ),
          ),
        );

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

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

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

        await showMagnifier(context, tester, magnifierInfo);

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

      testWidgets(
          'should never move outside the right bounds of the editing line',
          (WidgetTester tester) async {
        const double gestureOutsideLine = 100;

        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

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

        late ValueNotifier<MagnifierInfo> magnifierPositioner;
        addTearDown(() => magnifierPositioner.dispose());

        await showMagnifier(
          context,
          tester,
          magnifierPositioner = ValueNotifier<MagnifierInfo>(
            MagnifierInfo(
              currentLineBoundaries: reasonableTextField,
              // Inflate these two to make sure we're bounding on the
              // current line boundaries, not anything else.
              fieldBounds: reasonableTextField.inflate(gestureOutsideLine),
              caretRect: reasonableTextField.inflate(gestureOutsideLine),
              // The tap position is far out of the right side of the app.
              globalGesturePosition: Offset(reasonableTextField.right + gestureOutsideLine, 0),
            ),
          ),
        );

        // Should be less than the right edge, since we have padding.
        expect(getMagnifierPosition(tester).dx,
            lessThanOrEqualTo(reasonableTextField.right));
      });

      testWidgets(
          'should never move outside the left bounds of the editing line',
          (WidgetTester tester) async {
        const double gestureOutsideLine = 100;

        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

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

        late ValueNotifier<MagnifierInfo> magnifierPositioner;
        addTearDown(() => magnifierPositioner.dispose());

        await showMagnifier(
          context,
          tester,
          magnifierPositioner = ValueNotifier<MagnifierInfo>(
            MagnifierInfo(
              currentLineBoundaries: reasonableTextField,
              // Inflate these two to make sure we're bounding on the
              // current line boundaries, not anything else.
              fieldBounds: reasonableTextField.inflate(gestureOutsideLine),
              caretRect: reasonableTextField.inflate(gestureOutsideLine),
              // The tap position is far out of the left side of the app.
              globalGesturePosition: Offset(reasonableTextField.left - gestureOutsideLine, 0),
            ),
          ),
        );

        expect(getMagnifierPosition(tester).dx + basicOffset.dx,
            greaterThanOrEqualTo(reasonableTextField.left));
      });

      testWidgets('should position vertically at the center of the line', (WidgetTester tester) async {
        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

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

        late ValueNotifier<MagnifierInfo> magnifierPositioner;
        addTearDown(() => magnifierPositioner.dispose());

        await showMagnifier(
            context,
            tester,
            magnifierPositioner = ValueNotifier<MagnifierInfo>(
                MagnifierInfo(
              currentLineBoundaries: reasonableTextField,
              fieldBounds: reasonableTextField,
              caretRect: reasonableTextField,
              globalGesturePosition: reasonableTextField.center,
            )));

        expect(getMagnifierPosition(tester).dy,
            reasonableTextField.center.dy - basicOffset.dy);
      });

      testWidgets('should reposition vertically if mashed against the ceiling',
          (WidgetTester tester) async {
        final Rect topOfScreenTextFieldRect =
            Rect.fromPoints(Offset.zero, const Offset(200, 0));

        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

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

        late ValueNotifier<MagnifierInfo> magnifierPositioner;
        addTearDown(() => magnifierPositioner.dispose());

        await showMagnifier(
          context,
          tester,
          magnifierPositioner = ValueNotifier<MagnifierInfo>(
            MagnifierInfo(
              currentLineBoundaries: topOfScreenTextFieldRect,
              fieldBounds: topOfScreenTextFieldRect,
              caretRect: topOfScreenTextFieldRect,
              globalGesturePosition: topOfScreenTextFieldRect.topCenter,
            ),
          ),
        );

        expect(getMagnifierPosition(tester).dy, greaterThanOrEqualTo(0));
      });
    });

    group('focal point', () {
      Offset getMagnifierAdditionalFocalPoint(WidgetTester tester) {
        final Magnifier magnifier = tester.firstWidget(find.byType(Magnifier));
        return magnifier.additionalFocalPointOffset;
      }

      testWidgets(
          'should shift focal point so that the lens sees nothing out of bounds',
          (WidgetTester tester) async {
        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

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

        late ValueNotifier<MagnifierInfo> magnifierPositioner;
        addTearDown(() => magnifierPositioner.dispose());

        await showMagnifier(
          context,
          tester,
          magnifierPositioner =  ValueNotifier<MagnifierInfo>(
            MagnifierInfo(
              currentLineBoundaries: reasonableTextField,
              fieldBounds: reasonableTextField,
              caretRect: reasonableTextField,
              // Gesture on the far right of the magnifier.
              globalGesturePosition: reasonableTextField.topLeft,
            ),
          ),
        );

        expect(getMagnifierAdditionalFocalPoint(tester).dx,
            lessThan(reasonableTextField.left));
      });

      testWidgets(
          'focal point should shift if mashed against the top to always point to text',
          (WidgetTester tester) async {
        final Rect topOfScreenTextFieldRect =
            Rect.fromPoints(Offset.zero, const Offset(200, 0));

        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

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

        late ValueNotifier<MagnifierInfo> magnifierPositioner;
        addTearDown(() => magnifierPositioner.dispose());

        await showMagnifier(
          context,
          tester,
          magnifierPositioner = ValueNotifier<MagnifierInfo>(
            MagnifierInfo(
              currentLineBoundaries: topOfScreenTextFieldRect,
              fieldBounds: topOfScreenTextFieldRect,
              caretRect: topOfScreenTextFieldRect,
              globalGesturePosition: topOfScreenTextFieldRect.topCenter,
            ),
          ),
        );

        expect(getMagnifierAdditionalFocalPoint(tester).dy, lessThan(0));
      });
    });

    group('animation state', () {
      bool getIsAnimated(WidgetTester tester) {
        final AnimatedPositioned animatedPositioned =
            tester.firstWidget(find.byType(AnimatedPositioned));
        return animatedPositioned.duration.compareTo(Duration.zero) != 0;
      }

      testWidgets('should not be animated on the initial state',
          (WidgetTester tester) async {
        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

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

        late ValueNotifier<MagnifierInfo> magnifierInfo;
        addTearDown(() => magnifierInfo.dispose());

        await showMagnifier(
          context,
          tester,
          magnifierInfo = ValueNotifier<MagnifierInfo>(
            MagnifierInfo(
              currentLineBoundaries: reasonableTextField,
              fieldBounds: reasonableTextField,
              caretRect: reasonableTextField,
              globalGesturePosition: reasonableTextField.center,
            ),
          ),
        );

        expect(getIsAnimated(tester), false);
      });

      testWidgets('should not be animated on horizontal shifts',
          (WidgetTester tester) async {
        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

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

        final ValueNotifier<MagnifierInfo> magnifierPositioner = ValueNotifier<MagnifierInfo>(
          MagnifierInfo(
            currentLineBoundaries: reasonableTextField,
            fieldBounds: reasonableTextField,
            caretRect: reasonableTextField,
            globalGesturePosition: reasonableTextField.center,
          ),
        );
        addTearDown(magnifierPositioner.dispose);

        await showMagnifier(context, tester, magnifierPositioner);

        // New position has a horizontal shift.
        magnifierPositioner.value = MagnifierInfo(
          currentLineBoundaries: reasonableTextField,
          fieldBounds: reasonableTextField,
          caretRect: reasonableTextField,
          globalGesturePosition:
              reasonableTextField.center + const Offset(200, 0),
        );
        await tester.pumpAndSettle();

        expect(getIsAnimated(tester), false);
      });

      testWidgets('should be animated on vertical shifts',
          (WidgetTester tester) async {
        const Offset verticalShift = Offset(0, 200);

        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

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

        final ValueNotifier<MagnifierInfo> magnifierPositioner = ValueNotifier<MagnifierInfo>(
          MagnifierInfo(
            currentLineBoundaries: reasonableTextField,
            fieldBounds: reasonableTextField,
            caretRect: reasonableTextField,
            globalGesturePosition: reasonableTextField.center,
          ),
        );
        addTearDown(magnifierPositioner.dispose);

        await showMagnifier(context, tester, magnifierPositioner);

        // New position has a vertical shift.
        magnifierPositioner.value = MagnifierInfo(
          currentLineBoundaries: reasonableTextField.shift(verticalShift),
          fieldBounds: Rect.fromPoints(reasonableTextField.topLeft,
              reasonableTextField.bottomRight + verticalShift),
          caretRect: reasonableTextField.shift(verticalShift),
          globalGesturePosition: reasonableTextField.center + verticalShift,
        );

        await tester.pump();
        expect(getIsAnimated(tester), true);
      });

      testWidgets('should stop being animated when timer is up',
          (WidgetTester tester) async {
        const Offset verticalShift = Offset(0, 200);

        await tester.pumpWidget(const MaterialApp(
          home: Placeholder(),
        ));

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

        final ValueNotifier<MagnifierInfo> magnifierPositioner = ValueNotifier<MagnifierInfo>(
          MagnifierInfo(
            currentLineBoundaries: reasonableTextField,
            fieldBounds: reasonableTextField,
            caretRect: reasonableTextField,
            globalGesturePosition: reasonableTextField.center,
          ),
        );
        addTearDown(magnifierPositioner.dispose);

        await showMagnifier(context, tester, magnifierPositioner);

        // New position has a vertical shift.
        magnifierPositioner.value = MagnifierInfo(
          currentLineBoundaries: reasonableTextField.shift(verticalShift),
          fieldBounds: Rect.fromPoints(reasonableTextField.topLeft,
              reasonableTextField.bottomRight + verticalShift),
          caretRect: reasonableTextField.shift(verticalShift),
          globalGesturePosition: reasonableTextField.center + verticalShift,
        );

        await tester.pump();
        expect(getIsAnimated(tester), true);
        await tester.pump(TextMagnifier.jumpBetweenLinesAnimationDuration +
            const Duration(seconds: 2));
        expect(getIsAnimated(tester), false);
      });
    });
  });
}
