// 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:async';
import 'dart:typed_data';

import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/foundation.dart';

import 'widget_tester.dart';

export 'package:flutter/services.dart' show TextEditingValue, TextInputAction;

/// A testing stub for the system's onscreen keyboard.
///
/// Typical app tests will not need to use this class directly.
///
/// See also:
///
/// * [WidgetTester.enterText], which uses this class to simulate keyboard input.
/// * [WidgetTester.showKeyboard], which uses this class to simulate showing the
///   popup keyboard and initializing its text.
class TestTextInput {
  /// Create a fake keyboard backend.
  ///
  /// The [onCleared] argument may be set to be notified of when the keyboard
  /// is dismissed.
  TestTextInput({ this.onCleared });

  /// Called when the keyboard goes away.
  ///
  /// To use the methods on this API that send fake keyboard messages (such as
  /// [updateEditingValue], [enterText], or [receiveAction]), the keyboard must
  /// first be requested, e.g. using [WidgetTester.showKeyboard].
  final VoidCallback onCleared;

  /// The messenger which sends the bytes for this channel, not null.
  BinaryMessenger get _binaryMessenger => ServicesBinding.instance.defaultBinaryMessenger;

  /// Installs this object as a mock handler for [SystemChannels.textInput].
  void register() {
    SystemChannels.textInput.setMockMethodCallHandler(_handleTextInputCall);
    _isRegistered = true;
  }

  /// Removes this object as a mock handler for [SystemChannels.textInput].
  ///
  /// After calling this method, the channel will exchange messages with the
  /// Flutter engine. Use this with [FlutterDriver] tests that need to display
  /// on-screen keyboard provided by the operating system.
  void unregister() {
    SystemChannels.textInput.setMockMethodCallHandler(null);
    _isRegistered = false;
  }

  /// Log for method calls.
  ///
  /// For all registered channels, handled calls are added to the list. Can
  /// be cleaned using [clearLog].
  final List<MethodCall> log = <MethodCall>[];

  /// Whether this [TestTextInput] is registered with [SystemChannels.textInput].
  ///
  /// Use [register] and [unregister] methods to control this value.
  bool get isRegistered => _isRegistered;
  bool _isRegistered = false;

  /// Whether there are any active clients listening to text input.
  bool get hasAnyClients => _client > 0;

  int _client = 0;

  /// Arguments supplied to the TextInput.setClient method call.
  Map<String, dynamic> setClientArgs;

  /// The last set of arguments that [TextInputConnection.setEditingState] sent
  /// to the embedder.
  ///
  /// This is a map representation of a [TextEditingValue] object. For example,
  /// it will have a `text` entry whose value matches the most recent
  /// [TextEditingValue.text] that was sent to the embedder.
  Map<String, dynamic> editingState;

  Future<dynamic> _handleTextInputCall(MethodCall methodCall) async {
    log.add(methodCall);
    switch (methodCall.method) {
      case 'TextInput.setClient':
        _client = methodCall.arguments[0] as int;
        setClientArgs = methodCall.arguments[1] as Map<String, dynamic>;
        break;
      case 'TextInput.clearClient':
        _client = 0;
        _isVisible = false;
        if (onCleared != null)
          onCleared();
        break;
      case 'TextInput.setEditingState':
        editingState = methodCall.arguments as Map<String, dynamic>;
        break;
      case 'TextInput.show':
        _isVisible = true;
        break;
      case 'TextInput.hide':
        _isVisible = false;
        break;
    }
  }

  /// Whether the onscreen keyboard is visible to the user.
  bool get isVisible => _isVisible;
  bool _isVisible = false;

  /// Simulates the user changing the [TextEditingValue] to the given value.
  void updateEditingValue(TextEditingValue value) {
    // Not using the `expect` function because in the case of a FlutterDriver
    // test this code does not run in a package:test test zone.
    if (_client == 0)
      throw TestFailure('Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.');
    _binaryMessenger.handlePlatformMessage(
      SystemChannels.textInput.name,
      SystemChannels.textInput.codec.encodeMethodCall(
        MethodCall(
          'TextInputClient.updateEditingState',
          <dynamic>[_client, value.toJSON()],
        ),
      ),
      (ByteData data) { /* response from framework is discarded */ },
    );
  }

  /// Simulates the user closing the text input connection.
  ///
  /// For example:
  /// - User pressed the home button and sent the application to background.
  /// - User closed the virtual keyboard.
  void closeConnection() {
    // Not using the `expect` function because in the case of a FlutterDriver
    // test this code does not run in a package:test test zone.
    if (_client == 0)
      throw TestFailure('Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.');
    _binaryMessenger.handlePlatformMessage(
      SystemChannels.textInput.name,
      SystemChannels.textInput.codec.encodeMethodCall(
        MethodCall(
          'TextInputClient.onConnectionClosed',
           <dynamic>[_client,]
        ),
      ),
      (ByteData data) { /* response from framework is discarded */ },
    );
  }

  /// Simulates the user typing the given text.
  void enterText(String text) {
    updateEditingValue(TextEditingValue(
      text: text,
    ));
  }

  /// Simulates the user pressing one of the [TextInputAction] buttons.
  /// Does not check that the [TextInputAction] performed is an acceptable one
  /// based on the `inputAction` [setClientArgs].
  Future<void> receiveAction(TextInputAction action) async {
    return TestAsyncUtils.guard(() {
      // Not using the `expect` function because in the case of a FlutterDriver
      // test this code does not run in a package:test test zone.
      if (_client == 0) {
        throw TestFailure('Tried to use TestTextInput with no keyboard attached. You must use WidgetTester.showKeyboard() first.');
      }

      final Completer<void> completer = Completer<void>();

      _binaryMessenger.handlePlatformMessage(
        SystemChannels.textInput.name,
        SystemChannels.textInput.codec.encodeMethodCall(
          MethodCall(
            'TextInputClient.performAction',
            <dynamic>[_client, action.toString()],
          ),
        ),
        (ByteData data) {
          try {
            // Decoding throws a PlatformException if the data represents an
            // error, and that's all we care about here.
            SystemChannels.textInput.codec.decodeEnvelope(data);

            // No error was found. Complete without issue.
            completer.complete();
          } catch (error) {
            // An exception occurred as a result of receiveAction()'ing. Report
            // that error.
            completer.completeError(error);
          }
        },
      );

      return completer.future;
    });
  }

  /// Simulates the user hiding the onscreen keyboard.
  void hide() {
    _isVisible = false;
  }
}
