// 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 'package:path/path.dart' as p;
import 'package:pedantic/pedantic.dart';
import 'package:test_api/src/backend/runtime.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/application_exception.dart'; // ignore: implementation_imports
import 'package:test_core/src/util/exit_codes.dart' // ignore: implementation_imports
    as exit_codes;
import 'package:test_core/src/util/io.dart'; // ignore: implementation_imports

import '../executable_settings.dart';
import 'browser.dart';
import 'default_settings.dart';

/// The PhantomJS script that opens the host page.
final _script = '''
var system = require('system');
var page = require('webpage').create();

// PhantomJS versions older than 2.0.0 don't support the latest WebSocket spec.
if (phantom.version.major < 2) phantom.exit(${exit_codes.protocol});

// Pipe browser messages to the process's stdout. This isn't used by default,
// but it can be useful for debugging.
page.onConsoleMessage = function(message) {
  console.log(message);
}

page.open(system.args[1], function(status) {
  if (status !== "success") phantom.exit(1);
});
''';

/// A class for running an instance of PhantomJS.
///
/// Any errors starting or running the process are reported through [onExit].
class PhantomJS extends Browser {
  @override
  final name = 'PhantomJS';

  @override
  final Future<Uri> remoteDebuggerUrl;

  factory PhantomJS(url, {ExecutableSettings settings, bool debug = false}) {
    settings ??= defaultSettings[Runtime.phantomJS];
    var remoteDebuggerCompleter = Completer<Uri>.sync();
    return PhantomJS._(() async {
      var dir = createTempDir();
      var script = p.join(dir, 'script.js');
      File(script).writeAsStringSync(_script);

      var port = debug ? await getUnsafeUnusedPort() : null;

      var args = settings.arguments.toList();
      if (debug) {
        args.addAll(
            ['--remote-debugger-port=$port', '--remote-debugger-autorun=yes']);
      }
      args.addAll([script, url.toString()]);
      var process = await Process.start(settings.executable, args);

      // PhantomJS synchronously emits standard output, which means that if we
      // don't drain its stdout stream it can deadlock.
      process.stdout.listen((_) {});

      unawaited(process.exitCode.then((exitCode) {
        Directory(dir).deleteSync(recursive: true);

        if (exitCode == exit_codes.protocol) {
          throw ApplicationException(
              'Only PhantomJS version 2.0.0 or greater is supported');
        }
      }));

      if (port != null) {
        remoteDebuggerCompleter.complete(Uri.parse(
            'http://localhost:$port/webkit/inspector/inspector.html?page=2'));
      } else {
        remoteDebuggerCompleter.complete(null);
      }

      return process;
    }, remoteDebuggerCompleter.future);
  }

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