function Graph(boxes, test, days, node) {
  var boxes = boxes.split(",");
  this._node = node;
  this._pulled = 0;
  this._count = boxes.length;
  this._datasets = [];
  this._maxTime = Date.now();
  this._minTime = this._maxTime - days*24*60*60*1000;
  this._minVal = 10000000;
  this._maxVal = 0;

  for (var i = 0; i < boxes.length; i++)
    this.pullDataSet(boxes[i], test);
}

Graph.prototype = {
  _node: null,
  _count: null,
  _pulled: null,
  _datasets: null,
  _minTime: null,
  _maxTime: null,
  _maxVal: null,
  _minVal: null,

  renderGraph: function() {
    var step = (this._maxTime - this._minTime) / 10;
    var ticks = [];
    for (var i = 0; i <= 10; i++) {
      var tick = [];
      tick.push(this._minTime + parseInt(i * step));
      tick.push((new Date(tick[0])).toLocaleString());
      ticks.push(tick);
    }
    $.plot(this._node, this._datasets, {
      xaxis: {
        ticks: ticks
      },
      yaxis: {
        min: this._minVal,
        max: this._maxVal
      }
    });
  },

  onLoad: function(xhr, box) {
    var full = xhr.responseText;
    var start = full.indexOf("<pre>");
    var end = full.indexOf("</pre>", start);
    var lines = full.substring(start + 5, end).split("\n");

    var data = [];
    for (var i = 0; i < lines.length; i++) {
      var line = lines[i].replace(/^\s+|\s+$/g, "");
      var parts = line.split(/\s+/);
      if (parts.length != 3)
        continue;
      var date = parts[1].split(":");
      if (date.length != 6)
        continue;
      var time = (new Date(date[0], date[1] - 1, date[2], date[3], date[4], date[5], 0)).getTime();
      if (time < this._minTime || time > this._maxTime)
        continue
      var datapoint = [];
      datapoint[0] = time;
      datapoint[1] = parts[2];
      data.push(datapoint);
      if (!parts[2])
        if (confirm(line))
          return;
      this._minVal = Math.min(this._minVal, datapoint[1]);
      this._maxVal = Math.max(this._maxVal, datapoint[1]);
    }
    this._datasets.push({
      label: box,
      data: data
    });
    this._pulled++;
    if (this._pulled == this._count)
      this.renderGraph();
  },

  onError: function(xhr, box) {
    this._pulled++;
    if (this._pulled == this._count)
      this.renderGraph();
  },

  pullDataSet: function(box, test) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "perfdata.cgi?tbox=" + box + "&testname=" + test, true);
    xhr.overrideMimeType("text/plain");
    var self = this;
    xhr.onload = function() {
      self.onLoad(xhr, box);
    }
    xhr.onerror = function() {
      self.onError(xhr, box);
    }
    xhr.send(null);
  }
}

