<html>
<head>
  <title>pdf.js test slave</title>
  <style type="text/css"></style>
  <script type="text/javascript" src="/pdf.js"></script>
  <script type="text/javascript" src="/fonts.js"></script>
  <script type="text/javascript" src="/crypto.js"></script>
  <script type="text/javascript" src="/glyphlist.js"></script>
  <script type="application/javascript">
var appPath, browser, canvas, currentTask, currentTaskIdx, failure, manifest, numPages, pdfDoc, stdout;

function queryParams() {
    var qs = window.location.search.substring(1);
    var kvs = qs.split("&");
    var params = { };
    for (var i = 0; i < kvs.length; ++i) {
        var kv = kvs[i].split("=");
        params[unescape(kv[0])] = unescape(kv[1]);
    }
    return params;
}

function load() {
  var params = queryParams();
  browser = params.browser;
  manifestFile = params.manifestFile;
  appPath = params.path;

  canvas = document.createElement("canvas");
  canvas.mozOpaque = true;
  stdout = document.getElementById("stdout");

  log("Harness thinks this browser is '"+ browser + "' with path " + appPath + "\n");
  log("Fetching manifest "+ manifestFile +"...");

  var r = new XMLHttpRequest();
  r.open("GET", manifestFile, false);
  r.onreadystatechange = function(e) {
    if (r.readyState == 4) {
      log("done\n");

      manifest = JSON.parse(r.responseText);
      currentTaskIdx = 0, nextTask();
    }
  };
  r.send(null);
}

function nextTask() {
  if (currentTaskIdx == manifest.length) {
    return done();
  }
  currentTask = manifest[currentTaskIdx];
  currentTask.round = 0;

  log("Loading file "+ currentTask.file +"\n");

  var r = new XMLHttpRequest();
  r.open("GET", currentTask.file);
  r.mozResponseType = r.responseType = "arraybuffer";
  r.onreadystatechange = function() {
    if (r.readyState == 4) {
      var data = r.mozResponseArrayBuffer || r.mozResponse ||
                 r.responseArrayBuffer || r.response;

      try {
        pdfDoc = new PDFDoc(new Stream(data));
        numPages = pdfDoc.numPages;
      } catch(e) {
        numPages = 1;
        failure = 'load PDF doc: '+ e.toString();
      }

      currentTask.pageNum = 1, nextPage();
    }    
  };
  r.send(null);
}

function nextPage() {
  if (currentTask.pageNum > numPages) {
    if (++currentTask.round < currentTask.rounds) {
      log("  Round "+ (1 + currentTask.round) +"\n");
      currentTask.pageNum = 1;
    } else {
      ++currentTaskIdx, nextTask();
      return;
    }
  }

  failure = '';
  log("    loading page "+ currentTask.pageNum +"... ");

  var ctx = canvas.getContext("2d");

  var fonts = [];
  var gfx = null;
  try {
    gfx = new CanvasGraphics(ctx);
    currentPage = pdfDoc.getPage(currentTask.pageNum);
    currentPage.compile(gfx, fonts);
  } catch(e) {
    failure = 'compile: '+ e.toString();
  }

  try {
    var pdfToCssUnitsCoef = 96.0 / 72.0;
    // using mediaBox for the canvas size
    var pageWidth = (currentPage.mediaBox[2] - currentPage.mediaBox[0]);
    var pageHeight = (currentPage.mediaBox[3] - currentPage.mediaBox[1]);
    canvas.width = pageWidth * pdfToCssUnitsCoef;
    canvas.height = pageHeight * pdfToCssUnitsCoef;
    clear(ctx);
  } catch(e) {
    failure = 'page setup: '+ e.toString();
  }

  var fontLoaderTimer = null;
  function checkFontsLoaded() {
    try {
      if (!FontLoader.bind(fonts)) {
        fontLoaderTimer = window.setTimeout(checkFontsLoaded, 10);
        return;
      }
    } catch(e) {
      failure = 'fonts: '+ e.toString();
    }
    snapshotCurrentPage(gfx);
  }

  if (failure) {
    // Skip font loading if there was a failure, since the fonts might
    // be in an inconsistent state.
    snapshotCurrentPage(gfx);
  } else {
    checkFontsLoaded();
  }
}

function snapshotCurrentPage(gfx) {
  log("done, snapshotting... ");

  if (!failure) {
    try {
      currentPage.display(gfx);
    } catch(e) {
      failure = 'render: '+ e.toString();
    }
  }

  sendTaskResult(canvas.toDataURL("image/png"));
  log("done"+ (failure ? " (failed!)" : "") +"\n");

  // Set up the next request
  backoff = (inFlightRequests > 0) ? inFlightRequests * 10 : 0;
  setTimeout(function() {
      ++currentTask.pageNum, nextPage();
    },
    backoff
  );
}

function sendQuitRequest() {
  var r = new XMLHttpRequest();
  r.open("POST", "/tellMeToQuit?path=" + escape(appPath), false);
  r.send("");
}

function quitApp() {
  log("Done!");
  document.body.innerHTML = "Tests are finished.  <h1>CLOSE ME!</h1>";
  if (window.SpecialPowers) {
    SpecialPowers.quitApplication();
  } else {
    sendQuitRequest();
    window.close();
  }
}

function done() {
  if (inFlightRequests > 0) {
    document.getElementById("inFlightCount").innerHTML = inFlightRequests;
    setTimeout(done, 100);
  } else {
    setTimeout(quitApp, 100);
  }
}

var inFlightRequests = 0;
function sendTaskResult(snapshot) {
  var result = { browser: browser,
                 id: currentTask.id,
                 numPages: numPages,
                 failure: failure,
                 file: currentTask.file,
                 round: currentTask.round,
                 page: currentTask.pageNum,
                 snapshot: snapshot };

  var r = new XMLHttpRequest();
  // (The POST URI is ignored atm.)
  r.open("POST", "/submit_task_results", true);
  r.setRequestHeader("Content-Type", "application/json");
  r.onreadystatechange = function(e) {
    if (r.readyState == 4) {
      inFlightRequests--;
    }
  }
  document.getElementById("inFlightCount").innerHTML = inFlightRequests++;
  r.send(JSON.stringify(result));
}

function clear(ctx) {
  ctx.save();
  ctx.fillStyle = "rgb(255, 255, 255)";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.restore();
}

/* Auto-scroll if the scrollbar is near the bottom, otherwise do nothing. */
function checkScrolling() {
  if ((stdout.scrollHeight - stdout.scrollTop) <= stdout.offsetHeight) {
    stdout.scrollTop = stdout.scrollHeight;
  }
}

function log(str) {
  stdout.innerHTML += str;
  checkScrolling();
}
  </script>
</head>

<body onload="load();">
  <pre style="width:800; height:800; overflow: scroll;"id="stdout"></pre>
  <p>Inflight requests: <span id="inFlightCount"></span></p>
</body>

</html>