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

// Vertical position at which to anchor the toolbar for testing.
const double _kAnchor = 200;
// Amount for toolbar to overlap bottom padding for testing.
const double _kTestToolbarOverlap = 10;

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  /// Builds test button items for each of the suggestions provided.
  List<ContextMenuButtonItem> buildSuggestionButtons(List<String> suggestions) {
    return <ContextMenuButtonItem>[
      for (final String suggestion in suggestions)
        ContextMenuButtonItem(onPressed: () {}, label: suggestion),
      ContextMenuButtonItem(
        onPressed: () {},
        type: ContextMenuButtonType.delete,
        label: 'DELETE',
      ),
    ];
  }

  /// Finds the container of the [SpellCheckSuggestionsToolbar] so that
  /// the position of the toolbar itself may be determined.
  Finder findSpellCheckSuggestionsToolbar() {
    return find.descendant(
      of: find.byType(MaterialApp),
      matching: find.byWidgetPredicate(
        (Widget w) => '${w.runtimeType}' == '_SpellCheckSuggestionsToolbarContainer'),
    );
  }

  testWidgets('positions toolbar below anchor when it fits above bottom view padding', (WidgetTester tester) async {
    // We expect the toolbar to be positioned right below the anchor with padding accounted for.
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: SpellCheckSuggestionsToolbar(
            anchor: const Offset(0.0, _kAnchor),
            buttonItems: buildSuggestionButtons(<String>['hello', 'yellow', 'yell']),
          ),
        ),
      ),
    );

    final double toolbarY = tester.getTopLeft(findSpellCheckSuggestionsToolbar()).dy;
    expect(toolbarY, equals(_kAnchor));
  });

  testWidgets('re-positions toolbar higher below anchor when it does not fit above bottom view padding', (WidgetTester tester) async {
    // We expect the toolbar to be positioned _kTestToolbarOverlap pixels above the anchor.
    const double expectedToolbarY = _kAnchor - _kTestToolbarOverlap;

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: SpellCheckSuggestionsToolbar(
            anchor: const Offset(0.0, _kAnchor - _kTestToolbarOverlap),
            buttonItems: buildSuggestionButtons(<String>['hello', 'yellow', 'yell']),
          ),
        ),
      ),
    );

    final double toolbarY = tester.getTopLeft(findSpellCheckSuggestionsToolbar()).dy;
    expect(toolbarY, equals(expectedToolbarY));
  });

  testWidgets('more than three suggestions throws an error', (WidgetTester tester) async {
    Future<void> pumpToolbar(List<String> suggestions) async {
      await tester.pumpWidget(
        MaterialApp(
          home: Scaffold(
            body: SpellCheckSuggestionsToolbar(
              anchor: const Offset(0.0, _kAnchor - _kTestToolbarOverlap),
              buttonItems: buildSuggestionButtons(suggestions),
            ),
          ),
        ),
      );
    }
    await pumpToolbar(<String>['hello', 'yellow', 'yell']);
    expect(() async {
      await pumpToolbar(<String>['hello', 'yellow', 'yell', 'yeller']);
    }, throwsAssertionError);
  },
    skip: kIsWeb, // [intended]
  );

  test('buildSuggestionButtons only considers the first three suggestions', () {
    final _FakeEditableTextState editableTextState = _FakeEditableTextState(
      suggestions: <String>[
        'hello',
        'yellow',
        'yell',
        'yeller',
      ],
    );
    final List<ContextMenuButtonItem>? buttonItems =
        SpellCheckSuggestionsToolbar.buildButtonItems(editableTextState);
    expect(buttonItems, isNotNull);
    final Iterable<String?> labels = buttonItems!.map((ContextMenuButtonItem buttonItem) {
      return buttonItem.label;
    });
    expect(labels, hasLength(4));
    expect(labels, contains('hello'));
    expect(labels, contains('yellow'));
    expect(labels, contains('yell'));
    expect(labels, contains(null)); // For the delete button.
    expect(labels, isNot(contains('yeller')));
  });

  test('buildButtonItems builds only a delete button when no suggestions', () {
    final _FakeEditableTextState editableTextState = _FakeEditableTextState();
    final List<ContextMenuButtonItem>? buttonItems =
        SpellCheckSuggestionsToolbar.buildButtonItems(editableTextState);

    expect(buttonItems, hasLength(1));
    expect(buttonItems!.first.type, ContextMenuButtonType.delete);
  });
}

class _FakeEditableTextState extends EditableTextState {
  _FakeEditableTextState({
    this.suggestions,
  });

  final List<String>? suggestions;

  @override
  TextEditingValue get currentTextEditingValue => TextEditingValue.empty;

  @override
  SuggestionSpan? findSuggestionSpanAtCursorIndex(int cursorIndex) {
    return SuggestionSpan(
      const TextRange(
        start: 0,
        end: 0,
      ),
      suggestions ?? <String>[],
    );
  }
}
