// 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 [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(null);
    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>{};

  @override
  Future<ByteData?>? send(String channel, ByteData? message) {
    final Future<ByteData?>? resultFuture;
    final MessageHandler? handler = _outboundHandlers[channel];
    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', details: null);
      }
    }, 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;
}
