function Label() {
  this.references = [];
  this.name = "undefined";
  this.offset = 0;
  return this;
}

Label.prototype.reference = function(offset) {
  this.references.push(offset);
}

var BIGENDIAN=1;
var LITTLEENDIAN=2;
function Image(endian) {
  this.memory = [];
  this.labels = {};
  this.endian = endian;
  return this;
}

Image.prototype._writeLabels = function(stream) {
  var labels = []
  for(label in this.labels) {
    labels.push(this.labels[label]);
  }
  stream.write(this._longAsBytes(labels.length));
  for(var i=0;i < labels.length; ++i) {
    stream.write(this._longAsBytes(labels[i].offset));
    stream.write(this._longAsBytes(labels[i].references.length));
    for(var j=0;j < labels[i].references.length; ++j) {
      stream.write(this._longAsBytes(labels[i].references[j]));    
    }    
  }
}

Image.prototype.save = function(filename) {
  var stream;
  try {
    stream = new java.io.FileOutputStream(filename);

    // Write header - the number of bytes in the file
    stream.write(this._longAsBytes(this.memory.length));

    // Write data    
    for(var i = 0; i < this.memory.length; ++i) {
      stream.write(this.memory[i]);
    }

    this._writeLabels(stream);

  } finally {
    if(stream)
      stream.close();
  }
}

Image.prototype.emit = function(value) {  
  this.memory.push(value);
}

Image.prototype._longAsBytes = function(value) {
  var bytes = [];
  bytes.push(0xff & value);
  bytes.push(0xff & (value >> 8));
  bytes.push(0xff & (value >> 16));
  bytes.push(0xff & (value >> 24));
  return bytes;
}

Image.prototype.emit32 = function(value) {  
  var l = this._longAsBytes(value);
  if(this.endian == LITTLEENDIAN)
    this.memory.push(l[0], l[1], l[2], l[3]);
  else
    this.memory.push(l[3], l[2], l[1], l[0]);
}

Image.prototype.label = function(name) {
  if(!this.labels[name]) {
    this.labels[name] = new Label();
  }
  this.labels[name].name = name;
  this.labels[name].offset = this.memory.length;
}

Image.prototype.referLabel = function(name, offset) {
  if(!this.labels[name]) {
    this.labels[name] = new Label();
  }
  this.labels[name].reference(this.memory.length);
}
