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

import 'package:fake_async/fake_async.dart';
import 'package:flutter/services.dart';

/// A function which takes the name of the method channel, it's handler,
/// platform message and asynchronously returns an encoded response.
typedef AllMessagesHandler = Future<ByteData?>? Function(
    String channel, MessageHandler? handler, ByteData? message);

/// A [BinaryMessenger] subclass that is used as the default binary messenger
/// under testing environment.
///
/// It tracks status of data sent across the Flutter platform barrier, which is
/// useful for testing frameworks to monitor and synchronize against the
/// platform messages.
///
/// ## Messages from the framework to the platform
///
/// Messages are sent from the framework to the platform via the
/// [send] method.
///
/// To intercept a message sent from the framework to the platform,
/// consider using [setMockMessageHandler],
/// [setMockDecodedMessageHandler], and [setMockMethodCallHandler]
/// (see also [checkMockMessageHandler]).
///
/// To wait for all pending framework-to-platform messages, the
/// [platformMessagesFinished] getter provides an appropriate
/// [Future]. The [pendingMessageCount] getter returns the current
/// number of outstanding messages.
///
/// ## Messages from the platform to the framework
///
/// The platform sends messages via the [ChannelBuffers] API. Mock
/// messages can be sent to the framework using
/// [handlePlatformMessage].
///
/// Listeners for these messages are configured using [setMessageHandler].
class TestDefaultBinaryMessenger extends BinaryMessenger {
  /// Creates a [TestDefaultBinaryMessenger] instance.
  ///
  /// The [delegate] instance must not be null.
  TestDefaultBinaryMessenger(this.delegate): assert(delegate != null);

  /// The delegate [BinaryMessenger].
  final BinaryMessenger delegate;

  // The handlers for messages from the engine (including fake
  // messages sent by handlePlatformMessage).
  final Map<String, MessageHandler> _inboundHandlers = <String, MessageHandler>{};

  /// Send a mock message to the framework as if it came from the platform.
  ///
  /// If a listener has been set using [setMessageHandler], that listener is
  /// invoked to handle the message, and this method returns a future that
  /// completes with that handler's result.
  ///
  /// {@template flutter.flutter_test.TestDefaultBinaryMessenger.handlePlatformMessage.asyncHandlers}
  /// It is strongly recommended that all handlers used with this API be
  /// synchronous (not requiring any microtasks to complete), because
  /// [testWidgets] tests run in a [FakeAsync] zone in which microtasks do not
  /// progress except when time is explicitly advanced (e.g. with
  /// [WidgetTester.pump]), which means that `await`ing a [Future] will result
  /// in the test hanging.
  /// {@endtemplate}
  ///
  /// If no listener is configured, this method returns right away with null.
  ///
  /// The `callback` argument, if non-null, will be called just before this
  /// method's future completes, either with the result of the listener
  /// registered with [setMessageHandler], or with null if no listener has
  /// been registered.
  ///
  /// Messages can also be sent via [ChannelBuffers.push] (see
  /// [ServicesBinding.channelBuffers]); the effect is the same, though that API
  /// will not wait for a response.
  // TODO(ianh): When the superclass `handlePlatformMessage` is removed,
  // remove this @override (but leave the method).
  @override
  Future<ByteData?> handlePlatformMessage(
    String channel,
    ByteData? data,
    ui.PlatformMessageResponseCallback? callback,
  ) {
    Future<ByteData?>? result;
    if (_inboundHandlers.containsKey(channel))
      result = _inboundHandlers[channel]!(data);
    result ??= Future<ByteData?>.value();
    if (callback != null)
      result = result.then((ByteData? result) { callback(result); return result; });
    return result;
  }

  @override
  void setMessageHandler(String channel, MessageHandler? handler) {
    if (handler == null) {
      _inboundHandlers.remove(channel);
      delegate.setMessageHandler(channel, null);
    } else {
      _inboundHandlers[channel] = handler; // used to handle fake messages sent via handlePlatformMessage
      delegate.setMessageHandler(channel, handler); // used to handle real messages from the engine
    }
  }

  final List<Future<ByteData?>> _pendingMessages = <Future<ByteData?>>[];

  /// The number of incomplete/pending calls sent to the platform channels.
  int get pendingMessageCount => _pendingMessages.length;

  // Handlers that intercept and respond to outgoing messages,
  // pretending to be the platform.
  final Map<String, MessageHandler> _outboundHandlers = <String, MessageHandler>{};

  // The outbound callbacks that were actually registered, so that we
  // can implement the [checkMockMessageHandler] method.
  final Map<String, Object> _outboundHandlerIdentities = <String, Object>{};

  /// Handler that intercepts and responds to outgoing messages, pretending
  /// to be the platform, for all channels.
  AllMessagesHandler? allMessagesHandler;

  @override
  Future<ByteData?>? send(String channel, ByteData? message) {
    final Future<ByteData?>? resultFuture;
    final MessageHandler? handler = _outboundHandlers[channel];
    if (allMessagesHandler != null) {
      resultFuture = allMessagesHandler!(channel, handler, message);
    } else if (handler != null) {
      resultFuture = handler(message);
    } else {
      resultFuture = delegate.send(channel, message);
    }
    if (resultFuture != null) {
      _pendingMessages.add(resultFuture);
      resultFuture
        .catchError((Object error) { /* errors are the responsibility of the caller */ })
        .whenComplete(() => _pendingMessages.remove(resultFuture));
    }
    return resultFuture;
  }

  /// Returns a Future that completes after all the platform calls are finished.
  ///
  /// If a new platform message is sent after this method is called, this new
  /// message is not tracked. Use with [pendingMessageCount] to guarantee no
  /// pending message calls.
  Future<void> get platformMessagesFinished {
    return Future.wait<void>(_pendingMessages);
  }

  /// Set a callback for intercepting messages sent to the platform on
  /// the given channel, without decoding them.
  ///
  /// Intercepted messages are not forwarded to the platform.
  ///
  /// The given callback will replace the currently registered
  /// callback for that channel, if any. To stop intercepting messages
  /// at all, pass null as the handler.
  ///
  /// The handler's return value, if non-null, is used as a response,
  /// unencoded.
  ///
  /// {@macro flutter.flutter_test.TestDefaultBinaryMessenger.handlePlatformMessage.asyncHandlers}
  ///
  /// The `identity` argument, if non-null, is used to identify the
  /// callback when checked by [checkMockMessageHandler]. If null, the
  /// `handler` is used instead. (This allows closures to be passed as
  /// the `handler` with an alias used as the `identity` so that a
  /// reference to the closure need not be used. In practice, this is
  /// used by [setMockDecodedMessageHandler] and
  /// [setMockMethodCallHandler] to allow [checkMockMessageHandler] to
  /// recognize the closures that were passed to those methods even
  /// though those methods wrap those closures when passing them to
  /// this method.)
  ///
  /// Registered callbacks are cleared after each test.
  ///
  /// See also:
  ///
  ///  * [checkMockMessageHandler], which can verify if a handler is still
  ///    registered, which is useful in tests to ensure that no unexpected
  ///    handlers are being registered.
  ///
  ///  * [setMockDecodedMessageHandler], which wraps this method but
  ///    decodes the messages using a [MessageCodec].
  ///
  ///  * [setMockMethodCallHandler], which wraps this method but decodes
  ///    the messages using a [MethodCodec].
  void setMockMessageHandler(String channel, MessageHandler? handler, [ Object? identity ]) {
    if (handler == null) {
      _outboundHandlers.remove(channel);
      _outboundHandlerIdentities.remove(channel);
    } else {
      identity ??= handler;
      _outboundHandlers[channel] = handler;
      _outboundHandlerIdentities[channel] = identity;
    }
  }

  /// Set a callback for intercepting messages sent to the platform on
  /// the given channel.
  ///
  /// Intercepted messages are not forwarded to the platform.
  ///
  /// The given callback will replace the currently registered
  /// callback for that channel, if any. To stop intercepting messages
  /// at all, pass null as the handler.
  ///
  /// Messages are decoded using the codec of the channel.
  ///
  /// The handler's return value, if non-null, is used as a response,
  /// after encoding it using the channel's codec.
  ///
  /// {@macro flutter.flutter_test.TestDefaultBinaryMessenger.handlePlatformMessage.asyncHandlers}
  ///
  /// Registered callbacks are cleared after each test.
  ///
  /// See also:
  ///
  ///  * [checkMockMessageHandler], which can verify if a handler is still
  ///    registered, which is useful in tests to ensure that no unexpected
  ///    handlers are being registered.
  ///
  ///  * [setMockMessageHandler], which is similar but provides raw
  ///    access to the underlying bytes.
  ///
  ///  * [setMockMethodCallHandler], which is similar but decodes
  ///    the messages using a [MethodCodec].
  void setMockDecodedMessageHandler<T>(BasicMessageChannel<T> channel, Future<T> Function(T? message)? handler) {
    if (handler == null) {
      setMockMessageHandler(channel.name, null);
      return;
    }
    setMockMessageHandler(channel.name, (ByteData? message) async {
      return channel.codec.encodeMessage(await handler(channel.codec.decodeMessage(message)));
    }, handler);
  }

  /// Set a callback for intercepting method calls sent to the
  /// platform on the given channel.
  ///
  /// Intercepted method calls are not forwarded to the platform.
  ///
  /// The given callback will replace the currently registered
  /// callback for that channel, if any. To stop intercepting messages
  /// at all, pass null as the handler.
  ///
  /// Methods are decoded using the codec of the channel.
  ///
  /// The handler's return value, if non-null, is used as a response,
  /// after re-encoding it using the channel's codec.
  ///
  /// To send an error, throw a [PlatformException] in the handler.
  /// Other exceptions are not caught.
  ///
  /// {@macro flutter.flutter_test.TestDefaultBinaryMessenger.handlePlatformMessage.asyncHandlers}
  ///
  /// Registered callbacks are cleared after each test.
  ///
  /// See also:
  ///
  ///  * [checkMockMessageHandler], which can verify if a handler is still
  ///    registered, which is useful in tests to ensure that no unexpected
  ///    handlers are being registered.
  ///
  ///  * [setMockMessageHandler], which is similar but provides raw
  ///    access to the underlying bytes.
  ///
  ///  * [setMockDecodedMessageHandler], which is similar but decodes
  ///    the messages using a [MessageCodec].
  void setMockMethodCallHandler(MethodChannel channel, Future<Object?>? Function(MethodCall message)? handler) {
    if (handler == null) {
      setMockMessageHandler(channel.name, null);
      return;
    }
    setMockMessageHandler(channel.name, (ByteData? message) async {
      final MethodCall call = channel.codec.decodeMethodCall(message);
      try {
        return channel.codec.encodeSuccessEnvelope(await handler(call));
      } on PlatformException catch (error) {
        return channel.codec.encodeErrorEnvelope(
          code: error.code,
          message: error.message,
          details: error.details,
        );
      } on MissingPluginException {
        return null;
      } catch (error) {
        return channel.codec.encodeErrorEnvelope(code: 'error', message: '$error');
      }
    }, handler);
  }

  /// Returns true if the `handler` argument matches the `handler`
  /// previously passed to [setMockMessageHandler],
  /// [setMockDecodedMessageHandler], or [setMockMethodCallHandler].
  ///
  /// Specifically, it compares the argument provided to the `identity`
  /// argument provided to [setMockMessageHandler], defaulting to the
  /// `handler` argument passed to that method is `identity` was null.
  ///
  /// This method is useful for tests or test harnesses that want to assert the
  /// mock handler for the specified channel has not been altered by a previous
  /// test.
  ///
  /// Passing null for the `handler` returns true if the handler for the
  /// `channel` is not set.
  ///
  /// Registered callbacks are cleared after each test.
  bool checkMockMessageHandler(String channel, Object? handler) => _outboundHandlerIdentities[channel] == handler;
}
