// Copyright (c) 2013, 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.
library browser;

import "dart:async";
import "dart:convert" show LineSplitter, UTF8;
import "dart:core";
import "dart:io";

import 'android.dart';
import 'utils.dart';

class BrowserOutput {
  final StringBuffer stdout = new StringBuffer();
  final StringBuffer stderr = new StringBuffer();
  final StringBuffer eventLog = new StringBuffer();
}

/** Class describing the interface for communicating with browsers. */
abstract class Browser {
  BrowserOutput _allBrowserOutput = new BrowserOutput();
  BrowserOutput _testBrowserOutput = new BrowserOutput();

  // This is called after the process is closed, before the done future
  // is completed.
  // Subclasses can use this to cleanup any browser specific resources
  // (temp directories, profiles, etc). The function is expected to do
  // it's work synchronously.
  Function _cleanup;

  /** The version of the browser - normally set when starting a browser */
  String version = "";

  // The path to the browser executable.
  String _binary;

  /**
   * The underlying process - don't mess directly with this if you don't
   * know what you are doing (this is an interactive process that needs
   * special threatment to not leak).
   */
  Process process;

  Function logger;

  /**
   * Id of the browser
   */
  String id;

  /**
   * Delete the browser specific caches on startup.
   * Browser specific implementations are free to ignore this.
   */
  static bool deleteCache = false;

  /** Print everything (stdout, stderr, usageLog) whenever we add to it */
  bool debugPrint = false;

  // This future returns when the process exits. It is also the return value
  // of close()
  Future done;

  Browser();

  factory Browser.byName(String name,
                         String executablePath,
                         [bool checkedMode = false]) {
    var browser;
    if (name == 'firefox') {
      browser = new Firefox();
    } else if (name == 'chrome') {
      browser = new Chrome();
    } else if (name == 'dartium') {
      browser = new Dartium(checkedMode);
    } else if (name == 'safari') {
      browser = new Safari();
    } else if (name == 'safarimobilesim') {
      browser = new SafariMobileSimulator();
    } else if (name.startsWith('ie')) {
      browser = new IE();
    } else {
      throw "Non supported browser";
    }
    browser._binary = executablePath;
    return browser;
  }

  static const List<String> SUPPORTED_BROWSERS =
    const ['safari', 'ff', 'firefox', 'chrome', 'ie9', 'ie10',
           'ie11', 'dartium'];

  static const List<String> BROWSERS_WITH_WINDOW_SUPPORT = const ['ie11'];

  // TODO(kustermann): add standard support for chrome on android
  static bool supportedBrowser(String name) {
    return SUPPORTED_BROWSERS.contains(name);
  }

  void _logEvent(String event) {
    String toLog = "$this ($id) - $event \n";
    if (debugPrint) print("usageLog: $toLog");
    if (logger != null) logger(toLog);

    _allBrowserOutput.eventLog.write(toLog);
    _testBrowserOutput.eventLog.write(toLog);
  }

  void _addStdout(String output) {
    if (debugPrint) print("stdout: $output");

    _allBrowserOutput.stdout.write(output);
    _testBrowserOutput.stdout.write(output);
  }

  void _addStderr(String output) {
    if (debugPrint) print("stderr: $output");

    _allBrowserOutput.stderr.write(output);
    _testBrowserOutput.stderr.write(output);
  }

  Future close() {
    _logEvent("Close called on browser");
    if (process != null) {
      if (process.kill(ProcessSignal.SIGKILL)) {
        _logEvent("Successfully sent kill signal to process.");
      } else {
        _logEvent("Sending kill signal failed.");
      }
      return done;
    } else {
      _logEvent("The process is already dead.");
      return new Future.value(true);
    }
  }

  /**
   * Start the browser using the supplied argument.
   * This sets up the error handling and usage logging.
   */
  Future<bool> startBrowser(String command,
                            List<String> arguments,
                            {Map<String,String> environment}) {
    return Process.start(command, arguments, environment: environment)
        .then((startedProcess) {
      process = startedProcess;
      // Used to notify when exiting, and as a return value on calls to
      // close().
      var doneCompleter = new Completer();
      done = doneCompleter.future;

      Completer stdoutDone = new Completer();
      Completer stderrDone = new Completer();

      bool stdoutIsDone = false;
      bool stderrIsDone = false;
      StreamSubscription stdoutSubscription;
      StreamSubscription stderrSubscription;

      // This timer is used to close stdio to the subprocess once we got
      // the exitCode. Sometimes descendants of the subprocess keep stdio
      // handles alive even though the direct subprocess is dead.
      Timer watchdogTimer;

      void closeStdout([_]){
        if (!stdoutIsDone) {
          stdoutDone.complete();
          stdoutIsDone = true;

          if (stderrIsDone && watchdogTimer != null) {
            watchdogTimer.cancel();
          }
        }
      }

      void closeStderr([_]) {
        if (!stderrIsDone) {
          stderrDone.complete();
          stderrIsDone = true;

          if (stdoutIsDone && watchdogTimer != null) {
            watchdogTimer.cancel();
          }
        }
      }

      stdoutSubscription =
        process.stdout.transform(UTF8.decoder).listen((data) {
        _addStdout(data);
      }, onError: (error) {
        // This should _never_ happen, but we really want this in the log
        // if it actually does due to dart:io or vm bug.
        _logEvent("An error occured in the process stdout handling: $error");
      }, onDone: closeStdout);

      stderrSubscription =
        process.stderr.transform(UTF8.decoder).listen((data) {
        _addStderr(data);
      }, onError: (error) {
        // This should _never_ happen, but we really want this in the log
        // if it actually does due to dart:io or vm bug.
        _logEvent("An error occured in the process stderr handling: $error");
      },  onDone: closeStderr);

      process.exitCode.then((exitCode) {
        _logEvent("Browser closed with exitcode $exitCode");

        if (!stdoutIsDone || !stderrIsDone) {
          watchdogTimer = new Timer(MAX_STDIO_DELAY, () {
            DebugLogger.warning(
                "$MAX_STDIO_DELAY_PASSED_MESSAGE (browser: $this)");
            watchdogTimer = null;
            stdoutSubscription.cancel();
            stderrSubscription.cancel();
            closeStdout();
            closeStderr();
          });
        }

        Future.wait([stdoutDone.future, stderrDone.future]).then((_) {
          process = null;
          if (_cleanup != null) {
            _cleanup();
          }
        }).catchError((error) {
          _logEvent("Error closing browsers: $error");
        }).whenComplete(() => doneCompleter.complete(true));
      });
      return true;
    }).catchError((error) {
      _logEvent("Running $command $arguments failed with $error");
      return false;
    });
  }

  /**
   * Get the output that was written so far to stdout/stderr/eventLog.
   */
  BrowserOutput get allBrowserOutput => _allBrowserOutput;
  BrowserOutput get testBrowserOutput => _testBrowserOutput;

  void resetTestBrowserOutput() {
    _testBrowserOutput = new BrowserOutput();
  }

  String toString();

  /** Starts the browser loading the given url */
  Future<bool> start(String url);
}

class Safari extends Browser {
  /**
   * We get the safari version by parsing a version file
   */
  static const String versionFile =
      "/Applications/Safari.app/Contents/version.plist";

  /**
   * Directories where safari stores state. We delete these if the deleteCache
   * is set
   */
  static const List<String> CACHE_DIRECTORIES =
      const ["Library/Caches/com.apple.Safari",
             "Library/Safari",
             "Library/Saved Application State/com.apple.Safari.savedState",
             "Library/Caches/Metadata/Safari"];


  Future<bool> allowPopUps() {
    var command = "defaults";
    var args = ["write", "com.apple.safari",
                "com.apple.Safari.ContentPageGroupIdentifier."
                "WebKit2JavaScriptCanOpenWindowsAutomatically",
                "1"];
    return Process.run(command, args).then((result) {
      if (result.exitCode != 0) {
        _logEvent("Could not disable pop-up blocking for safari");
        return false;
      }
      return true;
    });
  }

  Future<bool> deleteIfExists(Iterator<String> paths) {
    if (!paths.moveNext()) return new Future.value(true);
    Directory directory = new Directory(paths.current);
    return directory.exists().then((exists) {
      if (exists) {
        _logEvent("Deleting ${paths.current}");
        return directory.delete(recursive: true)
	    .then((_) => deleteIfExists(paths))
	    .catchError((error) {
	      _logEvent("Failure trying to delete ${paths.current}: $error");
	      return false;
	    });
      } else {
        _logEvent("${paths.current} is not present");
        return deleteIfExists(paths);
      }
    });
  }

  // Clears the cache if the static deleteCache flag is set.
  // Returns false if the command to actually clear the cache did not complete.
  Future<bool> clearCache() {
    if (!Browser.deleteCache) return new Future.value(true);
    var home = Platform.environment['HOME'];
    Iterator iterator = CACHE_DIRECTORIES.map((s) => "$home/$s").iterator;
    return deleteIfExists(iterator);
  }

  Future<String> getVersion() {
    /**
     * Example of the file:
     * <?xml version="1.0" encoding="UTF-8"?>
     * <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     * <plist version="1.0">
     * <dict>
     *	     <key>BuildVersion</key>
     * 	     <string>2</string>
     * 	     <key>CFBundleShortVersionString</key>
     * 	     <string>6.0.4</string>
     * 	     <key>CFBundleVersion</key>
     * 	     <string>8536.29.13</string>
     * 	     <key>ProjectName</key>
     * 	     <string>WebBrowser</string>
     * 	     <key>SourceVersion</key>
     * 	     <string>7536029013000000</string>
     * </dict>
     * </plist>
     */
    File f = new File(versionFile);
    return f.readAsLines().then((content) {
      bool versionOnNextLine = false;
      for (var line in content) {
        if (versionOnNextLine) return line;
        if (line.contains("CFBundleShortVersionString")) {
          versionOnNextLine = true;
        }
      }
      return null;
    });
  }

  void _createLaunchHTML(var path, var url) {
    var file = new File("${path}/launch.html");
    var randomFile = file.openSync(mode: FileMode.WRITE);
    var content = '<script language="JavaScript">location = "$url"</script>';
    randomFile.writeStringSync(content);
    randomFile.close();
  }

  Future<bool> start(String url) {
    _logEvent("Starting Safari browser on: $url");
    return allowPopUps().then((success) {
      if (!success) {
        return false;
      }
      return clearCache().then((cleared) {
        if (!cleared) {
          _logEvent("Could not clear cache");
          return false;
        }
        // Get the version and log that.
        return getVersion().then((version) {
          _logEvent("Got version: $version");
          return Directory.systemTemp.createTemp().then((userDir) {
            _cleanup = () { userDir.deleteSync(recursive: true); };
            _createLaunchHTML(userDir.path, url);
            var args = ["${userDir.path}/launch.html"];
            return startBrowser(_binary, args);
          });
        }).catchError((error) {
          _logEvent("Running $_binary --version failed with $error");
          return false;
        });
      });
    });
  }

  String toString() => "Safari";
}


class Chrome extends Browser {
  String _version = "Version not found yet";

  Map<String, String> _getEnvironment() => null;

  Future<bool> _getVersion() {
    if (Platform.isWindows) {
      // The version flag does not work on windows.
      // See issue:
      // https://code.google.com/p/chromium/issues/detail?id=158372
      // The registry hack does not seem to work.
      _version = "Can't get version on windows";
      // We still validate that the binary exists so that we can give good
      // feedback.
      return new File(_binary).exists().then((exists) {
        if (!exists) {
          _logEvent("Chrome binary not available.");
          _logEvent("Make sure $_binary is a valid program for running chrome");
        }
        return exists;
      });
    }
    return Process.run(_binary, ["--version"]).then((var versionResult) {
      if (versionResult.exitCode != 0) {
        _logEvent("Failed to chrome get version");
        _logEvent("Make sure $_binary is a valid program for running chrome");
        return false;
      }
      _version = versionResult.stdout;
      return true;
    });
  }


  Future<bool> start(String url) {
    _logEvent("Starting chrome browser on: $url");
    // Get the version and log that.
    return _getVersion().then((success) {
      if (!success) return false;
      _logEvent("Got version: $_version");

      return Directory.systemTemp.createTemp().then((userDir) {
        _cleanup = () { userDir.deleteSync(recursive: true); };
        var args = ["--user-data-dir=${userDir.path}", url,
                    "--disable-extensions", "--disable-popup-blocking",
                    "--bwsi", "--no-first-run"];
        return startBrowser(_binary, args, environment: _getEnvironment());
      });
    }).catchError((e) {
      _logEvent("Running $_binary --version failed with $e");
      return false;
    });
  }

  String toString() => "Chrome";
}


class SafariMobileSimulator extends Safari {
  /**
   * Directories where safari simulator stores state. We delete these if the
   * deleteCache is set
   */
  static const List<String> CACHE_DIRECTORIES =
      const ["Library/Application Support/iPhone Simulator/7.1/Applications"];

  // Clears the cache if the static deleteCache flag is set.
  // Returns false if the command to actually clear the cache did not complete.
  Future<bool> clearCache() {
    if (!Browser.deleteCache) return new Future.value(true);
    var home = Platform.environment['HOME'];
    Iterator iterator = CACHE_DIRECTORIES.map((s) => "$home/$s").iterator;
    return deleteIfExists(iterator);
  }

  Future<bool> start(String url) {
    _logEvent("Starting safari mobile simulator browser on: $url");
    return clearCache().then((success) {
      if (!success) {
        _logEvent("Could not clear cache, exiting");
	return false;
      }
      var args = ["-SimulateApplication",
                  "/Applications/Xcode.app/Contents/Developer/Platforms/"
                  "iPhoneSimulator.platform/Developer/SDKs/"
                  "iPhoneSimulator7.1.sdk/Applications/MobileSafari.app/"
                  "MobileSafari",
                  "-u", url];
      return startBrowser(_binary, args)
        .catchError((e) {
          _logEvent("Running $_binary --version failed with $e");
          return false;
        });
    });
  }

  String toString() => "SafariMobileSimulator";
}


class Dartium extends Chrome {
  final bool checkedMode;

  Dartium(this.checkedMode);

  Map<String, String> _getEnvironment() {
    var environment = new Map<String,String>.from(Platform.environment);
    // By setting this environment variable, dartium will forward "print()"
    // calls in dart to the top-level javascript function "dartPrint()" if
    // available.
    environment['DART_FORWARDING_PRINT'] = '1';
    if (checkedMode) {
      environment['DART_FLAGS'] = '--checked';
    }
    return environment;
  }

  String toString() => "Dartium";
}

class IE extends Browser {
  Future<String> getVersion() {
    var args = ["query",
                "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Internet Explorer",
                "/v",
                "svcVersion"];
    return Process.run("reg", args).then((result) {
      if (result.exitCode == 0) {
        // The string we get back looks like this:
        // HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer
        //    version    REG_SZ    9.0.8112.16421
        var findString = "REG_SZ";
        var index = result.stdout.indexOf(findString);
        if (index > 0) {
          return result.stdout.substring(index + findString.length).trim();
        }
      }
      return "Could not get the version of internet explorer";
    });
  }

  // Clears the recovery cache if the static deleteCache flag is set.
  Future<bool> clearCache() {
    if (!Browser.deleteCache) return new Future.value(true);
    var localAppData = Platform.environment['LOCALAPPDATA'];

    Directory dir = new Directory("$localAppData\\Microsoft\\"
                                  "Internet Explorer\\Recovery");
    return dir.delete(recursive: true)
      .then((_) { return true; })
      .catchError((error) {
        _logEvent("Deleting recovery dir failed with $error");
        return false;
      });
  }

  Future<bool> start(String url) {
    _logEvent("Starting ie browser on: $url");
    return clearCache().then((_) => getVersion()).then((version) {
      _logEvent("Got version: $version");
      return startBrowser(_binary, [url]);
    });
  }
  String toString() => "IE";

}


class AndroidBrowserConfig {
  final String name;
  final String package;
  final String activity;
  final String action;
  AndroidBrowserConfig(this.name, this.package, this.activity, this.action);
}


final contentShellOnAndroidConfig = new AndroidBrowserConfig(
    'ContentShellOnAndroid',
    'org.chromium.content_shell_apk',
    '.ContentShellActivity',
    'android.intent.action.VIEW');


final dartiumOnAndroidConfig = new AndroidBrowserConfig(
    'DartiumOnAndroid',
    'com.google.android.apps.chrome',
    '.Main',
    'android.intent.action.VIEW');


class AndroidBrowser extends Browser {
  final bool checkedMode;
  AdbDevice _adbDevice;
  AndroidBrowserConfig _config;

  AndroidBrowser(this._adbDevice, this._config, this.checkedMode);

  Future<bool> start(String url) {
    var intent = new Intent(
        _config.action, _config.package, _config.activity, url);
    return _adbDevice.waitForBootCompleted().then((_) {
      return _adbDevice.forceStop(_config.package);
    }).then((_) {
      return _adbDevice.killAll();
    }).then((_) {
      return _adbDevice.adbRoot();
    }).then((_) {
      return _adbDevice.setProp("DART_FORWARDING_PRINT", "1");
    }).then((_) {
      if (checkedMode) {
        return _adbDevice.setProp("DART_FLAGS", "--checked");
      } else {
        return _adbDevice.setProp("DART_FLAGS", "");
      }
    }).then((_) {
      return _adbDevice.startActivity(intent).then((_) => true);
    });
  }

  Future<bool> close() {
    if (_adbDevice != null) {
      return _adbDevice.forceStop(_config.package).then((_) {
        return _adbDevice.killAll().then((_) => true);
      });
    }
    return new Future.value(true);
  }

  String toString() => _config.name;
}


class AndroidChrome extends Browser {
  static const String viewAction = 'android.intent.action.VIEW';
  static const String mainAction = 'android.intent.action.MAIN';
  static const String chromePackage = 'com.android.chrome';
  static const String browserPackage = 'com.android.browser';
  static const String firefoxPackage = 'org.mozilla.firefox';
  static const String turnScreenOnPackage = 'com.google.dart.turnscreenon';

  AndroidEmulator _emulator;
  AdbDevice _adbDevice;

  AndroidChrome(this._adbDevice);

  Future<bool> start(String url) {
    var browserIntent = new Intent(
        viewAction, browserPackage, '.BrowserActivity', url);
    var chromeIntent = new Intent(viewAction, chromePackage, '.Main', url);
    var firefoxIntent = new Intent(viewAction, firefoxPackage, '.App', url);
    var turnScreenOnIntent =
        new Intent(mainAction, turnScreenOnPackage, '.Main');

    var testing_resources_dir =
        new Path('third_party/android_testing_resources');
    if (!new Directory(testing_resources_dir.toNativePath()).existsSync()) {
      DebugLogger.error("$testing_resources_dir doesn't exist. Exiting now.");
      exit(1);
    }

    var chromeAPK = testing_resources_dir.append('com.android.chrome-1.apk');
    var turnScreenOnAPK = testing_resources_dir.append('TurnScreenOn.apk');
    var chromeConfDir = testing_resources_dir.append('chrome_configuration');
    var chromeConfDirRemote = new Path('/data/user/0/com.android.chrome/');

    return _adbDevice.waitForBootCompleted().then((_) {
      return _adbDevice.forceStop(chromeIntent.package);
    }).then((_) {
      return _adbDevice.killAll();
    }).then((_) {
      return _adbDevice.adbRoot();
    }).then((_) {
      return _adbDevice.installApk(turnScreenOnAPK);
    }).then((_) {
      return _adbDevice.installApk(chromeAPK);
    }).then((_) {
      return _adbDevice.pushData(chromeConfDir, chromeConfDirRemote);
    }).then((_) {
      return _adbDevice.chmod('777', chromeConfDirRemote);
    }).then((_) {
      return _adbDevice.startActivity(turnScreenOnIntent).then((_) => true);
    }).then((_) {
      return _adbDevice.startActivity(chromeIntent).then((_) => true);
    });
  }

  Future<bool> close() {
    if (_adbDevice != null) {
      return _adbDevice.forceStop(chromePackage).then((_) {
        return _adbDevice.killAll().then((_) => true);
      });
    }
    return new Future.value(true);
  }

  String toString() => "chromeOnAndroid";
}


class Firefox extends Browser {
  static const String enablePopUp =
      'user_pref("dom.disable_open_during_load", false);';
  static const String disableDefaultCheck =
      'user_pref("browser.shell.checkDefaultBrowser", false);';
  static const String disableScriptTimeLimit =
      'user_pref("dom.max_script_run_time", 0);';

  void _createPreferenceFile(var path) {
    var file = new File("${path.toString()}/user.js");
    var randomFile = file.openSync(mode: FileMode.WRITE);
    randomFile.writeStringSync(enablePopUp);
    randomFile.writeStringSync(disableDefaultCheck);
    randomFile.writeStringSync(disableScriptTimeLimit);
    randomFile.close();
  }

  Future<bool> start(String url) {
    _logEvent("Starting firefox browser on: $url");
    // Get the version and log that.
    return Process.run(_binary, ["--version"]).then((var versionResult) {
      if (versionResult.exitCode != 0) {
        _logEvent("Failed to firefox get version");
        _logEvent("Make sure $_binary is a valid program for running firefox");
        return new Future.value(false);
      }
      version = versionResult.stdout;
      _logEvent("Got version: $version");

      return Directory.systemTemp.createTemp().then((userDir) {
        _createPreferenceFile(userDir.path);
        _cleanup = () { userDir.deleteSync(recursive: true); };
        var args = ["-profile", "${userDir.path}",
                    "-no-remote", "-new-instance", url];
        return startBrowser(_binary, args);

      });
    }).catchError((e) {
      _logEvent("Running $_binary --version failed with $e");
      return false;
    });
  }

  String toString() => "Firefox";
}


/**
 * Describes the current state of a browser used for testing.
 */
class BrowserTestingStatus {
  Browser browser;
  BrowserTest currentTest;

  // This is currently not used for anything except for error reporting.
  // Given the usefulness of this in debugging issues this should not be
  // removed even when we have really stable system.
  BrowserTest lastTest;
  bool timeout = false;
  Timer nextTestTimeout;

  BrowserTestingStatus(Browser this.browser);
}


/**
 * Describes a single test to be run int the browser.
 */
class BrowserTest {
  // TODO(ricow): Add timeout callback instead of the string passing hack.
  Function doneCallback;
  String url;
  int timeout;
  String lastKnownMessage = '';
  Stopwatch stopwatch;

  // This might be null
  Duration delayUntilTestStarted;

  // We store this here for easy access when tests time out (instead of
  // capturing this in a closure)
  Timer timeoutTimer;

  // Used for debugging, this is simply a unique identifier assigned to each
  // test.
  int id;
  static int _idCounter = 0;

  BrowserTest(this.url, this.doneCallback, this.timeout) {
    id = _idCounter++;
  }
}

/* Describes the output of running the test in a browser */
class BrowserTestOutput {
  final Duration delayUntilTestStarted;
  final Duration duration;

  final String lastKnownMessage;

  final BrowserOutput browserOutput;
  final bool didTimeout;

  BrowserTestOutput(
      this.delayUntilTestStarted, this.duration, this.lastKnownMessage,
      this.browserOutput, {this.didTimeout: false});
}

/**
 * Encapsulates all the functionality for running tests in browsers.
 * The interface is rather simple. After starting, the runner tests
 * are simply added to the queue and a the supplied callbacks are called
 * whenever a test completes.
 */
class BrowserTestRunner {
  static const int MAX_NEXT_TEST_TIMEOUTS = 10;
  static const Duration NEXT_TEST_TIMEOUT = const Duration(seconds: 60);

  final Map globalConfiguration;
  final bool checkedMode; // needed for dartium

  String localIp;
  String browserName;
  int maxNumBrowsers;
  // Used to send back logs from the browser (start, stop etc)
  Function logger;
  int browserIdCount = 0;

  bool underTermination = false;
  int numBrowserGetTestTimeouts = 0;

  List<BrowserTest> testQueue = new List<BrowserTest>();
  Map<String, BrowserTestingStatus> browserStatus =
      new Map<String, BrowserTestingStatus>();

  var adbDeviceMapping = new Map<String, AdbDevice>();
  // This cache is used to guarantee that we never see double reporting.
  // If we do we need to provide developers with this information.
  // We don't add urls to the cache until we have run it.
  Map<int, String> testCache = new Map<int, String>();
  Map<int, String> doubleReportingOutputs = new Map<int, String>();

  BrowserTestingServer testingServer;

  /**
   * The TestRunner takes the testingServer in as a constructor parameter in
   * case we wish to have a testing server with different behavior (such as the
   * case for performance testing.
   */
  BrowserTestRunner(this.globalConfiguration,
                    this.localIp,
                    this.browserName,
                    this.maxNumBrowsers,
                    {bool this.checkedMode: false,
                    BrowserTestingServer this.testingServer});

  Future<bool> start() {
    // If [browserName] doesn't support opening new windows, we use new iframes
    // instead.
    bool useIframe =
        !Browser.BROWSERS_WITH_WINDOW_SUPPORT.contains(browserName);
    if (testingServer == null) {
      testingServer = new BrowserTestingServer(
          globalConfiguration, localIp, useIframe);
    }
    return testingServer.start().then((_) {
      testingServer.testDoneCallBack = handleResults;
      testingServer.testStatusUpdateCallBack = handleStatusUpdate;
      testingServer.testStartedCallBack = handleStarted;
      testingServer.nextTestCallBack = getNextTest;
      return getBrowsers().then((browsers) {
        var futures = [];
        for (var browser in browsers) {
          var url = testingServer.getDriverUrl(browser.id);
          var future = browser.start(url).then((success) {
            if (success) {
              var status = new BrowserTestingStatus(browser);
              browserStatus[browser.id] = status;
              status.nextTestTimeout = createNextTestTimer(status);
            }
            return success;
          });
          futures.add(future);
        }
        return Future.wait(futures).then((values) {
          return !values.contains(false);
        });
      });
    });
  }

  Future<List<Browser>> getBrowsers() {
    // TODO(kustermann): This is a hackisch way to accomplish it and should
    // be encapsulated
    var browsersCompleter = new Completer();
    var androidBrowserCreationMapping = {
      'chromeOnAndroid' : (AdbDevice device) => new AndroidChrome(device),
      'ContentShellOnAndroid' : (AdbDevice device) =>
          new AndroidBrowser(device, contentShellOnAndroidConfig, checkedMode),
      'DartiumOnAndroid' : (AdbDevice device) =>
          new AndroidBrowser(device, dartiumOnAndroidConfig, checkedMode),
    };
    if (androidBrowserCreationMapping.containsKey(browserName)) {
      AdbHelper.listDevices().then((deviceIds) {
        if (deviceIds.length > 0) {
          var browsers = [];
          for (int i = 0; i < deviceIds.length; i++) {
            var id = "BROWSER$i";
            var device = new AdbDevice(deviceIds[i]);
            adbDeviceMapping[id] = device;
            var browser = androidBrowserCreationMapping[browserName](device);
            browsers.add(browser);
            // We store this in case we need to kill the browser.
            browser.id = id;
          }
          browsersCompleter.complete(browsers);
        } else {
          throw new StateError("No android devices found.");
        }
      });
    } else {
      var browsers = [];
      for (int i = 0; i < maxNumBrowsers; i++) {
        var id = "BROWSER$browserIdCount";
        browserIdCount++;
        var browser = getInstance();
        browsers.add(browser);
        // We store this in case we need to kill the browser.
        browser.id = id;
      }
      browsersCompleter.complete(browsers);
    }
    return browsersCompleter.future;
  }

  var timedOut = [];

  void handleResults(String browserId, String output, int testId) {
    var status = browserStatus[browserId];
    if (testCache.containsKey(testId)) {
      doubleReportingOutputs[testId] = output;
      return;
    }

    if (status == null || status.timeout) {
      // We don't do anything, this browser is currently being killed and
      // replaced. The browser here can be null if we decided to kill the
      // browser.
    } else if (status.currentTest != null) {
      status.currentTest.timeoutTimer.cancel();
      status.currentTest.stopwatch.stop();

      if (status.currentTest.id != testId) {
        print("Expected test id ${status.currentTest.id} for"
              "${status.currentTest.url}");
        print("Got test id ${testId}");
        print("Last test id was ${status.lastTest.id} for "
              "${status.currentTest.url}");
        throw("This should never happen, wrong test id");
      }
      testCache[testId] = status.currentTest.url;

      // Report that the test is finished now
      var browserTestOutput = new BrowserTestOutput(
          status.currentTest.delayUntilTestStarted,
          status.currentTest.stopwatch.elapsed,
          output,
          status.browser.testBrowserOutput);
      status.currentTest.doneCallback(browserTestOutput);

      status.lastTest = status.currentTest;
      status.currentTest = null;
      status.nextTestTimeout = createNextTestTimer(status);
    } else {
      print("\nThis is bad, should never happen, handleResult no test");
      print("URL: ${status.lastTest.url}");
      print(output);
      terminate().then((_) {
        exit(1);
      });
    }
  }

  void handleStatusUpdate(String browserId, String output, int testId) {
    var status = browserStatus[browserId];

    if (status == null || status.timeout) {
      // We don't do anything, this browser is currently being killed and
      // replaced. The browser here can be null if we decided to kill the
      // browser.
    } else if (status.currentTest != null && status.currentTest.id == testId) {
      status.currentTest.lastKnownMessage = output;
    }
  }

  void handleStarted(String browserId, String output, int testId) {
    var status = browserStatus[browserId];

    if (status != null && !status.timeout && status.currentTest != null) {
      status.currentTest.timeoutTimer.cancel();
      status.currentTest.timeoutTimer =
          createTimeoutTimer(status.currentTest, status);
      status.currentTest.delayUntilTestStarted =
          status.currentTest.stopwatch.elapsed;
    }
  }

  void handleTimeout(BrowserTestingStatus status) {
    // We simply kill the browser and starts up a new one!
    // We could be smarter here, but it does not seems like it is worth it.
    status.timeout = true;
    timedOut.add(status.currentTest.url);
    var id = status.browser.id;

    status.currentTest.stopwatch.stop();
    status.browser.close().then((_) {
      var lastKnownMessage =
          'Dom could not be fetched, since the test timed out.';
      if (status.currentTest.lastKnownMessage.length > 0) {
        lastKnownMessage = status.currentTest.lastKnownMessage;
      }
      // Wait until the browser is closed before reporting the test as timeout.
      // This will enable us to capture stdout/stderr from the browser
      // (which might provide us with information about what went wrong).
      var browserTestOutput = new BrowserTestOutput(
          status.currentTest.delayUntilTestStarted,
          status.currentTest.stopwatch.elapsed,
          lastKnownMessage,
          status.browser.testBrowserOutput,
          didTimeout: true);
      status.currentTest.doneCallback(browserTestOutput);
      status.currentTest = null;

      // We don't want to start a new browser if we are terminating.
      if (underTermination) return;
      restartBrowser(id);
    });
  }

  void restartBrowser(String id) {
    var browser;
    var new_id = id;
    if (browserName == 'chromeOnAndroid') {
      browser = new AndroidChrome(adbDeviceMapping[id]);
    } else if (browserName == 'ContentShellOnAndroid') {
      browser = new AndroidBrowser(adbDeviceMapping[id],
                                   contentShellOnAndroidConfig,
                                   checkedMode);
    } else if (browserName == 'DartiumOnAndroid') {
      browser = new AndroidBrowser(adbDeviceMapping[id],
                                   dartiumOnAndroidConfig,
                                   checkedMode);
    } else {
      browserStatus.remove(id);
      browser = getInstance();
      new_id = "BROWSER$browserIdCount";
      browserIdCount++;
    }
    browser.id = new_id;
    var status = new BrowserTestingStatus(browser);
    browserStatus[new_id] = status;
    status.nextTestTimeout = createNextTestTimer(status);
    browser.start(testingServer.getDriverUrl(new_id)).then((success) {
      // We may have started terminating in the mean time.
      if (underTermination) {
        if (status.nextTestTimeout != null) {
          status.nextTestTimeout.cancel();
          status.nextTestTimeout = null;
        }
        browser.close().then((success) {
         // We should never hit this, print it out.
          if (!success) {
            print("Could not kill browser ($id) started due to timeout");
          }
        });
        return;
      }
      if (!success) {
        // TODO(ricow): Handle this better.
        print("This is bad, should never happen, could not start browser");
        exit(1);
      }
    });
  }

  BrowserTest getNextTest(String browserId) {
    var status = browserStatus[browserId];
    if (status == null) return null;
    if (status.nextTestTimeout != null) {
      status.nextTestTimeout.cancel();
      status.nextTestTimeout = null;
    }
    if (testQueue.isEmpty) return null;

    // We are currently terminating this browser, don't start a new test.
    if (status.timeout) return null;

    BrowserTest test = testQueue.removeLast();
    if (status.currentTest == null) {
      status.currentTest = test;
      status.currentTest.lastKnownMessage = '';
    } else {
      // TODO(ricow): Handle this better.
      print("This is bad, should never happen, getNextTest all full");
      print("This happened for browser $browserId");
      print("Old test was: ${status.currentTest.url}");
      print("Timed out tests:");
      for (var v in timedOut) {
        print("  $v");
      }
      exit(1);
    }

    status.currentTest.timeoutTimer = createTimeoutTimer(test, status);
    status.currentTest.stopwatch = new Stopwatch()..start();

    // Reset the test specific output information (stdout, stderr) on the
    // browser since a new test is begin started.
    status.browser.resetTestBrowserOutput();

    return test;
  }

  Timer createTimeoutTimer(BrowserTest test, BrowserTestingStatus status) {
    return new Timer(new Duration(seconds: test.timeout),
                     () { handleTimeout(status); });
  }

  Timer createNextTestTimer(BrowserTestingStatus status) {
    return new Timer(BrowserTestRunner.NEXT_TEST_TIMEOUT,
                     () { handleNextTestTimeout(status); });
  }

  void handleNextTestTimeout(status) {
    DebugLogger.warning(
        "Browser timed out before getting next test. Restarting");
    numBrowserGetTestTimeouts++;
    if (numBrowserGetTestTimeouts >= MAX_NEXT_TEST_TIMEOUTS) {
      DebugLogger.error(
          "Too many browser timeouts before getting next test. Terminating");
      terminate().then((_) => exit(1));
    } else {
      status.browser.close().then((_) => restartBrowser(status.browser.id));
    }
  }

  void queueTest(BrowserTest test) {
    testQueue.add(test);
  }

  void printDoubleReportingTests() {
    if (doubleReportingOutputs.length == 0) return;
    // TODO(ricow): die on double reporting.
    // Currently we just report this here, we could have a callback to the
    // encapsulating environment.
    print("");
    print("Double reporting tests");
    for (var id in doubleReportingOutputs.keys) {
      print("  ${testCache[id]}");
    }

    DebugLogger.warning("Double reporting tests:");
    for (var id in doubleReportingOutputs.keys) {
      DebugLogger.warning("${testCache[id]}, output: ");
      DebugLogger.warning("${doubleReportingOutputs[id]}");
      DebugLogger.warning("");
      DebugLogger.warning("");
    }
  }

  Future<bool> terminate() {
    var futures = [];
    underTermination = true;
    testingServer.underTermination = true;
    for (BrowserTestingStatus status in browserStatus.values) {
      futures.add(status.browser.close());
      if (status.nextTestTimeout != null) {
        status.nextTestTimeout.cancel();
        status.nextTestTimeout = null;
      }
    }
    return Future.wait(futures).then((values) {
      testingServer.httpServer.close();
      testingServer.errorReportingServer.close();
      printDoubleReportingTests();
      return !values.contains(false);
    });
  }

  Browser getInstance() {
    if (browserName == 'ff') browserName = 'firefox';
    var path = Locations.getBrowserLocation(browserName, globalConfiguration);
    var browser = new Browser.byName(browserName, path, checkedMode);
    browser.logger = logger;
    return browser;
  }
}

class BrowserTestingServer {
  final Map globalConfiguration;
  /// Interface of the testing server:
  ///
  /// GET /driver/BROWSER_ID -- This will get the driver page to fetch
  ///                           and run tests ...
  /// GET /next_test/BROWSER_ID -- returns "WAIT" "TERMINATE" or "url#id"
  /// where url is the test to run, and id is the id of the test.
  /// If there are currently no available tests the waitSignal is send
  /// back. If we are in the process of terminating the terminateSignal
  /// is send back and the browser will stop requesting new tasks.
  /// POST /report/BROWSER_ID?id=NUM -- sends back the dom of the executed
  ///                                   test

  final String localIp;

  static const String driverPath = "/driver";
  static const String nextTestPath = "/next_test";
  static const String reportPath = "/report";
  static const String statusUpdatePath = "/status_update";
  static const String startedPath = "/started";
  static const String waitSignal = "WAIT";
  static const String terminateSignal = "TERMINATE";

  var testCount = 0;
  var httpServer;
  var errorReportingServer;
  bool underTermination = false;
  bool useIframe = false;

  Function testDoneCallBack;
  Function testStatusUpdateCallBack;
  Function testStartedCallBack;
  Function nextTestCallBack;

  BrowserTestingServer(this.globalConfiguration, this.localIp, this.useIframe);

  Future start() {
    int port = globalConfiguration['test_driver_port'];
    return HttpServer.bind(localIp, port).then((createdServer) {
      httpServer = createdServer;
      void handler(HttpRequest request) {
        // Don't allow caching of resources from the browser controller, i.e.,
        // we don't want the browser to cache the result of getNextTest.
        request.response.headers.set("Cache-Control",
                                     "no-cache, no-store, must-revalidate");
        bool isReport = request.uri.path.startsWith(reportPath);
        bool isStatusUpdate = request.uri.path.startsWith(statusUpdatePath);
        if (isReport || isStatusUpdate) {
          var browserId;
          if (isStatusUpdate) {
            browserId = request.uri.path.substring(statusUpdatePath.length + 1);
          } else {
            browserId = request.uri.path.substring(reportPath.length + 1);
          }
          var testId =
              int.parse(request.uri.queryParameters["id"].split("=")[1]);
          handleReport(
              request, browserId, testId, isStatusUpdate: isStatusUpdate);
          // handleReport will asynchroniously fetch the data and will handle
          // the closing of the streams.
          return;
        }
        if (request.uri.path.startsWith(startedPath)) {
          var browserId = request.uri.path.substring(startedPath.length + 1);
          var testId =
              int.parse(request.uri.queryParameters["id"].split("=")[1]);
          handleStarted(request, browserId, testId);
          return;
        }
        var textResponse = "";
        if (request.uri.path.startsWith(driverPath)) {
          var browserId = request.uri.path.substring(driverPath.length + 1);
          textResponse = getDriverPage(browserId);
        } else if (request.uri.path.startsWith(nextTestPath)) {
          var browserId = request.uri.path.substring(nextTestPath.length + 1);
          textResponse = getNextTest(browserId);
        } else {
          // /favicon.ico requests
        }
        request.response.write(textResponse);
        request.listen((_) {}, onDone: request.response.close);
        request.response.done.catchError((error) {
          if (!underTermination) {
            print("URI ${request.uri}");
            print("Textresponse $textResponse");
            throw "Error returning content to browser: $error";
          }
        });
      }
      void errorHandler(e) {
        if (!underTermination) print("Error occured in httpserver: $e");
      };

      httpServer.listen(handler, onError: errorHandler);

      // Set up the error reporting server that enables us to send back
      // errors from the browser.
      port = globalConfiguration['test_driver_error_port'];
      return HttpServer.bind(localIp, port).then((createdReportServer) {
        errorReportingServer = createdReportServer;
        void errorReportingHandler(HttpRequest request) {
          StringBuffer buffer = new StringBuffer();
          request.transform(UTF8.decoder).listen((data) {
            buffer.write(data);
          }, onDone: () {
              String back = buffer.toString();
              request.response.headers.set("Access-Control-Allow-Origin", "*");
              request.response.done.catchError((error) {
                DebugLogger.error("Error getting error from browser"
                                  "on uri ${request.uri.path}: $error");
              });
              request.response.close();
              DebugLogger.error("Error from browser on : "
                               "${request.uri.path}, data:  $back");
          }, onError: (error) { print(error); });
        }
        errorReportingServer.listen(errorReportingHandler,
                                    onError: errorHandler);
        return true;
      });
    });
  }

  void handleReport(HttpRequest request, String browserId, var testId,
                    {bool isStatusUpdate}) {
    StringBuffer buffer = new StringBuffer();
    request.transform(UTF8.decoder).listen((data) {
      buffer.write(data);
    }, onDone: () {
      String back = buffer.toString();
      request.response.close();
      if (isStatusUpdate) {
        testStatusUpdateCallBack(browserId, back, testId);
      } else {
        testDoneCallBack(browserId, back, testId);
      }
      // TODO(ricow): We should do something smart if we get an error here.
    }, onError: (error) { DebugLogger.error("$error"); });
  }

  void handleStarted(HttpRequest request, String browserId, var testId) {
    StringBuffer buffer = new StringBuffer();
    // If an error occurs while receiving the data from the request stream,
    // we don't handle it specially. We can safely ignore it, since the started
    // events are not crucial.
    request.transform(UTF8.decoder).listen((data) {
      buffer.write(data);
    }, onDone: () {
      String back = buffer.toString();
      request.response.close();
      testStartedCallBack(browserId, back, testId);
    }, onError: (error) { DebugLogger.error("$error"); });
  }

  String getNextTest(String browserId) {
    var nextTest = nextTestCallBack(browserId);
    if (underTermination) {
      // Browsers will be killed shortly, send them a terminate signal so
      // that they stop pulling.
      return terminateSignal;
    } else if (nextTest == null) {
      // We don't currently have any tests ready for consumption, wait.
      return waitSignal;
    } else {
      return "${nextTest.url}#id=${nextTest.id}";
    }
  }

  String getDriverUrl(String browserId) {
    if (httpServer == null) {
      print("Bad browser testing server, you are not started yet. Can't "
            "produce driver url");
      exit(1);
      // This should never happen - exit immediately;
    }
    return "http://$localIp:${httpServer.port}/driver/$browserId";
  }


  String getDriverPage(String browserId) {
    var errorReportingUrl =
        "http://$localIp:${errorReportingServer.port}/$browserId";
    String driverContent = """
<!DOCTYPE html><html>
<head>
  <title>Driving page</title>
  <script type='text/javascript'>
    function startTesting() {
      var number_of_tests = 0;
      var current_id;
      var next_id;
      // Describes a state where we are currently fetching the next test
      // from the server. We use this to never double request tasks.
      var test_completed = true;
      var testing_window;

      var embedded_iframe = document.getElementById('embedded_iframe');
      var number_div = document.getElementById('number');
      var executing_div = document.getElementById('currently_executing');
      var error_div = document.getElementById('unhandled_error');
      var use_iframe = ${useIframe};
      var start = new Date();

      function newTaskHandler() {
        if (this.readyState == this.DONE) {
          if (this.status == 200) {
            if (this.responseText == '$waitSignal') {
              setTimeout(getNextTask, 500);
            } else if (this.responseText == '$terminateSignal') {
              // Don't do anything, we will be killed shortly.
            } else {
              var elapsed = new Date() - start;
              // The task is send to us as:
              // URL#ID
              var split = this.responseText.split('#');
              var nextTask = split[0];
              next_id = split[1];
              run(nextTask);
            }
          } else {
            reportError('Could not contact the server and get a new task');
          }
        }
      }

      function contactBrowserController(method,
                                        path,
                                        callback,
                                        msg,
                                        isUrlEncoded) {
        var client = new XMLHttpRequest();
        client.onreadystatechange = callback;
        client.open(method, path);
        if (isUrlEncoded) {
          client.setRequestHeader('Content-type',
                                  'application/x-www-form-urlencoded');
        }
        client.send(msg);
      }

      function getNextTask() {
        // Until we have the next task we set the current_id to a specific
        // negative value.
        contactBrowserController(
            'GET', '$nextTestPath/$browserId', newTaskHandler, "", false);
      }

      function run(url) {
        number_of_tests++;
        number_div.innerHTML = number_of_tests;
        executing_div.innerHTML = url;
        if (use_iframe) {
          embedded_iframe.src = url;
        } else {
          if (typeof testing_window != 'undefined') {
            testing_window.close();
          }
          testing_window = window.open(url);
        }
      }

      window.onerror = function (message, url, lineNumber) {
        if (url) {
          reportError(url + ':' + lineNumber + ':' + message);
        } else {
          reportError(message);
        }
      }

      function reportError(msg) {
        function handleReady() {
          if (this.readyState == this.DONE && this.status != 200) {
            var error = 'Sending back error did not succeeed: ' + this.status;
            error = error + '. Failed to send msg: ' + msg;
            error_div.innerHTML = error;
          }
        }
        contactBrowserController(
            'POST', '$errorReportingUrl?test=1', handleReady, msg, true);
      }

      function reportMessage(msg, isFirstMessage, isStatusUpdate) {
        if (isFirstMessage) {
          test_completed = false;
          current_id = next_id;
          contactBrowserController(
            'POST', '$startedPath/${browserId}?id=' + current_id,
            function () {}, msg, true);
        } else if (isStatusUpdate) {
            contactBrowserController(
              'POST', '$statusUpdatePath/${browserId}?id=' + current_id,
              function() {}, msg, true);
        } else {
          var is_double_report = test_completed;
          var retry = 0;
          test_completed = true;

          function reportDoneMessage() {
            contactBrowserController(
                'POST', '$reportPath/${browserId}?id=' + current_id,
                handleReady, msg, true);
          }

          function handleReady() {
            if (this.readyState == this.DONE) {
              if (this.status == 200) {
                if (!is_double_report) {
                  getNextTask();
                }
              } else {
                reportError('Error sending result to server. Status: ' +
                            this.status + ' Retry: ' + retry);
                retry++;
                if (retry < 3) {
                  setTimeout(reportDoneMessage, 1000);
                }
              }
            }
          }

          reportDoneMessage();
        }
      }

      function parseResult(result) {
        var parsedData = null;
        try {
          parsedData = JSON.parse(result);
        } catch(error) { }
        return parsedData;
      }

      function messageHandler(e) {
        var msg = e.data;
        if (typeof msg != 'string') return;

        var parsedData = parseResult(msg);
        if (parsedData) {
          // Only if the JSON message contains all required parameters,
          // will we handle it and post it back to the test controller.
          if ('message' in parsedData &&
              'is_first_message' in parsedData &&
              'is_status_update' in parsedData &&
              'is_done' in parsedData) {
            var message = parsedData['message'];
            var isFirstMessage = parsedData['is_first_message'];
            var isStatusUpdate = parsedData['is_status_update'];
            var isDone = parsedData['is_done'];
            if (!isFirstMessage && !isStatusUpdate) {
              if (!isDone) {
                alert("Bug in test_controller.js: " +
                      "isFirstMessage/isStatusUpdate/isDone were all false");
              }
            }
            reportMessage(message, isFirstMessage, isStatusUpdate);
          }
        }
      }

      window.addEventListener('message', messageHandler, false);
      waitForDone = false;

      getNextTask();
    }

  </script>
</head>
  <body onload="startTesting()">
    Dart test driver, number of tests: <div id="number"></div><br>
    Currently executing: <div id="currently_executing"></div><br>
    Unhandled error: <div id="unhandled_error"></div>
    <iframe id="embedded_iframe"></iframe>
  </body>
</html>
""";
    return driverContent;
  }
}
