// 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/services.dart';

import 'binding.dart';

// TODO(ianh): Once https://github.com/dart-lang/dartdoc/issues/2033 is fixed, update the hyperlinks marked HYPERLINK below.
// TODO(ianh): Once cocoon and other customer_tests are migrated, deprecate these transitional APIs

/// Shim to support the obsolete [setMockMessageHandler] and
/// [checkMockMessageHandler] methods on [BinaryMessenger] in tests.
///
/// The implementations defer to [TestDefaultBinaryMessengerBinding.defaultBinaryMessenger].
///
/// Rather than calling [setMockMessageHandler] on the
/// `ServicesBinding.defaultBinaryMessenger`, use
/// `tester.binding.defaultBinaryMessenger.setMockMessageHandler` directly. This
/// more accurately represents the actual method invocation.
extension TestBinaryMessengerExtension on BinaryMessenger {
  /// Shim for `TestDefaultBinaryMessenger.setMockMessageHandler`.
  // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // TODO(ianh): deprecate this method: @NotYetDeprecated(
  //   'Use tester.binding.defaultBinaryMessenger.setMockMessageHandler or '
  //   'TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMessageHandler instead. '
  //   'This feature was deprecated after v2.1.0-10.0.pre.'
  // )
  void setMockMessageHandler(String channel, MessageHandler? handler) {
    TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMessageHandler(channel, handler);
  }

  /// Shim for `TestDefaultBinaryMessenger.checkMockMessageHandler`.
  // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // TODO(ianh): deprecate this method: @NotYetDeprecated(
  //   'Use tester.binding.defaultBinaryMessenger.checkMockMessageHandler or '
  //   'TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.checkMockMessageHandler instead.'
  //   'This feature was deprecated after v2.1.0-10.0.pre.'
  // )
  bool checkMockMessageHandler(String channel, Object? handler) {
    return TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(channel, handler);
  }
}

/// Shim to support the obsolete [setMockMessageHandler] and
/// [checkMockMessageHandler] methods on [BasicMessageChannel] in tests.
///
/// The implementations defer to [TestDefaultBinaryMessengerBinding.defaultBinaryMessenger].
///
/// Rather than calling [setMockMessageHandler] on the message channel, use
/// `tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler`
/// directly. This more accurately represents the actual method invocation.
extension TestBasicMessageChannelExtension<T> on BasicMessageChannel<T> {
  /// Shim for `TestDefaultBinaryMessenger.setMockDecodedMessageHandler`.
  // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // TODO(ianh): deprecate this method: @NotYetDeprecated(
  //   'Use tester.binding.defaultBinaryMessenger.setMockDecodedMessageHandler or '
  //   'TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockDecodedMessageHandler instead. '
  //   'This feature was deprecated after v2.1.0-10.0.pre.'
  // )
  void setMockMessageHandler(Future<T> Function(T? message)? handler) {
    TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockDecodedMessageHandler<T>(this, handler);
  }

  /// Shim for `TestDefaultBinaryMessenger.checkMockMessageHandler`.
  // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // TODO(ianh): deprecate this method: @NotYetDeprecated(
  //   'Use tester.binding.defaultBinaryMessenger.checkMockMessageHandler or '
  //   'TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.checkMockMessageHandler instead. '
  //   'For the first argument, pass channel.name. '
  //   'This feature was deprecated after v2.1.0-10.0.pre.'
  // )
  bool checkMockMessageHandler(Object? handler) {
    return TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(name, handler);
  }
}

/// Shim to support the obsolete [setMockMethodCallHandler] and
/// [checkMockMethodCallHandler] methods on [MethodChannel] in tests.
///
/// The implementations defer to [TestDefaultBinaryMessengerBinding.defaultBinaryMessenger].
///
/// Rather than calling [setMockMethodCallHandler] on the method channel, use
/// `tester.binding.defaultBinaryMessenger.setMockMethodCallHandler` directly.
/// This more accurately represents the actual method invocation.
extension TestMethodChannelExtension on MethodChannel {
  /// Shim for `TestDefaultBinaryMessenger.setMockMethodCallHandler`.
  // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // TODO(ianh): deprecate this method: @NotYetDeprecated(
  //   'Use tester.binding.defaultBinaryMessenger.setMockMethodCallHandler or '
  //   'TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler instead. '
  //   'This feature was deprecated after v2.1.0-10.0.pre.'
  // )
  void setMockMethodCallHandler(Future<dynamic>? Function(MethodCall call)? handler) {
    TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(this, handler);
  }

  /// Shim for `TestDefaultBinaryMessenger.checkMockMessageHandler`.
  // HYPERLINK ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // TODO(ianh): deprecate this method: @NotYetDeprecated(
  //   'Use tester.binding.defaultBinaryMessenger.checkMockMessageHandler or '
  //   'TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.checkMockMessageHandler instead. '
  //   'For the first argument, pass channel.name. '
  //   'This feature was deprecated after v2.1.0-10.0.pre.'
  // )
  bool checkMockMethodCallHandler(Object? handler) {
    return TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.checkMockMessageHandler(name, handler);
  }
}
