'use strict';

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var sprintf = require('sprintf-js').sprintf;

var FLAGS_1 = {
  ENDIAN_LITTLE: 0x00,
  ENDIAN_BIG: 0x01,
  CHARSET_ASCII: 0x00,
  CHARSET_EBCDIC: 0x02,
  FLOAT_IEEE_754: 0x00,
  FLOAT_VAX: 0x04,
  FLOAT_ND5000: 0x08,
  BCP_DUMPLOAD_ON: 0x00,
  BCP_DUMPLOAD_OFF: 0x10,
  USE_DB_ON: 0x00,
  USE_DB_OFF: 0x20,
  INIT_DB_WARN: 0x00,
  INIT_DB_FATAL: 0x40,
  SET_LANG_WARN_OFF: 0x00,
  SET_LANG_WARN_ON: 0x80
};

var FLAGS_2 = {
  INIT_LANG_WARN: 0x00,
  INIT_LANG_FATAL: 0x01,
  ODBC_OFF: 0x00,
  ODBC_ON: 0x02,
  F_TRAN_BOUNDARY: 0x04,
  F_CACHE_CONNECT: 0x08,
  USER_NORMAL: 0x00,
  USER_SERVER: 0x10,
  USER_REMUSER: 0x20,
  USER_SQLREPL: 0x40,
  INTEGRATED_SECURITY_OFF: 0x00,
  INTEGRATED_SECURITY_ON: 0x80
};

var TYPE_FLAGS = {
  SQL_DFLT: 0x00,
  SQL_TSQL: 0x08,
  OLEDB_OFF: 0x00,
  OLEDB_ON: 0x10,
  READ_WRITE_INTENT: 0x00,
  READ_ONLY_INTENT: 0x20
};

var FLAGS_3 = {
  CHANGE_PASSWORD_NO: 0x00,
  CHANGE_PASSWORD_YES: 0x01,
  BINARY_XML: 0x02,
  SPAWN_USER_INSTANCE: 0x04,
  UNKNOWN_COLLATION_HANDLING: 0x08
};

/*
  s2.2.6.3
 */
module.exports = function () {
  function Login7Payload(_ref) {
    var tdsVersion = _ref.tdsVersion,
        packetSize = _ref.packetSize,
        clientProgVer = _ref.clientProgVer,
        clientPid = _ref.clientPid,
        connectionId = _ref.connectionId,
        clientTimeZone = _ref.clientTimeZone,
        clientLcid = _ref.clientLcid;
    (0, _classCallCheck3.default)(this, Login7Payload);

    this.tdsVersion = tdsVersion;
    this.packetSize = packetSize;
    this.clientProgVer = clientProgVer;
    this.clientPid = clientPid;
    this.connectionId = connectionId;
    this.clientTimeZone = clientTimeZone;
    this.clientLcid = clientLcid;

    this.readOnlyIntent = false;
    this.initDbFatal = false;

    this.userName = undefined;
    this.password = undefined;
    this.serverName = undefined;
    this.appName = undefined;
    this.hostname = undefined;
    this.libraryName = undefined;
    this.language = undefined;
    this.database = undefined;
    this.clientId = undefined;
    this.sspi = undefined;
    this.attachDbFile = undefined;
    this.changePassword = undefined;
  }

  (0, _createClass3.default)(Login7Payload, [{
    key: 'toBuffer',
    value: function toBuffer() {
      var fixedData = new Buffer(94);
      var buffers = [fixedData];

      var offset = 0,
          dataOffset = fixedData.length;

      // Length: 4-byte
      offset = fixedData.writeUInt32LE(0, offset);

      // TDSVersion: 4-byte
      offset = fixedData.writeUInt32LE(this.tdsVersion, offset);

      // PacketSize: 4-byte
      offset = fixedData.writeUInt32LE(this.packetSize, offset);

      // ClientProgVer: 4-byte
      offset = fixedData.writeUInt32LE(this.clientProgVer, offset);

      // ClientPID: 4-byte
      offset = fixedData.writeUInt32LE(this.clientPid, offset);

      // ConnectionID: 4-byte
      offset = fixedData.writeUInt32LE(this.connectionId, offset);

      // OptionFlags1: 1-byte
      offset = fixedData.writeUInt8(this.buildOptionFlags1(), offset);

      // OptionFlags2: 1-byte
      offset = fixedData.writeUInt8(this.buildOptionFlags2(), offset);

      // TypeFlags: 1-byte
      offset = fixedData.writeUInt8(this.buildTypeFlags(), offset);

      // OptionFlags3: 1-byte
      offset = fixedData.writeUInt8(this.buildOptionFlags3(), offset);

      // ClientTimZone: 4-byte
      offset = fixedData.writeInt32LE(this.clientTimeZone, offset);

      // ClientLCID: 4-byte
      offset = fixedData.writeUInt32LE(this.clientLcid, offset);

      // ibHostName: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cchHostName: 2-byte
      if (this.hostname) {
        var buffer = new Buffer(this.hostname, 'ucs2');

        offset = fixedData.writeUInt16LE(buffer.length / 2, offset);
        dataOffset += buffer.length;

        buffers.push(buffer);
      } else {
        offset = fixedData.writeUInt16LE(dataOffset, offset);
      }

      // ibUserName: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cchUserName: 2-byte
      if (this.userName) {
        var _buffer = new Buffer(this.userName, 'ucs2');

        offset = fixedData.writeUInt16LE(_buffer.length / 2, offset);
        dataOffset += _buffer.length;

        buffers.push(_buffer);
      } else {
        offset = fixedData.writeUInt16LE(0, offset);
      }

      // ibPassword: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cchPassword: 2-byte
      if (this.password) {
        var _buffer2 = new Buffer(this.password, 'ucs2');

        offset = fixedData.writeUInt16LE(_buffer2.length / 2, offset);
        dataOffset += _buffer2.length;

        buffers.push(this.scramblePassword(_buffer2));
      } else {
        offset = fixedData.writeUInt16LE(0, offset);
      }

      // ibAppName: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cchAppName: 2-byte
      if (this.appName) {
        var _buffer3 = new Buffer(this.appName, 'ucs2');

        offset = fixedData.writeUInt16LE(_buffer3.length / 2, offset);
        dataOffset += _buffer3.length;

        buffers.push(_buffer3);
      } else {
        offset = fixedData.writeUInt16LE(0, offset);
      }

      // ibServerName: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cchServerName: 2-byte
      if (this.serverName) {
        var _buffer4 = new Buffer(this.serverName, 'ucs2');

        offset = fixedData.writeUInt16LE(_buffer4.length / 2, offset);
        dataOffset += _buffer4.length;

        buffers.push(_buffer4);
      } else {
        offset = fixedData.writeUInt16LE(0, offset);
      }

      // (ibUnused / ibExtension): 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // (cchUnused / cbExtension): 2-byte
      offset = fixedData.writeUInt16LE(0, offset);

      // ibCltIntName: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cchCltIntName: 2-byte
      if (this.libraryName) {
        var _buffer5 = new Buffer(this.libraryName, 'ucs2');

        offset = fixedData.writeUInt16LE(_buffer5.length / 2, offset);
        dataOffset += _buffer5.length;

        buffers.push(_buffer5);
      } else {
        offset = fixedData.writeUInt16LE(0, offset);
      }

      // ibLanguage: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cchLanguage: 2-byte
      if (this.language) {
        var _buffer6 = new Buffer(this.language, 'ucs2');

        offset = fixedData.writeUInt16LE(_buffer6.length / 2, offset);
        dataOffset += _buffer6.length;

        buffers.push(_buffer6);
      } else {
        offset = fixedData.writeUInt16LE(0, offset);
      }

      // ibDatabase: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cchDatabase: 2-byte
      if (this.database) {
        var _buffer7 = new Buffer(this.database, 'ucs2');

        offset = fixedData.writeUInt16LE(_buffer7.length / 2, offset);
        dataOffset += _buffer7.length;

        buffers.push(_buffer7);
      } else {
        offset = fixedData.writeUInt16LE(0, offset);
      }

      // ClientID: 6-byte
      if (this.clientId) {
        this.clientId.copy(fixedData, offset, 0, 6);
      }
      offset += 6;

      // ibSSPI: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cbSSPI: 2-byte
      if (this.sspi) {
        if (this.sspi.length > 65535) {
          offset = fixedData.writeUInt16LE(65535, offset);
        } else {
          offset = fixedData.writeUInt16LE(this.sspi.length, offset);
        }

        buffers.push(this.sspi);
      } else {
        offset = fixedData.writeUInt16LE(0, offset);
      }

      // ibAtchDBFile: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cchAtchDBFile: 2-byte
      if (this.attachDbFile) {
        var _buffer8 = new Buffer(this.attachDbFile, 'ucs2');

        offset = fixedData.writeUInt16LE(_buffer8.length / 2, offset);
        dataOffset += _buffer8.length;

        buffers.push(_buffer8);
      } else {
        offset = fixedData.writeUInt16LE(0, offset);
      }

      // ibChangePassword: 2-byte
      offset = fixedData.writeUInt16LE(dataOffset, offset);

      // cchChangePassword: 2-byte
      if (this.changePassword) {
        var _buffer9 = new Buffer(this.changePassword, 'ucs2');

        offset = fixedData.writeUInt16LE(_buffer9.length / 2, offset);
        dataOffset += _buffer9.length;

        buffers.push(_buffer9);
      } else {
        offset = fixedData.writeUInt16LE(0, offset);
      }

      // cbSSPILong: 4-byte
      if (this.sspi && this.sspi.length > 65535) {
        fixedData.writeUInt32LE(this.sspi.length, offset);
      } else {
        fixedData.writeUInt32LE(0, offset);
      }

      var data = Buffer.concat(buffers);
      data.writeUInt32LE(data.length, 0);
      return data;
    }
  }, {
    key: 'buildOptionFlags1',
    value: function buildOptionFlags1() {
      var flags1 = FLAGS_1.ENDIAN_LITTLE | FLAGS_1.CHARSET_ASCII | FLAGS_1.FLOAT_IEEE_754 | FLAGS_1.BCP_DUMPLOAD_OFF | FLAGS_1.USE_DB_OFF | FLAGS_1.SET_LANG_WARN_ON;
      if (this.initDbFatal) {
        flags1 |= FLAGS_1.INIT_DB_FATAL;
      } else {
        flags1 |= FLAGS_1.INIT_DB_WARN;
      }
      return flags1;
    }
  }, {
    key: 'buildOptionFlags2',
    value: function buildOptionFlags2() {
      var flags2 = FLAGS_2.INIT_LANG_WARN | FLAGS_2.ODBC_OFF | FLAGS_2.USER_NORMAL;
      if (this.sspi) {
        flags2 |= FLAGS_2.INTEGRATED_SECURITY_ON;
      } else {
        flags2 |= FLAGS_2.INTEGRATED_SECURITY_OFF;
      }
      return flags2;
    }
  }, {
    key: 'buildTypeFlags',
    value: function buildTypeFlags() {
      var typeFlags = TYPE_FLAGS.SQL_DFLT | TYPE_FLAGS.OLEDB_OFF;
      if (this.readOnlyIntent) {
        typeFlags |= TYPE_FLAGS.READ_ONLY_INTENT;
      } else {
        typeFlags |= TYPE_FLAGS.READ_WRITE_INTENT;
      }
      return typeFlags;
    }
  }, {
    key: 'buildOptionFlags3',
    value: function buildOptionFlags3() {
      return FLAGS_3.CHANGE_PASSWORD_NO | FLAGS_3.UNKNOWN_COLLATION_HANDLING;
    }
  }, {
    key: 'scramblePassword',
    value: function scramblePassword(password) {
      for (var b = 0, len = password.length; b < len; b++) {
        var byte = password[b];
        var lowNibble = byte & 0x0f;
        var highNibble = byte >> 4;
        byte = lowNibble << 4 | highNibble;
        byte = byte ^ 0xa5;
        password[b] = byte;
      }
      return password;
    }
  }, {
    key: 'toString',
    value: function toString() {
      var indent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';

      return indent + 'Login7 - ' + sprintf('TDS:0x%08X, PacketSize:0x%08X, ClientProgVer:0x%08X, ClientPID:0x%08X, ConnectionID:0x%08X', this.tdsVersion, this.packetSize, this.clientProgVer, this.clientPid, this.connectionId) + '\n' + indent + '         ' + sprintf('Flags1:0x%02X, Flags2:0x%02X, TypeFlags:0x%02X, Flags3:0x%02X, ClientTimezone:%d, ClientLCID:0x%08X', this.buildOptionFlags1(), this.buildOptionFlags2(), this.buildTypeFlags(), this.buildOptionFlags3(), this.clientTimeZone, this.clientLcid) + '\n' + indent + '         ' + sprintf("Hostname:'%s', Username:'%s', Password:'%s', AppName:'%s', ServerName:'%s', LibraryName:'%s'", this.hostname, this.userName, this.password, this.appName, this.serverName, this.libraryName) + '\n' + indent + '         ' + sprintf("Language:'%s', Database:'%s', SSPI:'%s', AttachDbFile:'%s', ChangePassword:'%s'", this.language, this.database, this.sspi, this.attachDbFile, this.changePassword);
    }
  }]);
  return Login7Payload;
}();