/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

const Cu = Components.utils;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});

let gClient;
let gConnectionTimeout;

XPCOMUtils.defineLazyGetter(window, 'l10n', function () {
  return Services.strings.createBundle('chrome://browser/locale/devtools/connection-screen.properties');
});

/**
 * Once DOM is ready, we prefil the host/port inputs with
 * pref-stored values.
 */
window.addEventListener("DOMContentLoaded", function onDOMReady() {
  window.removeEventListener("DOMContentLoaded", onDOMReady, true);
  let host = Services.prefs.getCharPref("devtools.debugger.remote-host");
  let port = Services.prefs.getIntPref("devtools.debugger.remote-port");

  if (host) {
    document.getElementById("host").value = host;
  }

  if (port) {
    document.getElementById("port").value = port;
  }

}, true);

/**
 * Called when the "connect" button is clicked.
 */
function submit() {
  // Show the "connecting" screen
  document.body.classList.add("connecting");

  // Save the host/port values
  let host = document.getElementById("host").value;
  Services.prefs.setCharPref("devtools.debugger.remote-host", host);

  let port = document.getElementById("port").value;
  Services.prefs.setIntPref("devtools.debugger.remote-port", port);

  // Initiate the connection
  let transport = debuggerSocketConnect(host, port);
  gClient = new DebuggerClient(transport);
  let delay = Services.prefs.getIntPref("devtools.debugger.remote-timeout");
  gConnectionTimeout = setTimeout(handleConnectionTimeout, delay);
  gClient.connect(onConnectionReady);
}

/**
 * Connection is ready. List actors and build buttons.
 */
function onConnectionReady(aType, aTraits) {
  clearTimeout(gConnectionTimeout);
  gClient.listTabs(function(aResponse) {
    document.body.classList.remove("connecting");
    document.body.classList.add("actors-mode");

    let parent = document.getElementById("tabActors");

    // Add Global Process debugging...
    let globals = JSON.parse(JSON.stringify(aResponse));
    delete globals.tabs;
    delete globals.selected;
    // ...only if there are appropriate actors (a 'from' property will always
    // be there).

    // Add one entry for each open tab.
    for (let i = 0; i < aResponse.tabs.length; i++) {
      buildLink(aResponse.tabs[i], parent, i == aResponse.selected);
    }

    let gParent = document.getElementById("globalActors");

    // Build the Remote Process button
    if (Object.keys(globals).length > 1) {
      let a = document.createElement("a");
      a.onclick = function() {
        openToolbox(globals, true);

      }
      a.title = a.textContent = window.l10n.GetStringFromName("mainProcess");
      a.className = "remote-process";
      a.href = "#";
      gParent.appendChild(a);
    }
    // Move the selected tab on top
    let selectedLink = parent.querySelector("a.selected");
    if (selectedLink) {
      parent.insertBefore(selectedLink, parent.firstChild);
    }

    // Ensure the first link is focused
    let firstLink = parent.querySelector("a:first-of-type");
    if (firstLink) {
      firstLink.focus();
    }

  });
}

/**
 * Build one button for an actor.
 */
function buildLink(tab, parent, selected) {
  let a = document.createElement("a");
  a.onclick = function() {
    openToolbox(tab);
  }

  a.textContent = tab.title;
  a.title = tab.url;
  if (!a.textContent) {
    a.textContent = tab.url;
  }
  a.href = "#";

  if (selected) {
    a.classList.add("selected");
  }

  parent.appendChild(a);
}

/**
 * An error occured. Let's show it and return to the first screen.
 */
function showError(type) {
  document.body.className = "error";
  let activeError = document.querySelector(".error-message.active");
  if (activeError) {
    activeError.classList.remove("active");
  }
  activeError = document.querySelector(".error-" + type);
  if (activeError) {
    activeError.classList.add("active");
  }
}

/**
 * Connection timeout.
 */
function handleConnectionTimeout() {
  showError("timeout");
}

/**
 * The user clicked on one of the buttons.
 * Opens the toolbox.
 */
function openToolbox(form, chrome=false) {
  let options = {
    form: form,
    client: gClient,
    chrome: chrome
  };
  devtools.TargetFactory.forRemoteTab(options).then((target) => {
    gDevTools.showToolbox(target, "webconsole", devtools.Toolbox.HostType.WINDOW);
    window.close();
  });
}
