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

class _TestSliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
  _TestSliverPersistentHeaderDelegate({
    required this.minExtent,
    required this.maxExtent,
    required this.child,
    this.vsync = const TestVSync(),
    this.showOnScreenConfiguration = const PersistentHeaderShowOnScreenConfiguration(),
  });

  final Widget child;

  @override
  final double maxExtent;

  @override
  final double minExtent;

  @override
  final TickerProvider? vsync;

  @override
  final PersistentHeaderShowOnScreenConfiguration showOnScreenConfiguration;

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => child;

  @override
  bool shouldRebuild(_TestSliverPersistentHeaderDelegate oldDelegate) => true;
}

void main() {
  const TextStyle textStyle = TextStyle();
  const Color cursorColor = Color.fromARGB(0xFF, 0xFF, 0x00, 0x00);
    final FocusNode focusNode = FocusNode();

  testWidgets('tapping on a partly visible editable brings it fully on screen', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    final TextEditingController controller = TextEditingController();

    await tester.pumpWidget(MaterialApp(
      home: Center(
        child: SizedBox(
          height: 300.0,
          child: ListView(
            controller: scrollController,
            children: <Widget>[
              EditableText(
                backgroundCursorColor: Colors.grey,
                controller: controller,
                focusNode: focusNode,
                style: textStyle,
                cursorColor: cursorColor,
              ),
              const SizedBox(
                height: 350.0,
              ),
            ],
          ),
        ),
      ),
    ));

    // Scroll the EditableText half off screen.
    final RenderBox render = tester.renderObject(find.byType(EditableText));
    scrollController.jumpTo(render.size.height / 2);
    await tester.pumpAndSettle();
    expect(scrollController.offset, render.size.height / 2);

    await tester.showKeyboard(find.byType(EditableText));
    await tester.pumpAndSettle();
    expect(scrollController.offset, 0.0);
  });

  testWidgets('tapping on a partly visible editable brings it fully on screen with scrollInsets', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    final TextEditingController controller = TextEditingController();
    final FocusNode focusNode = FocusNode();

    await tester.pumpWidget(MaterialApp(
      home: Center(
        child: SizedBox(
          height: 300.0,
          child: ListView(
            controller: scrollController,
            children: <Widget>[
              const SizedBox(
                height: 200.0,
              ),
              EditableText(
                backgroundCursorColor: Colors.grey,
                scrollPadding: const EdgeInsets.all(50.0),
                controller: controller,
                focusNode: focusNode,
                style: textStyle,
                cursorColor: cursorColor,
              ),
              const SizedBox(
                height: 850.0,
              ),
            ],
          ),
        ),
      ),
    ));

    // Scroll the EditableText half off screen.
    final RenderBox render = tester.renderObject(find.byType(EditableText));
    scrollController.jumpTo(200 + render.size.height / 2);
    await tester.pumpAndSettle();
    expect(scrollController.offset, 200 + render.size.height / 2);

    await tester.showKeyboard(find.byType(EditableText));
    await tester.pumpAndSettle();
    // Container above the text is 200 in height, the scrollInsets are 50
    // Tolerance of 5 units (The actual value was 152.0 in the current tests instead of 150.0)
    expect(scrollController.offset, lessThan(200.0 - 50.0 + 5.0));
    expect(scrollController.offset, greaterThan(200.0 - 50.0 - 5.0));
  });

  testWidgets('editable comes back on screen when entering text while it is off-screen', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController(initialScrollOffset: 100.0);
    final TextEditingController controller = TextEditingController();
    final FocusNode focusNode = FocusNode();

    await tester.pumpWidget(MaterialApp(
      home: Center(
        child: SizedBox(
          height: 300.0,
          child: ListView(
            controller: scrollController,
            children: <Widget>[
              const SizedBox(
                height: 350.0,
              ),
              EditableText(
                backgroundCursorColor: Colors.grey,
                controller: controller,
                focusNode: focusNode,
                style: textStyle,
                cursorColor: cursorColor,
              ),
              const SizedBox(
                height: 350.0,
              ),
            ],
          ),
        ),
      ),
    ));

    // Focus the EditableText and scroll it off screen.
    await tester.showKeyboard(find.byType(EditableText));
    await tester.pumpAndSettle();
    expect(focusNode.hasFocus, isTrue);
    scrollController.jumpTo(0.0);
    await tester.pumpAndSettle();
    expect(scrollController.offset, 0.0);
    expect(find.byType(EditableText), findsNothing);

    // Entering text brings it back on screen.
    tester.testTextInput.enterText('Hello');
    await tester.pumpAndSettle();
    expect(scrollController.offset, greaterThan(0.0));
    expect(find.byType(EditableText), findsOneWidget);
  });

  testWidgets('entering text does not scroll when scrollPhysics.allowImplicitScrolling = false', (WidgetTester tester) async {
    // regression test for https://github.com/flutter/flutter/issues/19523

    final ScrollController scrollController = ScrollController(initialScrollOffset: 100.0);
    final TextEditingController controller = TextEditingController();
    final FocusNode focusNode = FocusNode();

    await tester.pumpWidget(MaterialApp(
      home: Center(
        child: SizedBox(
          height: 300.0,
          child: ListView(
            physics: const NoImplicitScrollPhysics(),
            controller: scrollController,
            children: <Widget>[
              const SizedBox(
                height: 350.0,
              ),
              EditableText(
                backgroundCursorColor: Colors.grey,
                controller: controller,
                focusNode: focusNode,
                style: textStyle,
                cursorColor: cursorColor,
              ),
              const SizedBox(
                height: 350.0,
              ),
            ],
          ),
        ),
      ),
    ));

    // Focus the EditableText and scroll it off screen.
    await tester.showKeyboard(find.byType(EditableText));
    await tester.pumpAndSettle();
    expect(focusNode.hasFocus, isTrue);
    scrollController.jumpTo(0.0);
    await tester.pumpAndSettle();
    expect(scrollController.offset, 0.0);
    expect(find.byType(EditableText), findsNothing);

    // Entering text brings it not back on screen.
    tester.testTextInput.enterText('Hello');
    await tester.pumpAndSettle();
    expect(scrollController.offset, 0.0);
    expect(find.byType(EditableText), findsNothing);
  });

  testWidgets('entering text does not scroll a surrounding PageView', (WidgetTester tester) async {
    // regression test for https://github.com/flutter/flutter/issues/19523

    final TextEditingController textController = TextEditingController();
    final PageController pageController = PageController(initialPage: 1);

    await tester.pumpWidget(
      MaterialApp(
        home: MediaQuery(
          data: const MediaQueryData(),
          child: Directionality(
            textDirection: TextDirection.ltr,
            child: Material(
              child: PageView(
                controller: pageController,
                children: <Widget>[
                  Container(
                    color: Colors.red,
                  ),
                  Container(
                    color: Colors.green,
                    child: TextField(
                      controller: textController,
                    ),
                  ),
                  Container(
                    color: Colors.red,
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );

    await tester.showKeyboard(find.byType(EditableText));
    await tester.pumpAndSettle();
    expect(textController.text, '');
    tester.testTextInput.enterText('H');
    final int frames = await tester.pumpAndSettle();

    // The text input should not trigger any animations, which would indicate
    // that the surrounding PageView is incorrectly scrolling back-and-forth.
    expect(frames, 1);

    expect(textController.text, 'H');
  });

  testWidgets('focused multi-line editable scrolls caret back into view when typing', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    final TextEditingController controller = TextEditingController();
    final FocusNode focusNode = FocusNode();
    controller.text = 'Start\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEnd';

    await tester.pumpWidget(MaterialApp(
      home: Center(
        child: SizedBox(
          height: 300.0,
          child: ListView(
            controller: scrollController,
            children: <Widget>[
              EditableText(
                backgroundCursorColor: Colors.grey,
                maxLines: null, // multiline
                controller: controller,
                focusNode: focusNode,
                style: textStyle,
                cursorColor: cursorColor,
              ),
            ],
          ),
        ),
      ),
    ));

    // Bring keyboard up and verify that end of EditableText is not on screen.
    await tester.showKeyboard(find.byType(EditableText));
    await tester.pumpAndSettle();
    scrollController.jumpTo(0.0);
    await tester.pumpAndSettle();
    final RenderBox render = tester.renderObject(find.byType(EditableText));
    expect(render.size.height, greaterThan(500.0));
    expect(scrollController.offset, 0.0);

    // Enter text at end, which is off-screen.
    final String textToEnter = '${controller.text} HELLO';
    tester.testTextInput.updateEditingValue(TextEditingValue(
      text: textToEnter,
      selection: TextSelection.collapsed(offset: textToEnter.length),
    ));
    await tester.pumpAndSettle();

    // Caret scrolls into view.
    expect(find.byType(EditableText), findsOneWidget);
    expect(render.size.height, greaterThan(500.0));
    expect(scrollController.offset, greaterThan(0.0));
  });

  testWidgets('scrolls into view with scrollInserts after the keyboard pops up', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    final TextEditingController controller = TextEditingController();
    final FocusNode focusNode = FocusNode();

    const Key container = Key('container');

    await tester.pumpWidget(MaterialApp(
      home: Align(
        alignment: Alignment.bottomCenter,
        child: SizedBox(
          height: 300.0,
          child: ListView(
            controller: scrollController,
            children: <Widget>[
              const SizedBox(
                key: container,
                height: 200.0,
              ),
              EditableText(
                backgroundCursorColor: Colors.grey,
                scrollPadding: const EdgeInsets.only(bottom: 300.0),
                controller: controller,
                focusNode: focusNode,
                style: textStyle,
                cursorColor: cursorColor,
              ),
              const SizedBox(
                height: 400.0,
              ),
            ],
          ),
        ),
      ),
    ));

    expect(scrollController.offset, 0.0);

    await tester.showKeyboard(find.byType(EditableText));
    await tester.pumpAndSettle();
    expect(scrollController.offset, greaterThan(0.0));
    expect(find.byKey(container), findsNothing);
  });

  testWidgets(
    'A pinned persistent header should not scroll when its descendant EditableText gains focus',
    (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/25507.
      ScrollController controller;
      final TextEditingController textEditingController = TextEditingController();
      final FocusNode focusNode = FocusNode();

      const Key headerKey = Key('header');
      await tester.pumpWidget(
        MaterialApp(
          home: Center(
            child: SizedBox(
              height: 600.0,
              width: 600.0,
              child: CustomScrollView(
                controller: controller = ScrollController(),
                slivers: List<Widget>.generate(50, (int i) {
                  return i == 10
                  ? SliverPersistentHeader(
                    pinned: true,
                    delegate: _TestSliverPersistentHeaderDelegate(
                      minExtent: 50,
                      maxExtent: 50,
                      child: Container(
                        alignment: Alignment.topCenter,
                        child: EditableText(
                          key: headerKey,
                          backgroundCursorColor: Colors.grey,
                          controller: textEditingController,
                          focusNode: focusNode,
                          style: textStyle,
                          cursorColor: cursorColor,
                        ),
                      ),
                    ),
                  )
                  : SliverToBoxAdapter(
                    child: SizedBox(
                      height: 100.0,
                      child: Text('Tile $i'),
                    ),
                  );
                }),
              ),
            ),
          ),
        ),
      );

      // The persistent header should now be pinned at the top.
      controller.jumpTo(100.0 * 15);
      await tester.pumpAndSettle();
      expect(controller.offset, 100.0 * 15);

      focusNode.requestFocus();
      await tester.pumpAndSettle();
      // The scroll offset should remain the same.
      expect(controller.offset, 100.0 * 15);
    },
  );

  testWidgets(
    'A pinned persistent header should not scroll when its descendant EditableText gains focus (no animation)',
    (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/25507.
      ScrollController controller;
      final TextEditingController textEditingController = TextEditingController();
      final FocusNode focusNode = FocusNode();

      const Key headerKey = Key('header');
      await tester.pumpWidget(
        MaterialApp(
          home: Center(
            child: SizedBox(
              height: 600.0,
              width: 600.0,
              child: CustomScrollView(
                controller: controller = ScrollController(),
                slivers: List<Widget>.generate(50, (int i) {
                  return i == 10
                    ? SliverPersistentHeader(
                      pinned: true,
                      delegate: _TestSliverPersistentHeaderDelegate(
                        minExtent: 50,
                        maxExtent: 50,
                        vsync: null,
                        child: Container(
                          alignment: Alignment.topCenter,
                          child: EditableText(
                            key: headerKey,
                            backgroundCursorColor: Colors.grey,
                            controller: textEditingController,
                            focusNode: focusNode,
                            style: textStyle,
                            cursorColor: cursorColor,
                          ),
                        ),
                      ),
                    )
                    : SliverToBoxAdapter(
                      child: SizedBox(
                        height: 100.0,
                        child: Text('Tile $i'),
                      ),
                    );
                }),
              ),
            ),
          ),
        ),
      );

      // The persistent header should now be pinned at the top.
      controller.jumpTo(100.0 * 15);
      await tester.pumpAndSettle();
      expect(controller.offset, 100.0 * 15);

      focusNode.requestFocus();
      await tester.pumpAndSettle();
      // The scroll offset should remain the same.
      expect(controller.offset, 100.0 * 15);
    },
  );

  void testShowCaretOnScreen({ required bool readOnly }) {
    group('EditableText._showCaretOnScreen, readOnly=$readOnly', () {
      final TextEditingController textEditingController = TextEditingController();
      final TextInputFormatter rejectEverythingFormatter = TextInputFormatter.withFunction((TextEditingValue old, TextEditingValue value) => old);

      bool isCaretOnScreen(WidgetTester tester) {
        final EditableTextState state = tester.state<EditableTextState>(
          find.byType(EditableText, skipOffstage: false),
        );
        final RenderEditable renderEditable = state.renderEditable;
        final Rect localRect = renderEditable.getLocalRectForCaret(state.textEditingValue.selection.base);
        final Offset caretOrigin = renderEditable.localToGlobal(localRect.topLeft);
        final Rect caretRect = caretOrigin & localRect.size;
        return const Rect.fromLTWH(0, 0,  800, 600).intersect(caretRect) == caretRect;
      }

      Widget buildEditableText({
        required bool rejectUserInputs,
        ScrollController? scrollController,
        ScrollController? editableScrollController,
      }) {
        return MaterialApp(
          home: Scaffold(
            body: ListView(
              controller: scrollController,
              cacheExtent: 1000,
              children: <Widget>[
                // The text field is not fully visible.
                const SizedBox(height: 599),
                EditableText(
                  backgroundCursorColor: Colors.grey,
                  controller: textEditingController,
                  scrollController: editableScrollController,
                  inputFormatters: <TextInputFormatter>[if (rejectUserInputs) rejectEverythingFormatter],
                  focusNode: focusNode,
                  style: textStyle,
                  cursorColor: cursorColor,
                  readOnly: readOnly,
                ),
              ],
            ),
          ),
        );
      }

      testWidgets('focus-triggered showCaretOnScreen', (WidgetTester tester) async {
        textEditingController.text = 'a' * 100;
        textEditingController.selection = const TextSelection.collapsed(offset: 100);
        final ScrollController scrollController = ScrollController();
        final ScrollController editableScrollController = ScrollController();

        await tester.pumpWidget(
          buildEditableText(
            rejectUserInputs: false,
            scrollController: scrollController,
            editableScrollController: editableScrollController,
          ),
        );

        focusNode.requestFocus();
        await tester.pumpAndSettle();

        expect(isCaretOnScreen(tester), !readOnly);
        expect(scrollController.offset, readOnly ? 0.0 : greaterThan(0.0));
        expect(editableScrollController.offset, readOnly ? 0.0 : greaterThan(0.0));
      });

      testWidgets('selection-triggered showCaretOnScreen: virtual keyboard', (WidgetTester tester) async {
        textEditingController.text = 'a' * 100;
        textEditingController.selection = const TextSelection.collapsed(offset: 80);
        final ScrollController scrollController = ScrollController();
        final ScrollController editableScrollController = ScrollController();

        await tester.pumpWidget(
          buildEditableText(
            rejectUserInputs: false,
            scrollController: scrollController,
            editableScrollController: editableScrollController,
          ),
        );

        focusNode.requestFocus();
        await tester.pumpAndSettle();

        // Ensure the caret is not fully visible and the text field is focused.
        scrollController.jumpTo(0);
        editableScrollController.jumpTo(0);
        await tester.pumpAndSettle();
        expect(isCaretOnScreen(tester), isFalse);

        final EditableTextState state = tester.state<EditableTextState>(
          find.byType(EditableText, skipOffstage: false),
        );

        // Change the selection. Show caret on screen when readyOnly is true,
        // as a read-only text field rejects everything from the software
        // keyboard (except for web).
        state.updateEditingValue(state.textEditingValue.copyWith(selection: const TextSelection.collapsed(offset: 90)));
        await tester.pumpAndSettle();
        expect(isCaretOnScreen(tester), !readOnly || kIsWeb);
        expect(scrollController.offset, readOnly && !kIsWeb ? 0.0 : greaterThan(0.0));
        expect(editableScrollController.offset, readOnly && !kIsWeb ? 0.0 : greaterThan(0.0));

        // Reject user input.
        await tester.pumpWidget(
          buildEditableText(
            rejectUserInputs: true,
            scrollController: scrollController,
            editableScrollController: editableScrollController,
          ),
        );

        // Ensure the caret is not fully visible and the text field is focused.
        scrollController.jumpTo(0);
        editableScrollController.jumpTo(0);
        await tester.pumpAndSettle();
        expect(isCaretOnScreen(tester), isFalse);

        state.updateEditingValue(state.textEditingValue.copyWith(selection: const TextSelection.collapsed(offset: 100)));
        await tester.pumpAndSettle();
        expect(isCaretOnScreen(tester), !readOnly || kIsWeb);
        expect(scrollController.offset, readOnly && !kIsWeb ? 0.0 : greaterThan(0.0));
        expect(editableScrollController.offset, readOnly && !kIsWeb ? 0.0 : greaterThan(0.0));
      });

      testWidgets('selection-triggered showCaretOnScreen: text selection delegate', (WidgetTester tester) async {
        textEditingController.text = 'a' * 100;
        textEditingController.selection = const TextSelection.collapsed(offset: 80);
        final ScrollController scrollController = ScrollController();
        final ScrollController editableScrollController = ScrollController();

        await tester.pumpWidget(
          buildEditableText(
            rejectUserInputs: false,
            scrollController: scrollController,
            editableScrollController: editableScrollController,
          ),
        );

        focusNode.requestFocus();
        await tester.pumpAndSettle();

        // Ensure the caret is not fully visible and the text field is focused.
        scrollController.jumpTo(0);
        editableScrollController.jumpTo(0);
        await tester.pumpAndSettle();
        expect(isCaretOnScreen(tester), isFalse);

        final EditableTextState state = tester.state<EditableTextState>(
          find.byType(EditableText, skipOffstage: false),
        );

        // Change the selection. Show caret on screen even when readyOnly is
        // false.
        state.userUpdateTextEditingValue(
          state.textEditingValue.copyWith(selection: const TextSelection.collapsed(offset: 90)),
          null,
        );
        await tester.pumpAndSettle();
        expect(isCaretOnScreen(tester), isTrue);
        expect(scrollController.offset, greaterThan(0.0));
        expect(editableScrollController.offset, greaterThan(0.0));

        // Rejects user input.
        await tester.pumpWidget(
          buildEditableText(
            rejectUserInputs: true,
            scrollController: scrollController,
            editableScrollController: editableScrollController,
          ),
        );

        // Ensure the caret is not fully visible and the text field is focused.
        scrollController.jumpTo(0);
        editableScrollController.jumpTo(0);
        await tester.pumpAndSettle();
        expect(isCaretOnScreen(tester), isFalse);

        state.userUpdateTextEditingValue(
          state.textEditingValue.copyWith(selection: const TextSelection.collapsed(offset: 100)),
          null,
        );
        await tester.pumpAndSettle();
        expect(isCaretOnScreen(tester), isTrue);
        expect(scrollController.offset, greaterThan(0.0));
        expect(editableScrollController.offset, greaterThan(0.0));
      });

      // Regression text for https://github.com/flutter/flutter/pull/74722.
      testWidgets('does NOT randomly trigger when cursor blinks', (WidgetTester tester) async {
        textEditingController.text = 'a' * 100;
        textEditingController.selection = const TextSelection.collapsed(offset: 0);
        final ScrollController editableScrollController = ScrollController();
        final bool deterministicCursor = EditableText.debugDeterministicCursor;
        EditableText.debugDeterministicCursor = false;

        await tester.pumpWidget(
          MaterialApp(
            home: Scaffold(
              body: EditableText(
                backgroundCursorColor: Colors.grey,
                controller: textEditingController,
                scrollController: editableScrollController,
                focusNode: focusNode,
                style: textStyle,
                cursorColor: cursorColor,
              ),
            ),
          ),
        );

        final EditableTextState state = tester.state<EditableTextState>(
          find.byType(EditableText, skipOffstage: false),
        );

        // Ensure the text was initially visible.
        expect(isCaretOnScreen(tester), true);
        expect(editableScrollController.offset, 0.0);

        // Change the text but keep the cursor location.
        state.updateEditingValue(textEditingController.value.copyWith(
          text: 'a' * 101,
        ));

        await tester.pumpAndSettle();

        // The caret should stay where it was, since the selection didn't change.
        expect(isCaretOnScreen(tester), true);
        expect(editableScrollController.offset, 0.0);

        // Now move to hide the cursor.
        editableScrollController.jumpTo(100.0);

        // Does not trigger showCaretOnScreen.
        await tester.pump();
        await tester.pumpAndSettle();
        expect(editableScrollController.offset, 100.0);
        expect(isCaretOnScreen(tester), isFalse);

        EditableText.debugDeterministicCursor = deterministicCursor;
      });
    });
  }

  testShowCaretOnScreen(readOnly: true);
  testShowCaretOnScreen(readOnly: false);
}

class NoImplicitScrollPhysics extends AlwaysScrollableScrollPhysics {
  const NoImplicitScrollPhysics({ ScrollPhysics? parent }) : super(parent: parent);

  @override
  bool get allowImplicitScrolling => false;

  @override
  NoImplicitScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return NoImplicitScrollPhysics(parent: buildParent(ancestor));
  }
}
