function begin()
{
  var funInstallFacts = [
      "#1 - Chapters were added to the Bible in 1238<small>AD</small> by Cardinal Hugo de Sancto Caro...",
      "...but it took 313 years for verse notations to be added by Robertus Stephanus in 1551<small>AD</small>.",
      "#2 - The longest verse is Esther 8v9, but sadly it won't fit in the remaining space of this box.",
      "#3 - Galatians 1v14 contains every letter of the alphabet... except the letter k.",
      "#4 - It takes around 70 hours to read the whole Bible out loud, but hopefully less time to install.",
      "#5 - The longest word in the Bible is &quot;Mahershalalhashbaz&quot; (18 letters) in Isaiah 8:1.",
      "#6 - The longest intercontinental telegram ever sent was the text of the New International Version...",
      "...it was sent by telegram from Geneva (where it was translated) to New York for printing."
    ];

  var controller = new BibleReaderController("body");
  var error = false;
  //controller.BibleDatabase().executeSql("DROP TABLE IF EXISTS manifests;");
  var localServer = google.gears.factory.create("beta.localserver");
  //localServer.removeManagedStore("OfflineBible");
  var coreManifest = controller.BibleDatabase().getManifest("OfflineBible Core");
  var install = coreManifest.major == 0 && coreManifest.minor == 0 && coreManifest.schema == 0;
  //alert(coreManifest.major + "." + coreManifest.minor + "." + coreManifest.schema);
  var installer = new Installer();

  var loadIntroBox     = function() { var introBox = new IntroBox(); introBox.onInstallClick(installThread); installer.setBox(introBox); }
  var loadWelcomeBox   = function() { var welcomeBox = new WelcomeBox(); welcomeBox.onReadClick(mainScreenTurnOn); welcomeBox.onPackagesClick(installThread); $(document).bind("keydown", function (e) { if (e.keyCode == 13) { $(document).unbind("keydown"); welcomeBox.defaultAction(); } } ); installer.setBox(welcomeBox); };
  var loadPackageBox   = function() { var packageBox = new PackageBox(); packageBox.onInstallClick( function () { mainScreenTurnOn(); } ); packageBox.onCancelClick(loadWelcomeBox); installer.setBox(packageBox); };
  var loadErrorBox     = function(m, l, t, e) { if (error) { return; } error = true; var errorBox = new ErrorBox(); errorBox.onContinueClick(function () { window.location = "http://" + location.host + "/"; } ); errorBox.setError(m, l, t, e); installer.setBox(errorBox); };
  var mainScreenTurnOn = function() { controller.load(); };

  var installThread = function(e)
        {
          var wp_packageManager = google.gears.factory.create("beta.workerpool");
          var installerWorkerId = wp_packageManager.createWorkerFromUrl("/scripts/workers/install.js.php");

          var progressBox = new ProgressBox();
          var packageBox = new PackageBox();

          progressBox.onCancelClick( function(e) { wp_packageManager.sendMessage( { "target": "CANCEL", "args": { } }, installerWorkerId); } );
          progressBox.onContinueClick( function(e) { controller.load(); } );

          wp_packageManager.onmessage = function(a, b, message) {
            try
            {
              var target = message.body.target;
              var args = message.body.args;

              switch (target)
              {
                case "constructComplete":
                {
                  var updatePath = "http://" + location.host + "/install/edge.js.php";
                  wp_packageManager.sendMessage( { "target": "getUpdatePath", "args": { "url": updatePath } }, installerWorkerId);
                }
                break;
                case "getUpdatePathComplete":
                {
                  packageBox.setManifests(args.manifestList);
                  packageBox.onInstallClick( function (manifestList)
                  {
                    var baseBuild = new Array();
                    $.each(manifestList, function(i,v) { if (v.force) { baseBuild.push(v); } })
                    installer.setBox(progressBox);
                    wp_packageManager.sendMessage( { "target": "getUpgradeScript", "args" : { "manifests": baseBuild } }, installerWorkerId);
                  } );
                  packageBox.onCancelClick(loadWelcomeBox);
                  installer.setBox(packageBox);
                }
                break;
                case "getUpgradeScriptComplete":
                {
                  wp_packageManager.sendMessage( { "target": "install", "args" : { } }, installerWorkerId);
                }
                break;
                case "installComplete":
                {
                  wp_packageManager.sendMessage( { "target": "getOfflineResources", "args" : { "manifestUrl": "http://" + location.host + "/manifest.php" } }, installerWorkerId);
                }
                break;
                case "getOfflineResourcesComplete":
                {
                  progressBox.title("Complete");
                  progressBox.action("All updates have been successfully installed.");
                  progressBox.progress(100);
                  progressBox.finish();
                }
                break;
                case "progressMessage":
                {
                  progressBox.title(args.title);
                  progressBox.action(args.action);
                  progressBox.progress(args.progress);
                }
                break;
                case "CANCELLED":
                {
                  loadErrorBox("User cancelled", "unknown", "Installation stopped", "The installation was cancelled as requested. You can <a href=\"/\" title=\"Reload the page to restart the installation\">reload</a> the page to recommence the installation.");
                }
                break;
                case "EXCEPTION":
                {
                  loadErrorBox(args.message + " (worker #" + message.sender + ")", args.lineNumber, "Installation failed", "The installation failed due to an unexpected error. It could be that the installer does not support your browser, or there is a problem with the current codebase. Please try again later.");
                }
                break;
                case "DEBUG":
                {
                  //var debugMessage = $(document.createElement("code"));
                  //debugMessage.text("[Worker #" + message.sender + "] " + args.message);
                  //$("#console").append(debugMessage);
                }
                break;
              }
            }
            catch (err)
            {
              loadErrorBox(err.message + " (receiving from #" + message.sender + ")", err.lineNumber, "Installation failed", "The installation failed due to an unexpected error. It could be that the installer does not support your browser, or there is a problem with the current codebase. Please try again later.");
            }
          };

          progressBox.title("0%");
          progressBox.action("Initializing, please wait...");
          progressBox.facts(funInstallFacts);
          progressBox.startFacts();
          installer.setBox(progressBox);

          wp_packageManager.sendMessage( { "target": "construct", "args": { "database": "OfflineBible" } }, installerWorkerId);
        };

  if (install) {
    controller.BibleDatabase().executeSql("DROP TABLE IF EXISTS manifests;");
    loadIntroBox();
  }
  else { loadWelcomeBox(); }
  installer.show();
  var debugBox = $(document.createElement("div"));
  debugBox.attr("id","console");
  $(".veil").append(debugBox);
}

/// BOOT SEQUENCE
/// Allow a split second for the browser to render. 1/10th of a second should
/// be plenty for the browser to render the "loading" image before we kick off
/// the UI builder.
$(document).ready( function () { window.setTimeout(begin, 250); } );

