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

import '../rendering/mock_canvas.dart';

class User {
  const User({
    required this.email,
    required this.name,
  });

  final String email;
  final String name;

  @override
  String toString() {
    return '$name, $email';
  }
}

void main() {
  const List<String> kOptions = <String>[
    'aardvark',
    'bobcat',
    'chameleon',
    'dingo',
    'elephant',
    'flamingo',
    'goose',
    'hippopotamus',
    'iguana',
    'jaguar',
    'koala',
    'lemur',
    'mouse',
    'northern white rhinoceros',
  ];

  const List<User> kOptionsUsers = <User>[
    User(name: 'Alice', email: 'alice@example.com'),
    User(name: 'Bob', email: 'bob@example.com'),
    User(name: 'Charlie', email: 'charlie123@gmail.com'),
  ];

  testWidgets('can filter and select a list of string options', (WidgetTester tester) async {
    late String lastSelection;
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<String>(
            onSelected: (String selection) {
              lastSelection = selection;
            },
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);

    // Focus the empty field. All the options are displayed.
    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    ListView list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, kOptions.length);

    // Enter text. The options are filtered by the text.
    await tester.enterText(find.byType(TextFormField), 'ele');
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsOneWidget);
    list = find.byType(ListView).evaluate().first.widget as ListView;
    // 'chameleon' and 'elephant' are displayed.
    expect(list.semanticChildCount, 2);

    // Select a option. The options hide and the field updates to show the
    // selection.
    await tester.tap(find.byType(InkWell).first);
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);
    final TextFormField field = find.byType(TextFormField).evaluate().first.widget as TextFormField;
    expect(field.controller!.text, 'chameleon');
    expect(lastSelection, 'chameleon');

    // Modify the field text. The options appear again and are filtered.
    await tester.enterText(find.byType(TextFormField), 'e');
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsOneWidget);
    list = find.byType(ListView).evaluate().first.widget as ListView;
    // 'chameleon', 'elephant', 'goose', 'lemur', 'mouse', and
    // 'northern white rhinoceros' are displayed.
    expect(list.semanticChildCount, 6);
  });

  testWidgets('can filter and select a list of custom User options', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<User>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptionsUsers.where((User option) {
                return option.toString().contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);

    // Focus the empty field. All the options are displayed.
    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    ListView list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, kOptionsUsers.length);

    // Enter text. The options are filtered by the text.
    await tester.enterText(find.byType(TextFormField), 'example');
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsOneWidget);
    list = find.byType(ListView).evaluate().first.widget as ListView;
    // 'Alice' and 'Bob' are displayed because they have "example.com" emails.
    expect(list.semanticChildCount, 2);

    // Select a option. The options hide and the field updates to show the
    // selection.
    await tester.tap(find.byType(InkWell).first);
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);
    final TextFormField field = find.byType(TextFormField).evaluate().first.widget as TextFormField;
    expect(field.controller!.text, 'Alice, alice@example.com');

    // Modify the field text. The options appear again and are filtered.
    await tester.enterText(find.byType(TextFormField), 'B');
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsOneWidget);
    list = find.byType(ListView).evaluate().first.widget as ListView;
    // 'Bob' is displayed.
    expect(list.semanticChildCount, 1);
  });

  testWidgets('displayStringForOption is displayed in the options', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<User>(
            displayStringForOption: (User option) {
              return option.name;
            },
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptionsUsers.where((User option) {
                return option.toString().contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);

    // Focus the empty field. All the options are displayed, and the string that
    // is used comes from displayStringForOption.
    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    final ListView list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, kOptionsUsers.length);
    for (int i = 0; i < kOptionsUsers.length; i++) {
      expect(find.text(kOptionsUsers[i].name), findsOneWidget);
    }

    // Select a option. The options hide and the field updates to show the
    // selection. The text in the field is given by displayStringForOption.
    await tester.tap(find.byType(InkWell).first);
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);
    final TextFormField field = find.byType(TextFormField).evaluate().first.widget as TextFormField;
    expect(field.controller!.text, kOptionsUsers.first.name);
  });

  testWidgets('can build a custom field', (WidgetTester tester) async {
    final GlobalKey fieldKey = GlobalKey();
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
            fieldViewBuilder: (BuildContext context, TextEditingController textEditingController, FocusNode focusNode, VoidCallback onFieldSubmitted) {
              return Container(key: fieldKey);
            },
          ),
        ),
      ),
    );

    // The custom field is rendered and not the default TextFormField.
    expect(find.byKey(fieldKey), findsOneWidget);
    expect(find.byType(TextFormField), findsNothing);
  });

  testWidgets('can build custom options', (WidgetTester tester) async {
    final GlobalKey optionsKey = GlobalKey();
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
            optionsViewBuilder: (BuildContext context, AutocompleteOnSelected<String> onSelected, Iterable<String> options) {
              return Container(key: optionsKey);
            },
          ),
        ),
      ),
    );

    // The default field is rendered but not the options, yet.
    expect(find.byKey(optionsKey), findsNothing);
    expect(find.byType(TextFormField), findsOneWidget);

    // Focus the empty field. The custom options is displayed.
    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byKey(optionsKey), findsOneWidget);
  });

  testWidgets('the default Autocomplete options widget has a maximum height of 200', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(home: Scaffold(
      body: Autocomplete<String>(
        optionsBuilder: (TextEditingValue textEditingValue) {
          return kOptions.where((String option) {
            return option.contains(textEditingValue.text.toLowerCase());
          });
        },
      ),
    )));

    final Finder listFinder = find.byType(ListView);
    final Finder inputFinder = find.byType(TextFormField);
    await tester.tap(inputFinder);
    await tester.enterText(inputFinder, '');
    await tester.pump();
    final Size baseSize = tester.getSize(listFinder);
    final double resultingHeight = baseSize.height;
    expect(resultingHeight, equals(200));
  });

  testWidgets('the options height restricts to max desired height', (WidgetTester tester) async {
    const double desiredHeight = 150.0;
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
      body: Autocomplete<String>(
        optionsMaxHeight: desiredHeight,
        optionsBuilder: (TextEditingValue textEditingValue) {
          return kOptions.where((String option) {
            return option.contains(textEditingValue.text.toLowerCase());
          });
        },
      ),
    )));

    /// entering "a" returns 9 items from kOptions so basically the
    /// height of 9 options would be beyond `desiredHeight=150`,
    /// so height gets restricted to desiredHeight.
    final Finder listFinder = find.byType(ListView);
    final Finder inputFinder = find.byType(TextFormField);
    await tester.tap(inputFinder);
    await tester.enterText(inputFinder, 'a');
    await tester.pump();
    final Size baseSize = tester.getSize(listFinder);
    final double resultingHeight = baseSize.height;

    /// expected desired Height =150.0
    expect(resultingHeight, equals(desiredHeight));
  });

  testWidgets('The height of options shrinks to height of resulting items, if less than maxHeight', (WidgetTester tester) async {
    // Returns a Future with the height of the default [Autocomplete] options widget
    // after the provided text had been entered into the [Autocomplete] field.
    Future<double> _getDefaultOptionsHeight(
        WidgetTester tester, String enteredText) async {
      final Finder listFinder = find.byType(ListView);
      final Finder inputFinder = find.byType(TextFormField);
      final TextFormField field = inputFinder.evaluate().first.widget as TextFormField;
      field.controller!.clear();
      await tester.tap(inputFinder);
      await tester.enterText(inputFinder, enteredText);
      await tester.pump();
      final Size baseSize = tester.getSize(listFinder);
      return baseSize.height;
    }

    const double maxOptionsHeight = 250.0;
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
      body: Autocomplete<String>(
        optionsMaxHeight: maxOptionsHeight,
        optionsBuilder: (TextEditingValue textEditingValue) {
          return kOptions.where((String option) {
            return option.contains(textEditingValue.text.toLowerCase());
          });
        },
      ),
    )));

    final Finder listFinder = find.byType(ListView);
    expect(listFinder, findsNothing);

    // Entering `a` returns 9 items(height > `maxOptionsHeight`) from the kOptions
    // so height gets restricted to `maxOptionsHeight =250`.
    final double nineItemsHeight = await _getDefaultOptionsHeight(tester, 'a');
    expect(nineItemsHeight, equals(maxOptionsHeight));

    // Returns 2 Items (height < `maxOptionsHeight`)
    // so options height shrinks to 2 Items combined height.
    final double twoItemsHeight = await _getDefaultOptionsHeight(tester, 'el');
    expect(twoItemsHeight, lessThan(maxOptionsHeight));

    // Returns 1 item (height < `maxOptionsHeight`) from `kOptions`
    // so options height shrinks to 1 items height.
    final double oneItemsHeight = await _getDefaultOptionsHeight(tester, 'elep');
    expect(oneItemsHeight, lessThan(twoItemsHeight));
  });

  testWidgets('initialValue sets initial text field value', (WidgetTester tester) async {
    late String lastSelection;
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Autocomplete<String>(
            initialValue: const TextEditingValue(text: 'lem'),
            onSelected: (String selection) {
              lastSelection = selection;
            },
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    // The field is always rendered, but the options are not unless needed.
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);
    expect(
      tester.widget<TextFormField>(find.byType(TextFormField)).controller!.text,
      'lem',
    );

    // Focus the empty field. All the options are displayed.
    await tester.tap(find.byType(TextFormField));
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    final ListView list = find.byType(ListView).evaluate().first.widget as ListView;
    // Displays just one option ('lemur').
    expect(list.semanticChildCount, 1);

    // Select a option. The options hide and the field updates to show the
    // selection.
    await tester.tap(find.byType(InkWell).first);
    await tester.pump();
    expect(find.byType(TextFormField), findsOneWidget);
    expect(find.byType(ListView), findsNothing);
    final TextFormField field = find.byType(TextFormField).evaluate().first.widget as TextFormField;
    expect(field.controller!.text, 'lemur');
    expect(lastSelection, 'lemur');
  });

  // Ensures that the option with the given label has a given background color
  // if given, or no background if color is null.
  void checkOptionHighlight(WidgetTester tester, String label, Color? color) {
    final RenderBox renderBox = tester.renderObject<RenderBox>(find.ancestor(matching: find.byType(Container), of: find.text(label)));
    if (color != null) {
      // Check to see that the container is painted with the highlighted background color.
      expect(renderBox, paints..rect(color: color));
    } else {
      // There should only be a paragraph painted.
      expect(renderBox, paintsExactlyCountTimes(const Symbol('drawRect'), 0));
      expect(renderBox, paints..paragraph());
    }
  }

  testWidgets('keyboard navigation of the options properly highlights the option', (WidgetTester tester) async {
    const Color highlightColor = Color(0xFF112233);
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData.light().copyWith(
          focusColor: highlightColor,
        ),
        home: Scaffold(
          body: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    await tester.tap(find.byType(TextFormField));
    await tester.enterText(find.byType(TextFormField), 'el');
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    final ListView list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, 2);

    // Initially the first option should be highlighted
    checkOptionHighlight(tester, 'chameleon', highlightColor);
    checkOptionHighlight(tester, 'elephant', null);

    // Move the selection down
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();

    // Highlight should be moved to the second item
    checkOptionHighlight(tester, 'chameleon', null);
    checkOptionHighlight(tester, 'elephant', highlightColor);
  });

  testWidgets('keyboard navigation keeps the highlighted option scrolled into view', (WidgetTester tester) async {
    const Color highlightColor = Color(0xFF112233);
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData.light().copyWith(
          focusColor: highlightColor,
        ),
        home: Scaffold(
          body: Autocomplete<String>(
            optionsBuilder: (TextEditingValue textEditingValue) {
              return kOptions.where((String option) {
                return option.contains(textEditingValue.text.toLowerCase());
              });
            },
          ),
        ),
      ),
    );

    await tester.tap(find.byType(TextFormField));
    await tester.enterText(find.byType(TextFormField), 'e');
    await tester.pump();
    expect(find.byType(ListView), findsOneWidget);
    final ListView list = find.byType(ListView).evaluate().first.widget as ListView;
    expect(list.semanticChildCount, 6);

    // Highlighted item should be at the top
    expect(tester.getTopLeft(find.text('chameleon')).dy, equals(64.0));
    checkOptionHighlight(tester, 'chameleon', highlightColor);

    // Move down the list of options
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();
    await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
    await tester.pump();

    // First item should have scrolled off the top, and not be selected.
    expect(find.text('chameleon'), findsNothing);

    // Highlighted item 'lemur' should be centered in the options popup
    expect(tester.getTopLeft(find.text('mouse')).dy, equals(187.0));
    checkOptionHighlight(tester, 'mouse', highlightColor);

    // The other items on screen should not be selected.
    checkOptionHighlight(tester, 'goose', null);
    checkOptionHighlight(tester, 'lemur', null);
    checkOptionHighlight(tester, 'northern white rhinoceros', null);
  });
}
