// Generated by CoffeeScript 1.7.1
var DEFAULT_PACKETID, DEFAULT_SPID, DEFAULT_WINDOW, HEADER_LENGTH, NL, OFFSET, Packet, STATUS, TYPE, isPacketComplete, name, packetLength, sprintf, typeByValue, value;

require('./buffertools');

sprintf = require('sprintf').sprintf;

HEADER_LENGTH = 8;

TYPE = {
  SQL_BATCH: 0x01,
  RPC_REQUEST: 0x03,
  TABULAR_RESULT: 0x04,
  ATTENTION: 0x06,
  BULK_LOAD: 0x07,
  TRANSACTION_MANAGER: 0x0E,
  LOGIN7: 0x10,
  NTLMAUTH_PKT: 0x11,
  PRELOGIN: 0x12
};

typeByValue = {};

for (name in TYPE) {
  value = TYPE[name];
  typeByValue[value] = name;
}

STATUS = {
  NORMAL: 0x00,
  EOM: 0x01,
  IGNORE: 0x02,
  RESETCONNECTION: 0x08,
  RESETCONNECTIONSKIPTRAN: 0x10
};

OFFSET = {
  Type: 0,
  Status: 1,
  Length: 2,
  SPID: 4,
  PacketID: 6,
  Window: 7
};

DEFAULT_SPID = 0;

DEFAULT_PACKETID = 1;

DEFAULT_WINDOW = 0;

NL = '\n';

Packet = (function() {
  function Packet(typeOrBuffer) {
    var type;
    if (typeOrBuffer instanceof Buffer) {
      this.buffer = typeOrBuffer;
    } else {
      type = typeOrBuffer;
      this.buffer = new Buffer(HEADER_LENGTH);
      this.buffer.writeUInt8(type, OFFSET.Type);
      this.buffer.writeUInt8(STATUS.NORMAL, OFFSET.Status);
      this.buffer.writeUInt16BE(DEFAULT_SPID, OFFSET.SPID);
      this.buffer.writeUInt8(DEFAULT_PACKETID, OFFSET.PacketID);
      this.buffer.writeUInt8(DEFAULT_WINDOW, OFFSET.Window);
      this.setLength();
    }
  }

  Packet.prototype.setLength = function() {
    return this.buffer.writeUInt16BE(this.buffer.length, OFFSET.Length);
  };

  Packet.prototype.length = function() {
    return this.buffer.readUInt16BE(OFFSET.Length);
  };

  Packet.prototype.resetConnection = function(reset) {
    var status;
    status = this.buffer.readUInt8(OFFSET.Status);
    if (reset) {
      status |= STATUS.RESETCONNECTION;
    } else {
      status &= 0xFF - STATUS.RESETCONNECTION;
    }
    return this.buffer.writeUInt8(status, OFFSET.Status);
  };

  Packet.prototype.last = function(last) {
    var status;
    status = this.buffer.readUInt8(OFFSET.Status);
    if (arguments.length > 0) {
      if (last) {
        status |= STATUS.EOM;
      } else {
        status &= 0xFF - STATUS.EOM;
      }
      this.buffer.writeUInt8(status, OFFSET.Status);
    }
    return this.isLast();
  };

  Packet.prototype.isLast = function() {
    return !!(this.buffer.readUInt8(OFFSET.Status) & STATUS.EOM);
  };

  Packet.prototype.packetId = function(packetId) {
    if (packetId) {
      this.buffer.writeUInt8(packetId % 256, OFFSET.PacketID);
    }
    return this.buffer.readUInt8(OFFSET.PacketID);
  };

  Packet.prototype.addData = function(data) {
    this.buffer = Buffer.concat([this.buffer, data]);
    this.setLength();
    return this;
  };

  Packet.prototype.data = function() {
    return this.buffer.slice(HEADER_LENGTH);
  };

  Packet.prototype.type = function() {
    return this.buffer.readUInt8(OFFSET.Type);
  };

  Packet.prototype.statusAsString = function() {
    var status, statuses;
    status = this.buffer.readUInt8(OFFSET.Status);
    statuses = (function() {
      var _results;
      _results = [];
      for (name in STATUS) {
        value = STATUS[name];
        if (status & value) {
          _results.push(name);
        } else {
          _results.push(void 0);
        }
      }
      return _results;
    })();
    return statuses.join(' ').trim();
  };

  Packet.prototype.headerToString = function(indent) {
    var text;
    indent || (indent = '');
    text = sprintf('type:0x%02X(%s), status:0x%02X(%s), length:0x%04X, spid:0x%04X, packetId:0x%02X, window:0x%02X', this.buffer.readUInt8(OFFSET.Type), typeByValue[this.buffer.readUInt8(OFFSET.Type)], this.buffer.readUInt8(OFFSET.Status), this.statusAsString(), this.buffer.readUInt16BE(OFFSET.Length), this.buffer.readUInt16BE(OFFSET.SPID), this.buffer.readUInt8(OFFSET.PacketID), this.buffer.readUInt8(OFFSET.Window));
    return indent + text;
  };

  Packet.prototype.dataToString = function(indent) {
    var BYTES_PER_GROUP, BYTES_PER_LINE, CHARS_PER_GROUP, chars, data, dataDump, offset, _i, _ref;
    BYTES_PER_GROUP = 0x04;
    CHARS_PER_GROUP = 0x08;
    BYTES_PER_LINE = 0x20;
    indent || (indent = '');
    data = this.data();
    dataDump = '';
    chars = '';
    for (offset = _i = 0, _ref = data.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; offset = 0 <= _ref ? ++_i : --_i) {
      if (offset % BYTES_PER_LINE === 0) {
        dataDump += indent;
        dataDump += sprintf('%04X  ', offset);
      }
      if (data[offset] < 0x20 || data[offset] > 0x7E) {
        chars += '.';
        if (((offset + 1) % CHARS_PER_GROUP === 0) && !((offset + 1) % BYTES_PER_LINE === 0)) {
          chars += ' ';
        }
      } else {
        chars += String.fromCharCode(data[offset]);
      }
      if (data[offset] != null) {
        dataDump += sprintf('%02X', data[offset]);
      }
      if (((offset + 1) % BYTES_PER_GROUP === 0) && !((offset + 1) % BYTES_PER_LINE === 0)) {
        dataDump += ' ';
      }
      if ((offset + 1) % BYTES_PER_LINE === 0) {
        dataDump += '  ' + chars;
        chars = '';
        if (offset < data.length - 1) {
          dataDump += NL;
        }
      }
    }
    if (chars.length) {
      dataDump += '  ' + chars;
    }
    return dataDump;
  };

  Packet.prototype.toString = function(indent) {
    indent || (indent = '');
    return this.headerToString(indent) + '\n' + this.dataToString(indent + indent);
  };

  Packet.prototype.payloadString = function(indent) {
    return "";
  };

  return Packet;

})();

isPacketComplete = function(potentialPacketBuffer) {
  if (potentialPacketBuffer.length < HEADER_LENGTH) {
    return false;
  } else {
    return potentialPacketBuffer.length >= potentialPacketBuffer.readUInt16BE(OFFSET.Length);
  }
};

packetLength = function(potentialPacketBuffer) {
  return potentialPacketBuffer.readUInt16BE(OFFSET.Length);
};

exports.Packet = Packet;

exports.OFFSET = OFFSET;

exports.TYPE = TYPE;

exports.isPacketComplete = isPacketComplete;

exports.packetLength = packetLength;

exports.HEADER_LENGTH = HEADER_LENGTH;
