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

import 'platform_channel.dart';

export 'dart:typed_data' show ByteData;

/// A message encoding/decoding mechanism.
///
/// Both operations throw an exception, if conversion fails. Such situations
/// should be treated as programming errors.
///
/// See also:
///
///  * [BasicMessageChannel], which use [MessageCodec]s for communication
///    between Flutter and platform plugins.
abstract class MessageCodec<T> {
  /// Encodes the specified [message] in binary.
  ///
  /// Returns null if the message is null.
  ByteData? encodeMessage(T message);

  /// Decodes the specified [message] from binary.
  ///
  /// Returns null if the message is null.
  T? decodeMessage(ByteData? message);
}

/// An command object representing the invocation of a named method.
@immutable
class MethodCall {
  /// Creates a [MethodCall] representing the invocation of [method] with the
  /// specified [arguments].
  const MethodCall(this.method, [this.arguments])
    : assert(method != null);

  /// The name of the method to be called.
  final String method;

  /// The arguments for the method.
  ///
  /// Must be a valid value for the [MethodCodec] used.
  ///
  /// This property is `dynamic`, which means type-checking is skipped when accessing
  /// this property. To minimize the risk of type errors at runtime, the value should
  /// be cast to `Object?` when accessed.
  final dynamic arguments;

  @override
  String toString() => '${objectRuntimeType(this, 'MethodCall')}($method, $arguments)';
}

/// A codec for method calls and enveloped results.
///
/// All operations throw an exception, if conversion fails.
///
/// See also:
///
///  * [MethodChannel], which use [MethodCodec]s for communication
///    between Flutter and platform plugins.
///  * [EventChannel], which use [MethodCodec]s for communication
///    between Flutter and platform plugins.
abstract class MethodCodec {
  /// Encodes the specified [methodCall] into binary.
  ByteData encodeMethodCall(MethodCall methodCall);

  /// Decodes the specified [methodCall] from binary.
  MethodCall decodeMethodCall(ByteData? methodCall);

  /// Decodes the specified result [envelope] from binary.
  ///
  /// Throws [PlatformException], if [envelope] represents an error, otherwise
  /// returns the enveloped result.
  ///
  /// The type returned from [decodeEnvelope] is `dynamic` (not `Object?`),
  /// which means *no type checking is performed on its return value*. It is
  /// strongly recommended that the return value be immediately cast to a known
  /// type to prevent runtime errors due to typos that the type checker could
  /// otherwise catch.
  dynamic decodeEnvelope(ByteData envelope);

  /// Encodes a successful [result] into a binary envelope.
  ByteData encodeSuccessEnvelope(Object? result);

  /// Encodes an error result into a binary envelope.
  ///
  /// The specified error [code], human-readable error [message] and error
  /// [details] correspond to the fields of [PlatformException].
  ByteData encodeErrorEnvelope({ required String code, String? message, Object? details});
}

/// Thrown to indicate that a platform interaction failed in the platform
/// plugin.
///
/// See also:
///
///  * [MethodCodec], which throws a [PlatformException], if a received result
///    envelope represents an error.
///  * [MethodChannel.invokeMethod], which completes the returned future
///    with a [PlatformException], if invoking the platform plugin method
///    results in an error envelope.
///  * [EventChannel.receiveBroadcastStream], which emits
///    [PlatformException]s as error events, whenever an event received from the
///    platform plugin is wrapped in an error envelope.
class PlatformException implements Exception {
  /// Creates a [PlatformException] with the specified error [code] and optional
  /// [message], and with the optional error [details] which must be a valid
  /// value for the [MethodCodec] involved in the interaction.
  PlatformException({
    required this.code,
    this.message,
    this.details,
    this.stacktrace,
  }) : assert(code != null);

  /// An error code.
  final String code;

  /// A human-readable error message, possibly null.
  final String? message;

  /// Error details, possibly null.
  ///
  /// This property is `dynamic`, which means type-checking is skipped when accessing
  /// this property. To minimize the risk of type errors at runtime, the value should
  /// be cast to `Object?` when accessed.
  final dynamic details;

  /// Native stacktrace for the error, possibly null.
  ///
  /// This contains the native platform stack trace, not the Dart stack trace.
  ///
  /// The stack trace for Dart exceptions can be obtained using try-catch blocks, for example:
  ///
  /// ```dart
  /// try {
  ///   // ...
  /// } catch (e, stacktrace) {
  ///   print(stacktrace);
  /// }
  /// ```
  ///
  /// On Android this field is populated when a `RuntimeException` or a subclass of it is thrown in the method call handler,
  /// as shown in the following example:
  ///
  /// ```kotlin
  /// import androidx.annotation.NonNull
  /// import io.flutter.embedding.android.FlutterActivity
  /// import io.flutter.embedding.engine.FlutterEngine
  /// import io.flutter.plugin.common.MethodChannel
  ///
  /// class MainActivity: FlutterActivity() {
  ///   private val CHANNEL = "channel_name"
  ///
  ///   override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
  ///     super.configureFlutterEngine(flutterEngine)
  ///     MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
  ///       call, result -> throw RuntimeException("Oh no")
  ///     }
  ///   }
  /// }
  /// ```
  ///
  /// It is also populated on Android if the method channel result is not serializable.
  /// If the result is not serializable, an exception gets thrown during the serialization process.
  /// This can be seen in the following example:
  ///
  /// ```kotlin
  /// import androidx.annotation.NonNull
  /// import io.flutter.embedding.android.FlutterActivity
  /// import io.flutter.embedding.engine.FlutterEngine
  /// import io.flutter.plugin.common.MethodChannel
  ///
  /// class MainActivity: FlutterActivity() {
  ///   private val CHANNEL = "channel_name"
  ///
  ///   override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
  ///     super.configureFlutterEngine(flutterEngine)
  ///     MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
  ///       call, result -> result.success(Object())
  ///     }
  ///   }
  /// }
  /// ```
  ///
  /// In the cases described above, the content of [stacktrace] will be the unprocessed output of calling `toString()` on the exception.
  final String? stacktrace;

  @override
  String toString() => 'PlatformException($code, $message, $details, $stacktrace)';
}

/// Thrown to indicate that a platform interaction failed to find a handling
/// plugin.
///
/// See also:
///
///  * [MethodChannel.invokeMethod], which completes the returned future
///    with a [MissingPluginException], if no plugin handler for the method call
///    was found.
///  * [OptionalMethodChannel.invokeMethod], which completes the returned future
///    with null, if no plugin handler for the method call was found.
class MissingPluginException implements Exception {
  /// Creates a [MissingPluginException] with an optional human-readable
  /// error message.
  MissingPluginException([this.message]);

  /// A human-readable error message, possibly null.
  final String? message;

  @override
  String toString() => 'MissingPluginException($message)';
}
