// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. 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:io';

import '../../backend/test_platform.dart';
import '../../util/io.dart';
import '../../utils.dart';
import '../application_exception.dart';
import '../executable_settings.dart';
import 'browser.dart';
import 'default_settings.dart';

final _observatoryRegExp = new RegExp(r"^Observatory listening on ([^ ]+)");
final _errorTimeout = const Duration(seconds: 10);

/// A class for running an instance of the Dartium content shell.
///
/// Most of the communication with the browser is expected to happen via HTTP,
/// so this exposes a bare-bones API. The browser starts as soon as the class is
/// constructed, and is killed when [close] is called.
///
/// Any errors starting or running the process are reported through [onExit].
class ContentShell extends Browser {
  final name = "Content Shell";

  final Future<Uri> observatoryUrl;

  final Future<Uri> remoteDebuggerUrl;

  factory ContentShell(url, {ExecutableSettings settings, bool debug: false}) {
    settings ??= defaultSettings[TestPlatform.contentShell];
    var observatoryCompleter = new Completer<Uri>.sync();
    var remoteDebuggerCompleter = new Completer<Uri>.sync();
    return new ContentShell._(() {
      var tryPort = ([int port]) async {
        var args = ["--dump-render-tree", url.toString()]
          ..addAll(settings.arguments);
        if (port != null) args.add("--remote-debugging-port=$port");

        var process = await Process.start(settings.executable, args,
            environment: {"DART_FLAGS": "--checked"});

        if (debug) {
          observatoryCompleter.complete(lineSplitter
              .bind(process.stdout)
              .map((line) {
                var match = _observatoryRegExp.firstMatch(line);
                if (match == null) return null;
                return Uri.parse(match[1]);
              })
              .where((uri) => uri != null)
              .first);
        } else {
          observatoryCompleter.complete(null);
        }

        var stderr = new StreamIterator(lineSplitter.bind(process.stderr));

        // Before we can consider content_shell started successfully, we have to
        // make sure it's not expired and that the remote debugging port worked.
        // Any errors from this will always come before the "Running without
        // renderer sandbox" message.
        while (await stderr.moveNext().timeout(_errorTimeout).catchError((_) =>
                throw new ApplicationException(
                    "Error starting up content_shell.\n"
                    "Ensure you are using the latest version:\n"
                    "http://gsdview.appspot.com/dart-archive/channels/stable/"
                    "release/latest/dartium/")) &&
            !stderr.current.endsWith("Running without renderer sandbox") &&
            !stderr.current.contains("Running without the SUID sandbox") &&
            // Error messages on Mac can get gobbled, we must assume that it
            // it started up successfully.
            !stderr.current
                .contains("kq_init: detected broken kqueue; not using")) {
          if (stderr.current == "[dartToStderr]: Dartium build has expired") {
            stderr.cancel();
            process.kill();
            // TODO(nweiz): link to dartlang.org once it has download links for
            // content shell
            // (https://github.com/dart-lang/www.dartlang.org/issues/1164).
            throw new ApplicationException(
                "You're using an expired content_shell. Upgrade to the latest "
                "version:\n"
                "http://gsdview.appspot.com/dart-archive/channels/stable/"
                "release/latest/dartium/");
          } else if (stderr.current.contains("bind() returned an error")) {
            // If we failed to bind to the port, return null to tell
            // getUnusedPort to try another one.
            stderr.cancel();
            process.kill();
            return null;
          }
        }

        if (port != null) {
          remoteDebuggerCompleter.complete(
              getRemoteDebuggerUrl(Uri.parse("http://localhost:$port")));
        } else {
          remoteDebuggerCompleter.complete(null);
        }

        stderr.cancel();
        return process;
      };

      if (!debug) return tryPort();
      return getUnusedPort<Process>(tryPort);
    }, observatoryCompleter.future, remoteDebuggerCompleter.future);
  }

  ContentShell._(Future<Process> startBrowser(), this.observatoryUrl,
      this.remoteDebuggerUrl)
      : super(startBrowser);
}
