// Copyright 2013 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.

// @dart = 2.6
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'dart:math';

import 'package:async/async.dart';
import 'package:http_multi_server/http_multi_server.dart';
import 'package:image/image.dart';
import 'package:package_config/package_config.dart';
import 'package:path/path.dart' as p;
import 'package:pool/pool.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_static/shelf_static.dart';
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:shelf_packages_handler/shelf_packages_handler.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_test_utils/goldens.dart';
import 'package:web_test_utils/image_compare.dart';

import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
import 'package:test_api/src/backend/suite_platform.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/runner_suite.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/platform.dart'; // ignore: implementation_imports
import 'package:test_core/src/util/stack_trace_mapper.dart'; // ignore: implementation_imports
import 'package:test_api/src/utils.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/suite.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/plugin/platform_helpers.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/environment.dart'; // ignore: implementation_imports

import 'package:test_core/src/util/io.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/configuration.dart'; // ignore: implementation_imports

import 'browser.dart';
import 'common.dart';
import 'environment.dart' as env;
import 'screenshot_manager.dart';
import 'supported_browsers.dart';

class BrowserPlatform extends PlatformPlugin {
  /// Starts the server.
  ///
  /// [root] is the root directory that the server should serve. It defaults to
  /// the working directory.
  static Future<BrowserPlatform> start(String name,
      {String root, bool doUpdateScreenshotGoldens: false}) async {
    assert(SupportedBrowsers.instance.supportedBrowserNames.contains(name));
    var server = shelf_io.IOServer(await HttpMultiServer.loopback(0));
    return BrowserPlatform._(
      name,
      server,
      Configuration.current,
      p.fromUri(await Isolate.resolvePackageUri(
          Uri.parse('package:test/src/runner/browser/static/favicon.ico'))),
      root: root,
      doUpdateScreenshotGoldens: doUpdateScreenshotGoldens,
    );
  }

  /// The test runner configuration.
  final Configuration _config;

  /// The underlying server.
  final shelf.Server _server;

  /// Name for the running browser. Not final on purpose can be mutated later.
  String browserName;

  /// A randomly-generated secret.
  ///
  /// This is used to ensure that other users on the same system can't snoop
  /// on data being served through this server.
  final _secret = Uri.encodeComponent(randomBase64(24));

  /// The URL for this server.
  Uri get url => _server.url.resolve(_secret + '/');

  /// A [OneOffHandler] for servicing WebSocket connections for
  /// [BrowserManager]s.
  ///
  /// This is one-off because each [BrowserManager] can only connect to a single
  /// WebSocket,
  final OneOffHandler _webSocketHandler = OneOffHandler();

  /// A [PathHandler] used to serve compiled JS.
  final PathHandler _jsHandler = PathHandler();

  /// The root directory served statically by this server.
  final String _root;

  /// The HTTP client to use when caching JS files in `pub serve`.
  final HttpClient _http;

  /// Handles taking screenshots during tests.
  ///
  /// Implementation will differ depending on the browser.
  ScreenshotManager _screenshotManager;

  /// Whether [close] has been called.
  bool get _closed => _closeMemo.hasRun;

  /// Whether to update screenshot golden files.
  final bool doUpdateScreenshotGoldens;

  BrowserPlatform._(
      String name, this._server, Configuration config, String faviconPath,
      {String root, this.doUpdateScreenshotGoldens})
      : this.browserName = name,
        _config = config,
        _root = root == null ? p.current : root,
        _http = config.pubServeUrl == null ? null : HttpClient() {
    var cascade = shelf.Cascade().add(_webSocketHandler.handler);

    if (_config.pubServeUrl == null) {
      // We server static files from here (JS, HTML, etc)
      final String staticFilePath =
          config.suiteDefaults.precompiledPath ?? _root;
      cascade = cascade
          .add(packagesDirHandler())
          .add(_jsHandler.handler)
          .add(createStaticHandler(staticFilePath,
              // Precompiled directories often contain symlinks
              serveFilesOutsidePath:
                  config.suiteDefaults.precompiledPath != null))
          .add(_wrapperHandler);
      // Screenshot tests are only enabled in Chrome and Safari iOS for now.
      if (browserName == 'chrome' || browserName == 'ios-safari') {
        cascade = cascade.add(_screeshotHandler);
        _screenshotManager = ScreenshotManager.choose(browserName);
      }
    }

    var pipeline = shelf.Pipeline()
        .addMiddleware(PathHandler.nestedIn(_secret))
        .addHandler(cascade.handler);

    _server.mount(shelf.Cascade()
        .add(createFileHandler(faviconPath))
        .add(pipeline)
        .handler);
  }

  Future<shelf.Response> _screeshotHandler(shelf.Request request) async {
    if (browserName != 'chrome' && browserName != 'ios-safari') {
      throw Exception('Screenshots tests are only available in Chrome '
          'and in Safari-iOS.');
    }

    if (!request.requestedUri.path.endsWith('/screenshot')) {
      return shelf.Response.notFound(
          'This request is not handled by the screenshot handler');
    }

    final String payload = await request.readAsString();
    final Map<String, dynamic> requestData =
        json.decode(payload) as Map<String, dynamic>;
    final String filename = requestData['filename'] as String;
    final bool write = requestData['write'] as bool;
    final double maxDiffRate = requestData.containsKey('maxdiffrate')
        ? (requestData['maxdiffrate'] as num)
            .toDouble() // can be parsed as either int or double
        : kMaxDiffRateFailure;
    final Map<String, dynamic> region =
        requestData['region'] as Map<String, dynamic>;
    final PixelComparison pixelComparison = PixelComparison.values.firstWhere(
        (value) => value.toString() == requestData['pixelComparison']);
    final String result = await _diffScreenshot(
        filename, write, maxDiffRate, region, pixelComparison);
    return shelf.Response.ok(json.encode(result));
  }

  Future<String> _diffScreenshot(
      String filename,
      bool write,
      double maxDiffRateFailure,
      Map<String, dynamic> region,
      PixelComparison pixelComparison) async {
    if (doUpdateScreenshotGoldens) {
      write = true;
    }

    filename =
        filename.replaceAll('.png', '${_screenshotManager.filenameSuffix}.png');

    String goldensDirectory;
    if (filename.startsWith('__local__')) {
      filename = filename.substring('__local__/'.length);
      goldensDirectory = p.join(
        env.environment.webUiRootDir.path,
        'test',
        'golden_files',
      );
    } else {
      goldensDirectory = p.join(
        env.environment.webUiGoldensRepositoryDirectory.path,
        'engine',
        'web',
      );
    }

    final Rectangle regionAsRectange = Rectangle(
      region['x'] as num,
      region['y'] as num,
      region['width'] as num,
      region['height'] as num,
    );

    // Take screenshot.
    final Image screenshot = await _screenshotManager.capture(regionAsRectange);

    return compareImage(
        screenshot,
        doUpdateScreenshotGoldens,
        filename,
        pixelComparison,
        maxDiffRateFailure,
        goldensDirectory: goldensDirectory,
        write: write);
  }

  /// A handler that serves wrapper files used to bootstrap tests.
  shelf.Response _wrapperHandler(shelf.Request request) {
    var path = p.fromUri(request.url);

    if (path.endsWith('.html')) {
      var test = p.withoutExtension(path) + '.dart';

      // Link to the Dart wrapper.
      var scriptBase = htmlEscape.convert(p.basename(test));
      var link = '<link rel="x-dart-test" href="$scriptBase">';

      return shelf.Response.ok('''
        <!DOCTYPE html>
        <html>
        <head>
          <title>${htmlEscape.convert(test)} Test</title>
          $link
          <script src="packages/test/dart.js"></script>
        </head>
        </html>
      ''', headers: {'Content-Type': 'text/html'});
    }

    return shelf.Response.notFound('Not found.');
  }

  /// Loads the test suite at [path] on the platform [platform].
  ///
  /// This will start a browser to load the suite if one isn't already running.
  /// Throws an [ArgumentError] if `platform.platform` isn't a browser.
  Future<RunnerSuite> load(String path, SuitePlatform platform,
      SuiteConfiguration suiteConfig, Object message) async {
    if (suiteConfig.precompiledPath == null) {
      throw Exception('This test platform only supports precompiled JS.');
    }
    var browser = platform.runtime;
    assert(suiteConfig.runtimes.contains(browser.identifier));

    if (!browser.isBrowser) {
      throw ArgumentError('$browser is not a browser.');
    }

    if (_closed) {
      return null;
    }
    Uri suiteUrl = url.resolveUri(
        p.toUri(p.withoutExtension(p.relative(path, from: _root)) + '.html'));

    if (_closed) {
      return null;
    }

    var browserManager = await _browserManagerFor(browser);
    if (_closed || browserManager == null) {
      return null;
    }

    var suite = await browserManager.load(path, suiteUrl, suiteConfig, message);
    if (_closed) {
      return null;
    }
    return suite;
  }

  StreamChannel loadChannel(String path, SuitePlatform platform) =>
      throw UnimplementedError();

  Future<BrowserManager> _browserManager;

  /// Returns the [BrowserManager] for [runtime], which should be a browser.
  ///
  /// If no browser manager is running yet, starts one.
  Future<BrowserManager> _browserManagerFor(Runtime browser) {
    if (_browserManager != null) {
      return _browserManager;
    }

    var completer = Completer<WebSocketChannel>.sync();
    var path = _webSocketHandler.create(webSocketHandler(completer.complete));
    var webSocketUrl = url.replace(scheme: 'ws').resolve(path);
    var hostUrl = (_config.pubServeUrl == null ? url : _config.pubServeUrl)
        .resolve('packages/web_engine_tester/static/index.html')
        .replace(queryParameters: <String, dynamic>{
      'managerUrl': webSocketUrl.toString(),
      'debug': _config.pauseAfterLoad.toString()
    });

    var future = BrowserManager.start(browser, hostUrl, completer.future,
        debug: _config.pauseAfterLoad);

    // Store null values for browsers that error out so we know not to load them
    // again.
    _browserManager = future.catchError((dynamic _) => null);

    return future;
  }

  /// Close all the browsers that the server currently has open.
  ///
  /// Note that this doesn't close the server itself. Browser tests can still be
  /// loaded, they'll just spawn new browsers.
  Future<void> closeEphemeral() async {
    final BrowserManager result = await _browserManager;
    if (result != null) {
      await result.close();
    }
  }

  /// Closes the server and releases all its resources.
  ///
  /// Returns a [Future] that completes once the server is closed and its
  /// resources have been fully released.
  Future<void> close() {
    return _closeMemo.runOnce(() async {
      final List<Future<void>> futures = <Future<void>>[];
      futures.add(Future<void>.microtask(() async {
        final BrowserManager result = await _browserManager;
        if (result != null) {
          await result.close();
        }
      }));
      futures.add(_server.close());

      await Future.wait(futures);

      if (_config.pubServeUrl != null) {
        _http.close();
      }
    });
  }

  final AsyncMemoizer<dynamic> _closeMemo = AsyncMemoizer<dynamic>();
}

/// A Shelf handler that provides support for one-time handlers.
///
/// This is useful for handlers that only expect to be hit once before becoming
/// invalid and don't need to have a persistent URL.
class OneOffHandler {
  /// A map from URL paths to handlers.
  final _handlers = Map<String, shelf.Handler>();

  /// The counter of handlers that have been activated.
  var _counter = 0;

  /// The actual [shelf.Handler] that dispatches requests.
  shelf.Handler get handler => _onRequest;

  /// Creates a new one-off handler that forwards to [handler].
  ///
  /// Returns a string that's the URL path for hitting this handler, relative to
  /// the URL for the one-off handler itself.
  ///
  /// [handler] will be unmounted as soon as it receives a request.
  String create(shelf.Handler handler) {
    var path = _counter.toString();
    _handlers[path] = handler;
    _counter++;
    return path;
  }

  /// Dispatches [request] to the appropriate handler.
  FutureOr<shelf.Response> _onRequest(shelf.Request request) {
    var components = p.url.split(request.url.path);
    if (components.isEmpty) {
      return shelf.Response.notFound(null);
    }

    var path = components.removeAt(0);
    var handler = _handlers.remove(path);
    if (handler == null) {
      return shelf.Response.notFound(null);
    }
    return handler(request.change(path: path));
  }
}

/// A handler that routes to sub-handlers based on exact path prefixes.
class PathHandler {
  /// A trie of path components to handlers.
  final _paths = _Node();

  /// The shelf handler.
  shelf.Handler get handler => _onRequest;

  /// Returns middleware that nests all requests beneath the URL prefix
  /// [beneath].
  static shelf.Middleware nestedIn(String beneath) {
    return (handler) {
      var pathHandler = PathHandler()..add(beneath, handler);
      return pathHandler.handler;
    };
  }

  /// Routes requests at or under [path] to [handler].
  ///
  /// If [path] is a parent or child directory of another path in this handler,
  /// the longest matching prefix wins.
  void add(String path, shelf.Handler handler) {
    var node = _paths;
    for (var component in p.url.split(path)) {
      node = node.children.putIfAbsent(component, () => _Node());
    }
    node.handler = handler;
  }

  FutureOr<shelf.Response> _onRequest(shelf.Request request) {
    shelf.Handler handler;
    int handlerIndex;
    var node = _paths;
    var components = p.url.split(request.url.path);
    for (var i = 0; i < components.length; i++) {
      node = node.children[components[i]];
      if (node == null) {
        break;
      }
      if (node.handler == null) {
        continue;
      }
      handler = node.handler;
      handlerIndex = i;
    }

    if (handler == null) {
      return shelf.Response.notFound('Not found.');
    }

    return handler(
        request.change(path: p.url.joinAll(components.take(handlerIndex + 1))));
  }
}

/// A trie node.
class _Node {
  shelf.Handler handler;
  final children = Map<String, _Node>();
}

/// A class that manages the connection to a single running browser.
///
/// This is in charge of telling the browser which test suites to load and
/// converting its responses into [Suite] objects.
class BrowserManager {
  /// The browser instance that this is connected to via [_channel].
  final Browser _browser;

  /// The [Runtime] for [_browser].
  final Runtime _runtime;

  /// The channel used to communicate with the browser.
  ///
  /// This is connected to a page running `static/host.dart`.
  MultiChannel _channel;

  /// A pool that ensures that limits the number of initial connections the
  /// manager will wait for at once.
  ///
  /// This isn't the *total* number of connections; any number of iframes may be
  /// loaded in the same browser. However, the browser can only load so many at
  /// once, and we want a timeout in case they fail so we only wait for so many
  /// at once.
  final _pool = Pool(8);

  /// The ID of the next suite to be loaded.
  ///
  /// This is used to ensure that the suites can be referred to consistently
  /// across the client and server.
  int _suiteID = 0;

  /// Whether the channel to the browser has closed.
  bool _closed = false;

  /// The completer for [_BrowserEnvironment.displayPause].
  ///
  /// This will be `null` as long as the browser isn't displaying a pause
  /// screen.
  CancelableCompleter _pauseCompleter;

  /// The controller for [_BrowserEnvironment.onRestart].
  final _onRestartController = StreamController<dynamic>.broadcast();

  /// The environment to attach to each suite.
  Future<_BrowserEnvironment> _environment;

  /// Controllers for every suite in this browser.
  ///
  /// These are used to mark suites as debugging or not based on the browser's
  /// pings.
  final _controllers = Set<RunnerSuiteController>();

  // A timer that's reset whenever we receive a message from the browser.
  //
  // Because the browser stops running code when the user is actively debugging,
  // this lets us detect whether they're debugging reasonably accurately.
  RestartableTimer _timer;

  /// Starts the browser identified by [runtime] and has it connect to [url].
  ///
  /// [url] should serve a page that establishes a WebSocket connection with
  /// this process. That connection, once established, should be emitted via
  /// [future]. If [debug] is true, starts the browser in debug mode, with its
  /// debugger interfaces on and detected.
  ///
  /// The [settings] indicate how to invoke this browser's executable.
  ///
  /// Returns the browser manager, or throws an [Exception] if a
  /// connection fails to be established.
  static Future<BrowserManager> start(
      Runtime runtime, Uri url, Future<WebSocketChannel> future,
      {bool debug = false}) {
    var browser = _newBrowser(url, runtime, debug: debug);

    var completer = Completer<BrowserManager>();

    // For the cases where we use a delegator such as `adb` (for Android) or
    // `xcrun` (for IOS), these delegator processes can shut down before the
    // websocket is available. Therefore do not throw an error if proccess
    // exits with exitCode 0. Note that `browser` will throw and error if the
    // exit code was not 0, which will be processed by the next callback.
    browser.onExit.catchError((dynamic error, StackTrace stackTrace) {
      if (completer.isCompleted) {
        return;
      }
      completer.completeError(error, stackTrace);
    });

    future.then((webSocket) {
      if (completer.isCompleted) {
        return;
      }
      completer.complete(BrowserManager._(browser, runtime, webSocket));
    }).catchError((dynamic error, StackTrace stackTrace) {
      browser.close();
      if (completer.isCompleted) {
        return;
      }
      completer.completeError(error, stackTrace);
    });

    return completer.future;
  }

  /// Starts the browser identified by [browser] using [settings] and has it load [url].
  ///
  /// If [debug] is true, starts the browser in debug mode.
  static Browser _newBrowser(Uri url, Runtime browser, {bool debug = false}) {
    return SupportedBrowsers.instance.getBrowser(browser, url, debug: debug);
  }

  /// Creates a new BrowserManager that communicates with [browser] over
  /// [webSocket].
  BrowserManager._(this._browser, this._runtime, WebSocketChannel webSocket) {
    // The duration should be short enough that the debugging console is open as
    // soon as the user is done setting breakpoints, but long enough that a test
    // doing a lot of synchronous work doesn't trigger a false positive.
    //
    // Start this canceled because we don't want it to start ticking until we
    // get some response from the iframe.
    _timer = RestartableTimer(Duration(seconds: 3), () {
      for (var controller in _controllers) {
        controller.setDebugging(true);
      }
    })
      ..cancel();

    // Whenever we get a message, no matter which child channel it's for, we the
    // know browser is still running code which means the user isn't debugging.
    _channel = MultiChannel<dynamic>(
        webSocket.cast<String>().transform(jsonDocument).changeStream((stream) {
      return stream.map((message) {
        if (!_closed) {
          _timer.reset();
        }
        for (var controller in _controllers) {
          controller.setDebugging(false);
        }

        return message;
      });
    }));

    _environment = _loadBrowserEnvironment();
    _channel.stream
        .listen((dynamic message) => _onMessage(message as Map), onDone: close);
  }

  /// Loads [_BrowserEnvironment].
  Future<_BrowserEnvironment> _loadBrowserEnvironment() async {
    return _BrowserEnvironment(this, await _browser.observatoryUrl,
        await _browser.remoteDebuggerUrl, _onRestartController.stream);
  }

  /// Tells the browser the load a test suite from the URL [url].
  ///
  /// [url] should be an HTML page with a reference to the JS-compiled test
  /// suite. [path] is the path of the original test suite file, which is used
  /// for reporting. [suiteConfig] is the configuration for the test suite.
  Future<RunnerSuite> load(String path, Uri url, SuiteConfiguration suiteConfig,
      Object message) async {
    url = url.replace(
        fragment: Uri.encodeFull(jsonEncode(<String, dynamic>{
      'metadata': suiteConfig.metadata.serialize(),
      'browser': _runtime.identifier
    })));

    var suiteID = _suiteID++;
    RunnerSuiteController controller;
    void closeIframe() {
      if (_closed) {
        return;
      }
      _controllers.remove(controller);
      _channel.sink.add({'command': 'closeSuite', 'id': suiteID});
    }

    // The virtual channel will be closed when the suite is closed, in which
    // case we should unload the iframe.
    var virtualChannel = _channel.virtualChannel();
    var suiteChannelID = virtualChannel.id;
    var suiteChannel = virtualChannel.transformStream(
        StreamTransformer<dynamic, dynamic>.fromHandlers(handleDone: (sink) {
      closeIframe();
      sink.close();
    }));

    return await _pool.withResource<RunnerSuite>(() async {
      _channel.sink.add({
        'command': 'loadSuite',
        'url': url.toString(),
        'id': suiteID,
        'channel': suiteChannelID
      });

      try {
        controller = deserializeSuite(path, currentPlatform(_runtime),
            suiteConfig, await _environment, suiteChannel, message);

        final String sourceMapFileName =
            '${p.basename(path)}.browser_test.dart.js.map';
        final String pathToTest = p.dirname(path);

        final String mapPath = p.join(env.environment.webUiRootDir.path,
            'build', pathToTest, sourceMapFileName);

        PackageConfig packageConfig =
            await loadPackageConfigUri(await Isolate.packageConfig);
        Map<String, Uri> packageMap = {
          for (var p in packageConfig.packages) p.name: p.packageUriRoot
        };
        final JSStackTraceMapper mapper = JSStackTraceMapper(
          await File(mapPath).readAsString(),
          mapUrl: p.toUri(mapPath),
          packageMap: packageMap,
          sdkRoot: p.toUri(sdkDir),
        );

        controller.channel('test.browser.mapper').sink.add(mapper.serialize());

        _controllers.add(controller);
        return await controller.suite;
      } catch (_) {
        closeIframe();
        rethrow;
      }
    });
  }

  /// An implementation of [Environment.displayPause].
  CancelableOperation _displayPause() {
    if (_pauseCompleter != null) {
      return _pauseCompleter.operation;
    }

    _pauseCompleter = CancelableCompleter<void>(onCancel: () {
      _channel.sink.add({'command': 'resume'});
      _pauseCompleter = null;
    });

    _pauseCompleter.operation.value.whenComplete(() {
      _pauseCompleter = null;
    });

    _channel.sink.add({'command': 'displayPause'});

    return _pauseCompleter.operation;
  }

  /// The callback for handling messages received from the host page.
  void _onMessage(Map message) {
    switch (message['command'] as String) {
      case 'ping':
        break;

      case 'restart':
        _onRestartController.add(null);
        break;

      case 'resume':
        if (_pauseCompleter != null) {
          _pauseCompleter.complete();
        }
        break;

      default:
        // Unreachable.
        assert(false);
        break;
    }
  }

  /// Closes the manager and releases any resources it owns, including closing
  /// the browser.
  Future close() => _closeMemoizer.runOnce(() {
        _closed = true;
        _timer.cancel();
        if (_pauseCompleter != null) {
          _pauseCompleter.complete();
        }
        _pauseCompleter = null;
        _controllers.clear();
        return _browser.close();
      });
  final AsyncMemoizer<dynamic> _closeMemoizer = AsyncMemoizer<dynamic>();
}

/// An implementation of [Environment] for the browser.
///
/// All methods forward directly to [BrowserManager].
class _BrowserEnvironment implements Environment {
  final BrowserManager _manager;

  final supportsDebugging = true;

  final Uri observatoryUrl;

  final Uri remoteDebuggerUrl;

  final Stream onRestart;

  _BrowserEnvironment(this._manager, this.observatoryUrl,
      this.remoteDebuggerUrl, this.onRestart);

  CancelableOperation displayPause() => _manager._displayPause();
}

bool get isCirrus => Platform.environment['CIRRUS_CI'] == 'true';
