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

/// A callback to use with [integrationDriver].
///
/// The callback receives the name of screenshot passed to `binding.takeScreenshot(<name>)`,
/// a PNG byte buffer representing the screenshot, and an optional `Map` of arguments.
///
/// The callback returns `true` if the test passes or `false` otherwise.
///
/// You can use this callback to store the bytes locally in a file or upload them to a service
/// that compares the image against a gold or baseline version.
///
/// The optional `Map` of arguments can be passed from the
/// `binding.takeScreenshot(<name>, <args>)` callsite in the integration test,
/// and then the arguments can be used in the `onScreenshot` handler that is defined by
/// the Flutter driver. This `Map` should only contain values that can be serialized
/// to JSON.
///
/// Since the function is executed on the host driving the test, you can access any environment
/// variable from it.
typedef ScreenshotCallback = Future<bool> Function(String name, List<int> image, [Map<String, Object?>? args]);

/// Classes shared between `integration_test.dart` and `flutter drive` based
/// adaptor (ex: `integration_test_driver.dart`).

/// An object sent from integration_test back to the Flutter Driver in response to
/// `request_data` command.
class Response {
  /// Constructor to use for positive response.
  Response.allTestsPassed({this.data})
      : _allTestsPassed = true,
        _failureDetails = null;

  /// Constructor for failure response.
  Response.someTestsFailed(this._failureDetails, {this.data})
      : _allTestsPassed = false;

  /// Constructor for failure response.
  Response.toolException({String? ex})
      : _allTestsPassed = false,
        _failureDetails = <Failure>[Failure('ToolException', ex)];

  /// Constructor for web driver commands response.
  Response.webDriverCommand({this.data})
      : _allTestsPassed = false,
        _failureDetails = null;

  final List<Failure>? _failureDetails;

  final bool _allTestsPassed;

  /// The extra information to be added along side the test result.
  Map<String, dynamic>? data;

  /// Whether the test ran successfully or not.
  bool get allTestsPassed => _allTestsPassed;

  /// If the result are failures get the formatted details.
  String get formattedFailureDetails =>
      _allTestsPassed ? '' : formatFailures(_failureDetails!);

  /// Failure details as a list.
  List<Failure>? get failureDetails => _failureDetails;

  /// Serializes this message to a JSON map.
  String toJson() => json.encode(<String, dynamic>{
        'result': allTestsPassed.toString(),
        'failureDetails': _failureDetailsAsString(),
        if (data != null) 'data': data,
      });

  /// Deserializes the result from JSON.
  static Response fromJson(String source) {
    final Map<String, dynamic> responseJson = json.decode(source) as Map<String, dynamic>;
    if ((responseJson['result'] as String?) == 'true') {
      return Response.allTestsPassed(data: responseJson['data'] as Map<String, dynamic>?);
    } else {
      return Response.someTestsFailed(
        _failureDetailsFromJson(responseJson['failureDetails'] as List<dynamic>),
        data: responseJson['data'] as Map<String, dynamic>?,
      );
    }
  }

  /// Method for formatting the test failures' details.
  String formatFailures(List<Failure> failureDetails) {
    if (failureDetails.isEmpty) {
      return '';
    }

    final StringBuffer sb = StringBuffer();
    int failureCount = 1;
    for (final Failure failure in failureDetails) {
      sb.writeln('Failure in method: ${failure.methodName}');
      sb.writeln(failure.details);
      sb.writeln('end of failure $failureCount\n\n');
      failureCount++;
    }
    return sb.toString();
  }

  /// Create a list of Strings from [_failureDetails].
  List<String> _failureDetailsAsString() {
    final List<String> list = <String>[];
    if (_failureDetails == null || _failureDetails!.isEmpty) {
      return list;
    }

    for (final Failure failure in _failureDetails!) {
      list.add(failure.toJson());
    }

    return list;
  }

  /// Creates a [Failure] list using a json response.
  static List<Failure> _failureDetailsFromJson(List<dynamic> list) {
    return list.map((dynamic s) {
      return Failure.fromJsonString(s as String);
    }).toList();
  }
}

/// Representing a failure includes the method name and the failure details.
class Failure {
  /// Constructor requiring all fields during initialization.
  Failure(this.methodName, this.details);

  /// The name of the test method which failed.
  final String methodName;

  /// The details of the failure such as stack trace.
  final String? details;

  /// Serializes the object to JSON.
  String toJson() {
    return json.encode(<String, String?>{
      'methodName': methodName,
      'details': details,
    });
  }

  @override
  String toString() => toJson();

  /// Decode a JSON string to create a Failure object.
  static Failure fromJsonString(String jsonString) {
    final Map<String, dynamic> failure = json.decode(jsonString) as Map<String, dynamic>;
    return Failure(failure['methodName'] as String, failure['details'] as String?);
  }
}

/// Message used to communicate between app side tests and driver tests.
///
/// Not all `integration_tests` use this message. They are only used when app
/// side tests are sending [WebDriverCommand]s to the driver side.
///
/// These messages are used for the handshake since they carry information on
/// the driver side test such as: status pending or tests failed.
class DriverTestMessage {
  /// When tests are failed on the driver side.
  DriverTestMessage.error()
      : _isSuccess = false,
        _isPending = false;

  /// When driver side is waiting on [WebDriverCommand]s to be sent from the
  /// app side.
  DriverTestMessage.pending()
      : _isSuccess = false,
        _isPending = true;

  /// When driver side successfully completed executing the [WebDriverCommand].
  DriverTestMessage.complete()
      : _isSuccess = true,
        _isPending = false;

  final bool _isSuccess;
  final bool _isPending;

  // /// Status of this message.
  // ///
  // /// The status will be use to notify `integration_test` of driver side's
  // /// state.
  // String get status => _status;

  /// Has the command completed successfully by the driver.
  bool get isSuccess => _isSuccess;

  /// Is the driver waiting for a command.
  bool get isPending => _isPending;

  /// Depending on the values of [isPending] and [isSuccess], returns a string
  /// to represent the [DriverTestMessage].
  ///
  /// Used as an alternative method to converting the object to json since
  /// [RequestData] is only accepting string as `message`.
  @override
  String toString() {
    if (isPending) {
      return 'pending';
    } else if (isSuccess) {
      return 'complete';
    } else {
      return 'error';
    }
  }

  /// Return a DriverTestMessage depending on `status`.
  static DriverTestMessage fromString(String status) {
    switch (status) {
      case 'error':
        return DriverTestMessage.error();
      case 'pending':
        return DriverTestMessage.pending();
      case 'complete':
        return DriverTestMessage.complete();
      default:
        throw StateError('This type of status does not exist: $status');
    }
  }
}

/// Types of different WebDriver commands that can be used in web integration
/// tests.
///
/// These commands are either commands that WebDriver can execute or used
/// for the communication between `integration_test` and the driver test.
enum WebDriverCommandType {
  /// Acknowledgement for the previously sent message.
  ack,

  /// No further WebDriver commands is requested by the app-side tests.
  noop,

  /// Asking WebDriver to take a screenshot of the Web page.
  screenshot,
}

/// Command for WebDriver to execute.
///
/// Only works on Web when tests are run via `flutter driver` command.
///
/// See: https://www.w3.org/TR/webdriver/
class WebDriverCommand {
  /// Constructor for [WebDriverCommandType.noop] command.
  WebDriverCommand.noop()
      : type = WebDriverCommandType.noop,
        values = <String, dynamic>{};

  /// Constructor for [WebDriverCommandType.noop] screenshot.
  WebDriverCommand.screenshot(String screenshotName, [Map<String, Object?>? args])
      : type = WebDriverCommandType.screenshot,
        values = <String, dynamic>{
          'screenshot_name': screenshotName,
          if (args != null) 'args': args,
        };

  /// Type of the [WebDriverCommand].
  ///
  /// Currently the only command that triggers a WebDriver API is `screenshot`.
  ///
  /// There are also `ack` and `noop` commands defined to manage the handshake
  /// during the communication.
  final WebDriverCommandType type;

  /// Used for adding extra values to the commands such as file name for
  /// `screenshot`.
  final Map<String, dynamic> values;

  /// Util method for converting [WebDriverCommandType] to a map entry.
  ///
  /// Used for converting messages to json format.
  static Map<String, dynamic> typeToMap(WebDriverCommandType type) => <String, dynamic>{
    'web_driver_command': '$type',
  };
}

/// Template methods each class that responses the driver side inputs must
/// implement.
///
/// Depending on the platform the communication between `integration_tests` and
/// the `driver_tests` can be different.
///
/// For the web implementation [WebCallbackManager].
/// For the io implementation [IOCallbackManager].
abstract class CallbackManager {
  /// The callback function to response the driver side input.
  Future<Map<String, dynamic>> callback(
      Map<String, String> params, IntegrationTestResults testRunner);

  /// Takes a screenshot of the application.
  /// Returns the data that is sent back to the host.
   Future<Map<String, dynamic>> takeScreenshot(String screenshot, [Map<String, Object?>? args]);

  /// Android only. Converts the Flutter surface to an image view.
  Future<void> convertFlutterSurfaceToImage();

  /// Cleanup and completers or locks used during the communication.
  void cleanup();
}

/// Interface that surfaces test results of integration tests.
///
/// Implemented by [IntegrationTestWidgetsFlutterBinding]s.
///
/// Any class which needs to access the test results but do not want to create
/// a cyclic dependency [IntegrationTestWidgetsFlutterBinding]s can use this
/// interface. Example [CallbackManager].
abstract class IntegrationTestResults {
  /// Stores failure details.
  ///
  /// Failed test method's names used as key.
  List<Failure> get failureMethodsDetails;

  /// The extra data for the reported result.
  Map<String, dynamic>? get reportData;

  /// Whether all the test methods completed successfully.
  ///
  /// Completes when the tests have finished. The boolean value will be true if
  /// all tests have passed, and false otherwise.
  Completer<bool> get allTestsPassed;
}
