var BufferCursor = require('buffercursor');

function BufferBuilder(){
  this._pieces = [];
  this._length = 0;
}

BufferBuilder.prototype._sizes = [null, null, 1, 2, 4, 1, 2, 4, 4, 8];

// Accepts numbers, strings, and buffers
BufferBuilder.prototype.append = function(data, type) {

  // Types (Numbers are BE)
  // 0: String
  // 1: Buffer
  // 2: UInt8
  // 3: UInt16
  // 4: UInt32
  // 5: Int8
  // 6: Int16
  // 7: Int32
  // 8: Float
  // 9: Double
  switch(type) {
    case 0:
      this._length += Buffer.byteLength(data);
      break;
    case 1: 
      this._length += data.length;
      break;
    default:
      this._length += this._sizes[type];
  };
  this._pieces.push([data, type]);
};

BufferBuilder.prototype.getBuffer = function() {
  var buffer = new Buffer(this._length);
  var cursor = new BufferCursor(buffer);
  for (var i = 0, ii = this._pieces.length; i < ii; i++) {
    var tuple = this._pieces[i];
    switch (tuple[1] /* type */) {
      case 0:
        cursor.write(tuple[0]);
        break;
      case 1:
        var index = cursor.tell();
        tuple[0].copy(buffer, index);
        cursor.seek(index + tuple[0].length);
        break;
      case 2:
        cursor.writeUInt8(tuple[0]);
        break;
      case 3:
        cursor.writeUInt16BE(tuple[0]);
        break;
      case 4:
        cursor.writeUInt32BE(tuple[0]);
        break;
      case 5:
        cursor.writeInt8(tuple[0]);
        break;
      case 6:
        cursor.writeInt16BE(tuple[0]);
        break;
      case 7:
        cursor.writeInt32BE(tuple[0]);
        break;
      case 8:
        cursor.writeFloatBE(tuple[0]);
        break;
      case 9:
        cursor.writeDoubleBE(tuple[0]);
        break;
      default:
        throw new Error('Unexpected type for `'+tuple[0]+'` in buffer builder');
    }
  }
  return buffer;
};

module.exports = BufferBuilder;
