// 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:convert';
import 'dart:io';
import 'package:file/file.dart';
import 'package:matcher/matcher.dart';
import 'package:meta/meta.dart';

import 'package:path/path.dart' as path;
import 'package:vm_service/vm_service.dart' as vms;
import 'package:webdriver/async_io.dart' as async_io;
import 'package:webdriver/support/async.dart';

import '../common/error.dart';
import '../common/message.dart';

import 'common.dart';
import 'driver.dart';
import 'timeline.dart';

/// An implementation of the Flutter Driver using the WebDriver.
///
/// Example of how to test WebFlutterDriver:
///   1. Launch WebDriver binary: ./chromedriver --port=4444
///   2. Run test script: flutter drive --target=test_driver/scroll_perf_web.dart -d web-server --release
class WebFlutterDriver extends FlutterDriver {
  /// Creates a driver that uses a connection provided by the given
  /// [_connection].
  WebFlutterDriver.connectedTo(
    this._connection, {
    bool printCommunication = false,
    bool logCommunicationToFile = true,
  })  : _printCommunication = printCommunication,
        _logCommunicationToFile = logCommunicationToFile,
        _startTime = DateTime.now(),
        _driverId = _nextDriverId++
    {
      _logFilePathName = path.join(testOutputsDirectory, 'flutter_driver_commands_$_driverId.log');
    }


  final FlutterWebConnection _connection;
  DateTime _startTime;
  static int _nextDriverId = 0;

  /// The unique ID of this driver instance.
  final int _driverId;

  /// Start time for tracing.
  @visibleForTesting
  DateTime get startTime => _startTime;

  @override
  vms.Isolate get appIsolate => throw UnsupportedError('WebFlutterDriver does not support appIsolate');

  @override
  vms.VmService get serviceClient => throw UnsupportedError('WebFlutterDriver does not support serviceClient');

  @override
  async_io.WebDriver get webDriver => _connection._driver;

  /// Whether to print communication between host and app to `stdout`.
  final bool _printCommunication;

  /// Whether to log communication between host and app to `flutter_driver_commands.log`.
  final bool _logCommunicationToFile;

  /// Logs are written here when _logCommunicationToFile is true.
  late final String _logFilePathName;

  /// Getter for file pathname where logs are written when _logCommunicationToFile is true
  String get logFilePathName => _logFilePathName;

  /// Creates a driver that uses a connection provided by the given
  /// [hostUrl] which would fallback to environment variable VM_SERVICE_URL.
  /// Driver also depends on environment variables DRIVER_SESSION_ID,
  /// BROWSER_SUPPORTS_TIMELINE, DRIVER_SESSION_URI, DRIVER_SESSION_SPEC,
  /// DRIVER_SESSION_CAPABILITIES and ANDROID_CHROME_ON_EMULATOR for
  /// configurations.
  ///
  /// See [FlutterDriver.connect] for more documentation.
  static Future<FlutterDriver> connectWeb({
    String? hostUrl,
    bool printCommunication = false,
    bool logCommunicationToFile = true,
    Duration? timeout,
  }) async {
    hostUrl ??= Platform.environment['VM_SERVICE_URL'];
    final Map<String, dynamic> settings = <String, dynamic>{
      'support-timeline-action': Platform.environment['SUPPORT_TIMELINE_ACTION'] == 'true',
      'session-id': Platform.environment['DRIVER_SESSION_ID'],
      'session-uri': Platform.environment['DRIVER_SESSION_URI'],
      'session-spec': Platform.environment['DRIVER_SESSION_SPEC'],
      'android-chrome-on-emulator': Platform.environment['ANDROID_CHROME_ON_EMULATOR'] == 'true',
      'session-capabilities': Platform.environment['DRIVER_SESSION_CAPABILITIES'],
    };
    final FlutterWebConnection connection = await FlutterWebConnection.connect
      (hostUrl!, settings, timeout: timeout);
    return WebFlutterDriver.connectedTo(
      connection,
      printCommunication: printCommunication,
      logCommunicationToFile: logCommunicationToFile,
    );
  }

  static DriverError _createMalformedExtensionResponseError(Object? data) {
    throw DriverError(
      'Received malformed response from the FlutterDriver extension.\n'
      'Expected a JSON map containing a "response" field and, optionally, an '
      '"isError" field, but got ${data.runtimeType}: $data'
    );
  }

  @override
  Future<Map<String, dynamic>> sendCommand(Command command) async {
    final Map<String, dynamic> response;
    final Object? data;
    final Map<String, String> serialized = command.serialize();
    _logCommunication('>>> $serialized');
    try {
      data = await _connection.sendCommand("window.\$flutterDriver('${jsonEncode(serialized)}')", command.timeout);

      // The returned data is expected to be a string. If it's null or anything
      // other than a string, something's wrong.
      if (data is! String) {
        throw _createMalformedExtensionResponseError(data);
      }

      final Object? decoded = json.decode(data);
      if (decoded is! Map<String, dynamic>) {
        throw _createMalformedExtensionResponseError(data);
      } else {
        response = decoded;
      }

      _logCommunication('<<< $response');
    } on DriverError catch(_) {
      rethrow;
    } catch (error, stackTrace) {
      throw DriverError(
        'FlutterDriver command ${command.runtimeType} failed due to a remote error.\n'
        'Command sent: ${jsonEncode(serialized)}',
        error,
        stackTrace
      );
    }

    final Object? isError = response['isError'];
    final Object? responseData = response['response'];
    if (isError is! bool?) {
      throw _createMalformedExtensionResponseError(data);
    } else if (isError ?? false) {
      throw DriverError('Error in Flutter application: $responseData');
    }

    if (responseData is! Map<String, dynamic>) {
      throw _createMalformedExtensionResponseError(data);
    }
    return responseData;
  }

  @override
  Future<void> close() => _connection.close();

  @override
  Future<void> waitUntilFirstFrameRasterized() async {
    throw UnimplementedError();
  }

  void _logCommunication(String message) {
    if (_printCommunication) {
      driverLog('WebFlutterDriver', message);
    }
    if (_logCommunicationToFile) {
      assert(_logFilePathName != null);
      final File file = fs.file(_logFilePathName);
      file.createSync(recursive: true); // no-op if file exists
      file.writeAsStringSync('${DateTime.now()} $message\n', mode: FileMode.append, flush: true);
    }
  }

  @override
  Future<List<int>> screenshot() async {
    await Future<void>.delayed(const Duration(seconds: 2));

    return _connection.screenshot();
  }

  @override
  Future<void> startTracing({
    List<TimelineStream> streams = const <TimelineStream>[TimelineStream.all],
    Duration timeout = kUnusuallyLongTimeout,
  }) async {
    _checkBrowserSupportsTimeline();
  }

  @override
  Future<Timeline> stopTracingAndDownloadTimeline({Duration timeout = kUnusuallyLongTimeout}) async {
    _checkBrowserSupportsTimeline();

    final List<Map<String, dynamic>> events = <Map<String, dynamic>>[];
    for (final async_io.LogEntry entry in await _connection.logs.toList()) {
      if (_startTime.isBefore(entry.timestamp)) {
        final Map<String, dynamic> data = (jsonDecode(entry.message!) as Map<String, dynamic>)['message'] as Map<String, dynamic>;
        if (data['method'] == 'Tracing.dataCollected') {
          // 'ts' data collected from Chrome is in double format, conversion needed
          try {
            final Map<String, dynamic> params = data['params'] as Map<String, dynamic>;
            params['ts'] = double.parse(params['ts'].toString()).toInt();
          } on FormatException catch (_) {
            // data is corrupted, skip
            continue;
          }
          events.add(data['params']! as Map<String, dynamic>);
        }
      }
    }
    final Map<String, dynamic> json = <String, dynamic>{
      'traceEvents': events,
    };
    return Timeline.fromJson(json);
  }

  @override
  Future<Timeline> traceAction(Future<dynamic> Function() action, {
    List<TimelineStream> streams = const <TimelineStream>[TimelineStream.all],
    bool retainPriorEvents = false,
  }) async {
    _checkBrowserSupportsTimeline();
    if (!retainPriorEvents) {
      await clearTimeline();
    }
    await startTracing(streams: streams);
    await action();

    return stopTracingAndDownloadTimeline();
  }

  @override
  Future<void> clearTimeline({Duration timeout = kUnusuallyLongTimeout}) async {
    _checkBrowserSupportsTimeline();

    // Reset start time
    _startTime = DateTime.now();
  }

  /// Checks whether browser supports Timeline related operations.
  void _checkBrowserSupportsTimeline() {
    if (!_connection.supportsTimelineAction) {
      throw UnsupportedError('Timeline action is not supported by current testing browser');
    }
  }
}

/// Encapsulates connection information to an instance of a Flutter Web application.
class FlutterWebConnection {
  /// Creates a FlutterWebConnection with WebDriver
  /// and whether the WebDriver supports timeline action.
  FlutterWebConnection(this._driver, this.supportsTimelineAction);

  final async_io.WebDriver _driver;

  /// Whether the connected WebDriver supports timeline action for Flutter Web Driver.
  bool supportsTimelineAction;

  /// Starts WebDriver with the given [settings] and
  /// establishes the connection to Flutter Web application.
  static Future<FlutterWebConnection> connect(
      String url,
      Map<String, dynamic> settings,
      {Duration? timeout}) async {
    final String sessionId = settings['session-id'].toString();
    final Uri sessionUri = Uri.parse(settings['session-uri'].toString());
    final async_io.WebDriver driver = async_io.WebDriver(
        sessionUri,
        sessionId,
        json.decode(settings['session-capabilities'] as String) as Map<String, dynamic>,
        async_io.AsyncIoRequestClient(sessionUri.resolve('session/$sessionId/')),
        _convertToSpec(settings['session-spec'].toString().toLowerCase()));
    if (settings['android-chrome-on-emulator'] == true) {
      final Uri localUri = Uri.parse(url);
      // Converts to Android Emulator Uri.
      // Hardcode the host to 10.0.2.2 based on
      // https://developer.android.com/studio/run/emulator-networking
      url = Uri(scheme: localUri.scheme, host: '10.0.2.2', port:localUri.port).toString();
    }
    await driver.get(url);

    await waitUntilExtensionInstalled(driver, timeout);
    return FlutterWebConnection(driver, settings['support-timeline-action'] as bool);
  }

  /// Sends command via WebDriver to Flutter web application.
  Future<dynamic> sendCommand(String script, Duration? duration) async {
    // This code should not be reachable before the VM service extension is
    // initialized. The VM service extension is expected to initialize both
    // `$flutterDriverResult` and `$flutterDriver` variables before attempting
    // to send commands. This part checks that `$flutterDriverResult` is present.
    // `$flutterDriver` is not checked because it is covered by the `script`
    // that's executed next.
    try {
      await _driver.execute(r'return $flutterDriverResult', <String>[]);
    } catch (error, stackTrace) {
      throw DriverError(
        'Driver extension has not been initialized correctly.\n'
        'If the test uses a custom VM service extension, make sure it conforms '
        'to the protocol used by package:integration_test and '
        'package:flutter_driver.\n'
        'If the test uses VM service extensions provided by the Flutter SDK, '
        'then this error is likely caused by a bug in Flutter. Please report it '
        'by filing a bug on GitHub:\n'
        '  https://github.com/flutter/flutter/issues/new?template=2_bug.md',
        error,
        stackTrace,
      );
    }

    String phase = 'executing';
    try {
      // Execute the script, which should leave the result in the `$flutterDriverResult` global variable.
      await _driver.execute(script, <void>[]);

      // Read the result.
      phase = 'reading';
      final dynamic result = await waitFor<dynamic>(
        () => _driver.execute(r'return $flutterDriverResult', <String>[]),
        matcher: isNotNull,
        timeout: duration ?? const Duration(days: 30),
      );

      // Reset the result to null to avoid polluting the results of future commands.
      phase = 'resetting';
      await _driver.execute(r'$flutterDriverResult = null', <void>[]);
      return result;
    } catch (error, stackTrace) {
      throw DriverError(
        'Error while $phase FlutterDriver result for command: $script',
        error,
        stackTrace,
      );
    }
  }

  /// Gets performance log from WebDriver.
  Stream<async_io.LogEntry> get logs => _driver.logs.get(async_io.LogType.performance);

  /// Takes screenshot via WebDriver.
  Future<List<int>> screenshot()  => _driver.captureScreenshotAsList();

  /// Closes the WebDriver.
  Future<void> close() async {
    await _driver.quit(closeSession: false);
  }
}

/// Waits until extension is installed.
Future<void> waitUntilExtensionInstalled(async_io.WebDriver driver, Duration? timeout) async {
  await waitFor<void>(() =>
      driver.execute(r'return typeof(window.$flutterDriver)', <String>[]),
      matcher: 'function',
      timeout: timeout ?? const Duration(days: 365));
}

async_io.WebDriverSpec _convertToSpec(String specString) {
  switch (specString.toLowerCase()) {
    case 'webdriverspec.w3c':
      return async_io.WebDriverSpec.W3c;
    case 'webdriverspec.jsonwire':
      return async_io.WebDriverSpec.JsonWire;
    default:
      return async_io.WebDriverSpec.Auto;
  }
}
