<!DOCTYPE html>

<html>

  <head>
    <meta charset="utf8">
    <title></title>

    <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
    <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
    <script type="application/javascript;version=1.8" src="head.js"></script>
    <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
  </head>

  <body>

    <script type="application/javascript;version=1.8">
      window.onload = function() {
        SimpleTest.waitForExplicitFinish();

        let win;

        SimpleTest.registerCleanupFunction(() => {
          Task.spawn(function*() {
            if (win) {
              yield closeWebIDE(win);
            }
            DebuggerServer.destroy();
            yield removeAllProjects();
          });
        });

        Task.spawn(function*() {
          function isPlayActive() {
            return !win.document.querySelector("#cmd_play").hasAttribute("disabled");
          }

          function isStopActive() {
            return !win.document.querySelector("#cmd_stop").hasAttribute("disabled");
          }

          if (!DebuggerServer.initialized) {
            DebuggerServer.init();
            DebuggerServer.addBrowserActors();
          }

          win = yield openWebIDE();
          let docRuntime = getRuntimeDocument(win);
          let docProject = getProjectDocument(win);
          let winProject = getProjectWindow(win);

          let packagedAppLocation = getTestFilePath("app");

          let onValidated = waitForUpdate(win, "project-validated");
          let onDetails = waitForUpdate(win, "details");
          yield winProject.projectList.importPackagedApp(packagedAppLocation);
          yield onValidated;
          yield onDetails;

          win.AppManager.runtimeList.usb.push({
            connect: function(connection) {
              is(connection, win.AppManager.connection, "connection is valid");
              connection.host = null; // force connectPipe
              connection.connect();
              return promise.resolve();
            },

            get name() {
              return "fakeRuntime";
            }
          });

          win.AppManager.runtimeList.usb.push({
            connect: function(connection) {
              let deferred = promise.defer();
              return deferred.promise;
            },

            get name() {
              return "infiniteRuntime";
            }
          });

          win.AppManager.runtimeList.usb.push({
            connect: function(connection) {
              let deferred = promise.defer();
              return deferred.promise;
            },

            prolongedConnection: true,

            get name() {
              return "prolongedRuntime";
            }
          });

          win.AppManager.update("runtime-list");

          let panelNode = docRuntime.querySelector("#runtime-panel");
          let items = panelNode.querySelectorAll(".runtime-panel-item-usb");
          is(items.length, 3, "Found 3 runtime buttons");

          let connectionsChanged = waitForConnectionChange("opened", 2);
          items[0].click();

          ok(win.document.querySelector("window").className, "busy", "UI is busy");
          yield win.UI._busyPromise;

          yield connectionsChanged;
          is(Object.keys(DebuggerServer._connections).length, 2, "Connected");

          yield waitForUpdate(win, "runtime-global-actors");

          // Play button always disabled now, webapps actor removed
          ok(!isPlayActive(), "play button is disabled");
          ok(!isStopActive(), "stop button is disabled");
          let oldProject = win.AppManager.selectedProject;
          win.AppManager.selectedProject = null;

          yield nextTick();

          ok(!isPlayActive(), "play button is disabled");
          ok(!isStopActive(), "stop button is disabled");
          win.AppManager._selectedProject = oldProject;
          win.UI.updateCommands();

          yield nextTick();

          ok(!isPlayActive(), "play button is enabled");
          ok(!isStopActive(), "stop button is disabled");

          connectionsChanged = waitForConnectionChange("closed", 2);
          yield win.Cmds.disconnectRuntime();

          yield connectionsChanged;
          is(Object.keys(DebuggerServer._connections).length, 0, "Disconnected");

          ok(win.AppManager.selectedProject, "A project is still selected");
          ok(!isPlayActive(), "play button is disabled");
          ok(!isStopActive(), "stop button is disabled");

          connectionsChanged = waitForConnectionChange("opened", 2);
          docRuntime.querySelectorAll(".runtime-panel-item-other")[1].click();

          yield waitForUpdate(win, "runtime-targets");

          yield connectionsChanged;
          is(Object.keys(DebuggerServer._connections).length, 2, "Locally connected");

          ok(win.AppManager.isMainProcessDebuggable(), "Main process available");

          // Select main process
          SimpleTest.executeSoon(() => {
            docProject.querySelectorAll("#project-panel-runtimeapps .panel-item")[0].click();
          });

          yield waitForUpdate(win, "project");

          // Toolbox opens automatically for main process / runtime apps
          ok(win.UI.toolboxPromise, "Toolbox promise exists");
          yield win.UI.toolboxPromise;

          yield win.Cmds.disconnectRuntime();

          Services.prefs.setIntPref("devtools.webide.busyTimeout", 100);

          // Wait for error message since connection never completes
          let errorDeferred = promise.defer();
          win.UI.reportError = errorName => {
            if (errorName === "error_operationTimeout") {
              errorDeferred.resolve();
            }
          };

          // Click the infinite runtime
          items[1].click();
          ok(win.document.querySelector("window").className, "busy", "UI is busy");
          yield errorDeferred.promise;

          // Check for unexpected error message since this is prolonged
          let noErrorDeferred = promise.defer();
          win.UI.reportError = errorName => {
            if (errorName === "error_operationTimeout") {
              noErrorDeferred.reject();
            }
          };

          // Click the prolonged runtime
          items[2].click();
          ok(win.document.querySelector("window").className, "busy", "UI is busy");

          setTimeout(() => {
            noErrorDeferred.resolve();
          }, 1000);

          yield noErrorDeferred.promise;

          SimpleTest.finish();
        });
      }
    </script>
  </body>
</html>