// 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 'dart:ui';

import 'package:flutter/foundation.dart';
import 'system_channels.dart';

/// A data structure representing a range of misspelled text and the suggested
/// replacements for this range.
///
/// For example, one [SuggestionSpan] of the
/// [List<SuggestionSpan>] suggestions of the [SpellCheckResults] corresponding
/// to "Hello, wrold!" may be:
/// ```dart
/// SuggestionSpan suggestionSpan =
///   SuggestionSpan(
///     const TextRange(start: 7, end: 12),
///     List<String>.of(<String>['word', 'world', 'old']),
/// );
/// ```
@immutable
class SuggestionSpan {
  /// Creates a span representing a misspelled range of text and the replacements
  /// suggested by a spell checker.
  ///
  /// The [range] and replacement [suggestions] must all not
  /// be null.
  const SuggestionSpan(this.range, this.suggestions)
      : assert(range != null),
        assert(suggestions != null);

  /// The misspelled range of text.
  final TextRange range;

  /// The alternate suggestions for the misspelled range of text.
  final List<String> suggestions;

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }

    return other is SuggestionSpan &&
        other.range.start == range.start &&
        other.range.end == range.end &&
        listEquals<String>(other.suggestions, suggestions);
  }

  @override
  int get hashCode => Object.hash(range.start, range.end, Object.hashAll(suggestions));
}

/// A data structure grouping together the [SuggestionSpan]s and related text of
/// results returned by a spell checker.
@immutable
class SpellCheckResults {
  /// Creates results based off those received by spell checking some text input.
  const SpellCheckResults(this.spellCheckedText, this.suggestionSpans)
      : assert(spellCheckedText != null),
        assert(suggestionSpans != null);

  /// The text that the [suggestionSpans] correspond to.
  final String spellCheckedText;

  /// The spell check results of the [spellCheckedText].
  ///
  /// See also:
  ///
  ///  * [SuggestionSpan], the ranges of misspelled text and corresponding
  ///    replacement suggestions.
  final List<SuggestionSpan> suggestionSpans;

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
        return true;
    }

    return other is SpellCheckResults &&
        other.spellCheckedText == spellCheckedText &&
        listEquals<SuggestionSpan>(other.suggestionSpans, suggestionSpans);
  }

  @override
  int get hashCode => Object.hash(spellCheckedText, Object.hashAll(suggestionSpans));
}

/// Determines how spell check results are received for text input.
abstract class SpellCheckService {
  /// Facilitates a spell check request.
  ///
  /// Returns a [Future] that resolves with a [List] of [SuggestionSpan]s for
  /// all misspelled words in the given [String] for the given [Locale].
  Future<List<SuggestionSpan>?> fetchSpellCheckSuggestions(
    Locale locale, String text
  );
}

/// The service used by default to fetch spell check results for text input.
///
/// Any widget may use this service to spell check text by calling
/// `fetchSpellCheckSuggestions(locale, text)` with an instance of this class.
/// This is currently only supported by Android and iOS.
///
/// See also:
///
///  * [SpellCheckService], the service that this implements that may be
///    overridden for use by [EditableText].
///  * [EditableText], which may use this service to fetch results.
class DefaultSpellCheckService implements SpellCheckService {
  /// Creates service to spell check text input by default via communication
  /// over the spell check [MethodChannel].
  DefaultSpellCheckService() {
    spellCheckChannel = SystemChannels.spellCheck;
  }

  /// The last received results from the shell side.
  SpellCheckResults? lastSavedResults;

  /// The channel used to communicate with the shell side to complete spell
  /// check requests.
  late MethodChannel spellCheckChannel;

  /// Merges two lists of spell check [SuggestionSpan]s.
  ///
  /// Used in cases where the text has not changed, but the spell check results
  /// received from the shell side have. This case is caused by IMEs (GBoard,
  /// for instance) that ignore the composing region when spell checking text.
  ///
  /// Assumes that the lists provided as parameters are sorted by range start
  /// and that both list of [SuggestionSpan]s apply to the same text.
  static List<SuggestionSpan> mergeResults(
      List<SuggestionSpan> oldResults, List<SuggestionSpan> newResults) {
    final List<SuggestionSpan> mergedResults = <SuggestionSpan>[];

    SuggestionSpan oldSpan;
    SuggestionSpan newSpan;
    int oldSpanPointer = 0;
    int newSpanPointer = 0;

    while (oldSpanPointer < oldResults.length &&
        newSpanPointer < newResults.length) {
      oldSpan = oldResults[oldSpanPointer];
      newSpan = newResults[newSpanPointer];

      if (oldSpan.range.start == newSpan.range.start) {
        mergedResults.add(oldSpan);
        oldSpanPointer++;
        newSpanPointer++;
      } else {
        if (oldSpan.range.start < newSpan.range.start) {
          mergedResults.add(oldSpan);
          oldSpanPointer++;
        } else {
          mergedResults.add(newSpan);
          newSpanPointer++;
        }
      }
    }

    mergedResults.addAll(oldResults.sublist(oldSpanPointer));
    mergedResults.addAll(newResults.sublist(newSpanPointer));

    return mergedResults;
  }

  @override
  Future<List<SuggestionSpan>?> fetchSpellCheckSuggestions(
      Locale locale, String text) async {
    assert(locale != null);
    assert(text != null);

    final List<dynamic> rawResults;
    final String languageTag = locale.toLanguageTag();

    try {
      rawResults = await spellCheckChannel.invokeMethod(
        'SpellCheck.initiateSpellCheck',
        <String>[languageTag, text],
      ) as List<dynamic>;
    } catch (e) {
      // Spell check request canceled due to pending request.
      return null;
    }

    List<SuggestionSpan> suggestionSpans = <SuggestionSpan>[];

    for (final dynamic result in rawResults) {
      final Map<String, dynamic> resultMap =
        Map<String,dynamic>.from(result as Map<dynamic, dynamic>);
      suggestionSpans.add(
        SuggestionSpan(
          TextRange(
            start: resultMap['startIndex'] as int,
            end: resultMap['endIndex'] as int),
          (resultMap['suggestions'] as List<dynamic>).cast<String>(),
        )
      );
    }

    if (lastSavedResults != null) {
      // Merge current and previous spell check results if between requests,
      // the text has not changed but the spell check results have.
      final bool textHasNotChanged = lastSavedResults!.spellCheckedText == text;
      final bool spansHaveChanged =
          listEquals(lastSavedResults!.suggestionSpans, suggestionSpans);

      if (textHasNotChanged && spansHaveChanged) {
        suggestionSpans = mergeResults(lastSavedResults!.suggestionSpans, suggestionSpans);
      }
    }
    lastSavedResults = SpellCheckResults(text, suggestionSpans);

    return suggestionSpans;
  }
}
