// 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_test/flutter_test.dart';

void main() {
  final basicOffset = Offset(
    CupertinoMagnifier.kDefaultSize.width / 2,
    CupertinoMagnifier.kDefaultSize.height - CupertinoMagnifier.kMagnifierAboveFocalPoint,
  );
  const reasonableTextField = Rect.fromLTRB(0, 100, 200, 200);
  final 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: (BuildContext context) =>
          CupertinoTextMagnifier(controller: magnifierController, magnifierInfo: magnifierInfo),
    );
    await tester.pump();
    await tester.pump(const Duration(seconds: 2));
    await magnifierShown;
  }

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

  group('CupertinoTextEditingMagnifier', () {
    testWidgets('Magnifier border color inherits from parent CupertinoTheme', (
      WidgetTester tester,
    ) async {
      final Key fakeTextFieldKey = UniqueKey();

      await tester.pumpWidget(
        CupertinoApp(
          home: SizedBox.square(
            key: fakeTextFieldKey,
            dimension: 10,
            child: CupertinoTheme(
              data: const CupertinoThemeData(primaryColor: CupertinoColors.activeGreen),
              child: Builder(
                builder: (BuildContext context) {
                  return const Placeholder();
                },
              ),
            ),
          ),
        ),
      );
      final BuildContext context = tester.element(find.byType(Placeholder));

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

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

      await showCupertinoMagnifier(context, tester, magnifier);

      // Magnifier border color should inherit from CupertinoTheme.of(context).primaryColor.
      final Color magnifierBorderColor = tester
          .widget<CupertinoMagnifier>(find.byType(CupertinoMagnifier))
          .borderSide
          .color;
      expect(magnifierBorderColor, equals(CupertinoColors.activeGreen));
    });

    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(
          CupertinoApp(
            key: outerKey,
            theme: const CupertinoThemeData(primaryColor: Color(0xFF6750A4)),
            // The CupertinoApp adds a `CupertinoUserInterfaceLevel` widget,
            // which has effect on the color of the background behind the child.
            // So enforce a consistent background color that fills the background.
            home: ColoredBox(
              color: const Color.fromARGB(255, 0, 255, 179),
              child: Center(
                child: Container(
                  key: fakeTextFieldKey,
                  width: 10,
                  height: 10,
                  color: const Color(0xFFF44336),
                  child: const Placeholder(),
                ),
              ),
            ),
          ),
        );
        final BuildContext context = tester.element(find.byType(Placeholder));

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

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

        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 CupertinoApp(color: Color.fromARGB(7, 0, 129, 90), home: Placeholder()),
        );

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

        final magnifierInfo = 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.sizeOf(context).width + 100, 0),
          ),
        );
        addTearDown(magnifierInfo.dispose);
        await showCupertinoMagnifier(context, tester, magnifierInfo);

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

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

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

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

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

        // 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 CupertinoApp(color: Color.fromARGB(7, 0, 129, 90), home: Placeholder()),
        );

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

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

        // Show the magnifier initially, 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 CupertinoApp(color: Color.fromARGB(7, 0, 129, 90), home: Placeholder()),
        );

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

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

        // Show the magnifier initially, 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.sizeOf(context).width / 2,
            reasonableTextField.top,
          ),
        );
        await tester.pumpAndSettle();

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

    group('magnificationScale', () {
      testWidgets('Throws assertion error when magnificationScale is zero', (
        WidgetTester tester,
      ) async {
        expect(
          () => CupertinoPageScaffold(child: CupertinoMagnifier(magnificationScale: 0)),
          throwsAssertionError,
        );
      });

      testWidgets('Throws assertion error when magnificationScale is negative', (
        WidgetTester tester,
      ) async {
        expect(
          () => CupertinoPageScaffold(child: CupertinoMagnifier(magnificationScale: -1)),
          throwsAssertionError,
        );
      });

      testWidgets('CupertinoMagnifier magnification scale defaults to 1', (
        WidgetTester tester,
      ) async {
        await tester.pumpWidget(
          const CupertinoApp(home: CupertinoPageScaffold(child: CupertinoMagnifier())),
        );

        expect(
          tester.widget(find.byType(RawMagnifier)),
          isA<RawMagnifier>().having(
            (RawMagnifier t) => t.magnificationScale,
            'magnificationScale',
            1,
          ),
        );
      });

      testWidgets('Magnification scale argument is passed to the RawMagnifier', (
        WidgetTester tester,
      ) async {
        await tester.pumpWidget(
          const CupertinoApp(
            home: CupertinoPageScaffold(child: CupertinoMagnifier(magnificationScale: 2)),
          ),
        );

        expect(
          tester.widget(find.byType(RawMagnifier)),
          isA<RawMagnifier>().having(
            (RawMagnifier t) => t.magnificationScale,
            'magnificationScale',
            2,
          ),
        );
      });
    });
  });

  testWidgets('CupertinoMagnifier does not crash at zero area', (WidgetTester tester) async {
    await tester.pumpWidget(
      const CupertinoApp(
        home: Center(child: SizedBox.shrink(child: CupertinoMagnifier(magnificationScale: 2))),
      ),
    );
    expect(tester.getSize(find.byType(CupertinoMagnifier)), Size.zero);
  });

  testWidgets('RawMagnifier does not crash at zero area', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: SizedBox.shrink(
            child: RawMagnifier(size: Size.square(2), child: Text('X')),
          ),
        ),
      ),
    );
    expect(tester.getSize(find.byType(RawMagnifier)), Size.zero);
  });
}
