// Generated by CoffeeScript 1.7.1
var ENCRYPT, MARS, PreloginPayload, SUBBUILD, TOKEN, VERSION, WritableTrackingBuffer, encryptByValue, marsByValue, name, optionBufferSize, sprintf, value;

sprintf = require('sprintf').sprintf;

WritableTrackingBuffer = require('./tracking-buffer/tracking-buffer').WritableTrackingBuffer;

optionBufferSize = 20;

VERSION = 0x000000001;

SUBBUILD = 0x0001;

TOKEN = {
  VERSION: 0x00,
  ENCRYPTION: 0x01,
  INSTOPT: 0x02,
  THREADID: 0x03,
  MARS: 0x04,
  TERMINATOR: 0xFF
};

ENCRYPT = {
  OFF: 0x00,
  ON: 0x01,
  NOT_SUP: 0x02,
  REQ: 0x03
};

encryptByValue = {};

for (name in ENCRYPT) {
  value = ENCRYPT[name];
  encryptByValue[value] = name;
}

MARS = {
  OFF: 0x00,
  ON: 0x01
};

marsByValue = {};

for (name in MARS) {
  value = MARS[name];
  marsByValue[value] = name;
}


/*
  s2.2.6.4
 */

PreloginPayload = (function() {
  function PreloginPayload(bufferOrOptions) {
    if (bufferOrOptions instanceof Buffer) {
      this.data = bufferOrOptions;
    } else {
      this.options = bufferOrOptions || {};
      this.createOptions();
    }
    this.extractOptions();
  }

  PreloginPayload.prototype.createOptions = function() {
    var length, option, optionDataOffset, optionOffset, options, _i, _j, _len, _len1;
    options = [this.createVersionOption(), this.createEncryptionOption(), this.createInstanceOption(), this.createThreadIdOption(), this.createMarsOption()];
    length = 0;
    for (_i = 0, _len = options.length; _i < _len; _i++) {
      option = options[_i];
      length += 5 + option.data.length;
    }
    length++;
    this.data = new Buffer(length);
    optionOffset = 0;
    optionDataOffset = 5 * options.length + 1;
    for (_j = 0, _len1 = options.length; _j < _len1; _j++) {
      option = options[_j];
      this.data.writeUInt8(option.token, optionOffset + 0);
      this.data.writeUInt16BE(optionDataOffset, optionOffset + 1);
      this.data.writeUInt16BE(option.data.length, optionOffset + 3);
      optionOffset += 5;
      option.data.copy(this.data, optionDataOffset);
      optionDataOffset += option.data.length;
    }
    return this.data.writeUInt8(TOKEN.TERMINATOR, optionOffset);
  };

  PreloginPayload.prototype.createVersionOption = function() {
    var buffer;
    buffer = new WritableTrackingBuffer(optionBufferSize);
    buffer.writeUInt32BE(VERSION);
    buffer.writeUInt16BE(SUBBUILD);
    return {
      token: TOKEN.VERSION,
      data: buffer.data
    };
  };

  PreloginPayload.prototype.createEncryptionOption = function() {
    var buffer;
    buffer = new WritableTrackingBuffer(optionBufferSize);
    if (this.options.encrypt) {
      buffer.writeUInt8(ENCRYPT.ON);
    } else {
      buffer.writeUInt8(ENCRYPT.NOT_SUP);
    }
    return {
      token: TOKEN.ENCRYPTION,
      data: buffer.data
    };
  };

  PreloginPayload.prototype.createInstanceOption = function() {
    var buffer;
    buffer = new WritableTrackingBuffer(optionBufferSize);
    buffer.writeUInt8(0x00);
    return {
      token: TOKEN.INSTOPT,
      data: buffer.data
    };
  };

  PreloginPayload.prototype.createThreadIdOption = function() {
    var buffer;
    buffer = new WritableTrackingBuffer(optionBufferSize);
    buffer.writeUInt32BE(0x00);
    return {
      token: TOKEN.THREADID,
      data: buffer.data
    };
  };

  PreloginPayload.prototype.createMarsOption = function() {
    var buffer;
    buffer = new WritableTrackingBuffer(optionBufferSize);
    buffer.writeUInt8(MARS.OFF);
    return {
      token: TOKEN.MARS,
      data: buffer.data
    };
  };

  PreloginPayload.prototype.extractOptions = function() {
    var dataLength, dataOffset, offset, _results;
    offset = 0;
    _results = [];
    while (this.data[offset] !== TOKEN.TERMINATOR) {
      dataOffset = this.data.readUInt16BE(offset + 1);
      dataLength = this.data.readUInt16BE(offset + 3);
      switch (this.data[offset]) {
        case TOKEN.VERSION:
          this.extractVersion(dataOffset);
          break;
        case TOKEN.ENCRYPTION:
          this.extractEncryption(dataOffset);
          break;
        case TOKEN.INSTOPT:
          this.extractInstance(dataOffset);
          break;
        case TOKEN.THREADID:
          if (dataLength > 0) {
            this.extractThreadId(dataOffset);
          }
          break;
        case TOKEN.MARS:
          this.extractMars(dataOffset);
      }
      offset += 5;
      _results.push(dataOffset += dataLength);
    }
    return _results;
  };

  PreloginPayload.prototype.extractVersion = function(offset) {
    return this.version = {
      major: this.data.readUInt8(offset + 0),
      minor: this.data.readUInt8(offset + 1),
      patch: this.data.readUInt8(offset + 2),
      trivial: this.data.readUInt8(offset + 3),
      subbuild: this.data.readUInt16BE(offset + 4)
    };
  };

  PreloginPayload.prototype.extractEncryption = function(offset) {
    this.encryption = this.data.readUInt8(offset);
    return this.encryptionString = encryptByValue[this.encryption];
  };

  PreloginPayload.prototype.extractInstance = function(offset) {
    return this.instance = this.data.readUInt8(offset);
  };

  PreloginPayload.prototype.extractThreadId = function(offset) {
    return this.threadId = this.data.readUInt32BE(offset);
  };

  PreloginPayload.prototype.extractMars = function(offset) {
    this.mars = this.data.readUInt8(offset);
    return this.marsString = marsByValue[this.mars];
  };

  PreloginPayload.prototype.toString = function(indent) {
    indent || (indent = '');
    return indent + 'PreLogin - ' + sprintf('version:%d.%d.%d.%d %d, encryption:0x%02X(%s), instopt:0x%02X, threadId:0x%08X, mars:0x%02X(%s)', this.version.major, this.version.minor, this.version.patch, this.version.trivial, this.version.subbuild, this.encryption ? this.encryption : 0, this.encryptionString ? this.encryptionString : 0, this.instance ? this.instance : 0, this.threadId ? this.threadId : 0, this.mars ? this.mars : 0, this.marsString ? this.marsString : 0);
  };

  return PreloginPayload;

})();

module.exports = PreloginPayload;
