"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _collation = require("../collation");
var _token = require("./token");
var _helpers = require("./helpers");
const types = {
  1: {
    name: 'DATABASE',
    event: 'databaseChange'
  },
  2: {
    name: 'LANGUAGE',
    event: 'languageChange'
  },
  3: {
    name: 'CHARSET',
    event: 'charsetChange'
  },
  4: {
    name: 'PACKET_SIZE',
    event: 'packetSizeChange'
  },
  7: {
    name: 'SQL_COLLATION',
    event: 'sqlCollationChange'
  },
  8: {
    name: 'BEGIN_TXN',
    event: 'beginTransaction'
  },
  9: {
    name: 'COMMIT_TXN',
    event: 'commitTransaction'
  },
  10: {
    name: 'ROLLBACK_TXN',
    event: 'rollbackTransaction'
  },
  13: {
    name: 'DATABASE_MIRRORING_PARTNER',
    event: 'partnerNode'
  },
  17: {
    name: 'TXN_ENDED'
  },
  18: {
    name: 'RESET_CONNECTION',
    event: 'resetConnection'
  },
  20: {
    name: 'ROUTING_CHANGE',
    event: 'routingChange'
  }
};
function _readNewAndOldValue(buf, offset, length, type) {
  switch (type.name) {
    case 'DATABASE':
    case 'LANGUAGE':
    case 'CHARSET':
    case 'PACKET_SIZE':
    case 'DATABASE_MIRRORING_PARTNER':
      {
        let newValue;
        ({
          offset,
          value: newValue
        } = (0, _helpers.readBVarChar)(buf, offset));
        let oldValue;
        ({
          offset,
          value: oldValue
        } = (0, _helpers.readBVarChar)(buf, offset));
        switch (type.name) {
          case 'PACKET_SIZE':
            return new _helpers.Result(new _token.PacketSizeEnvChangeToken(parseInt(newValue), parseInt(oldValue)), offset);
          case 'DATABASE':
            return new _helpers.Result(new _token.DatabaseEnvChangeToken(newValue, oldValue), offset);
          case 'LANGUAGE':
            return new _helpers.Result(new _token.LanguageEnvChangeToken(newValue, oldValue), offset);
          case 'CHARSET':
            return new _helpers.Result(new _token.CharsetEnvChangeToken(newValue, oldValue), offset);
          case 'DATABASE_MIRRORING_PARTNER':
            return new _helpers.Result(new _token.DatabaseMirroringPartnerEnvChangeToken(newValue, oldValue), offset);
        }
        throw new Error('unreachable');
      }
    case 'SQL_COLLATION':
    case 'BEGIN_TXN':
    case 'COMMIT_TXN':
    case 'ROLLBACK_TXN':
    case 'RESET_CONNECTION':
      {
        let newValue;
        ({
          offset,
          value: newValue
        } = (0, _helpers.readBVarByte)(buf, offset));
        let oldValue;
        ({
          offset,
          value: oldValue
        } = (0, _helpers.readBVarByte)(buf, offset));
        switch (type.name) {
          case 'SQL_COLLATION':
            {
              const newCollation = newValue.length ? _collation.Collation.fromBuffer(newValue) : undefined;
              const oldCollation = oldValue.length ? _collation.Collation.fromBuffer(oldValue) : undefined;
              return new _helpers.Result(new _token.CollationChangeToken(newCollation, oldCollation), offset);
            }
          case 'BEGIN_TXN':
            return new _helpers.Result(new _token.BeginTransactionEnvChangeToken(newValue, oldValue), offset);
          case 'COMMIT_TXN':
            return new _helpers.Result(new _token.CommitTransactionEnvChangeToken(newValue, oldValue), offset);
          case 'ROLLBACK_TXN':
            return new _helpers.Result(new _token.RollbackTransactionEnvChangeToken(newValue, oldValue), offset);
          case 'RESET_CONNECTION':
            return new _helpers.Result(new _token.ResetConnectionEnvChangeToken(newValue, oldValue), offset);
        }
        throw new Error('unreachable');
      }
    case 'ROUTING_CHANGE':
      {
        let routePacket;
        ({
          offset,
          value: routePacket
        } = (0, _helpers.readUsVarByte)(buf, offset));
        let oldValue;
        ({
          offset,
          value: oldValue
        } = (0, _helpers.readUsVarByte)(buf, offset));

        // Routing Change:
        // Byte 1: Protocol (must be 0)
        // Bytes 2-3 (USHORT): Port number
        // Bytes 4-5 (USHORT): Length of server data in unicode (2byte chars)
        // Bytes 6-*: Server name in unicode characters
        const protocol = routePacket.readUInt8(0);
        if (protocol !== 0) {
          throw new Error('Unknown protocol byte in routing change event');
        }
        const port = routePacket.readUInt16LE(1);
        const serverLen = routePacket.readUInt16LE(3);
        // 2 bytes per char, starting at offset 5
        const server = routePacket.toString('ucs2', 5, 5 + serverLen * 2);
        const newValue = {
          protocol: protocol,
          port: port,
          server: server
        };
        return new _helpers.Result(new _token.RoutingEnvChangeToken(newValue, oldValue), offset);
      }
    default:
      {
        console.error('Tedious > Unsupported ENVCHANGE type ' + type.name);

        // skip unknown bytes
        return new _helpers.Result(undefined, offset + length - 1);
      }
  }
}
function envChangeParser(buf, offset, _options) {
  let tokenLength;
  ({
    offset,
    value: tokenLength
  } = (0, _helpers.readUInt16LE)(buf, offset));
  if (buf.length < offset + tokenLength) {
    throw new _helpers.NotEnoughDataError(offset + tokenLength);
  }
  let typeNumber;
  ({
    offset,
    value: typeNumber
  } = (0, _helpers.readUInt8)(buf, offset));
  const type = types[typeNumber];
  if (!type) {
    console.error('Tedious > Unsupported ENVCHANGE type ' + typeNumber);
    return new _helpers.Result(undefined, offset + tokenLength - 1);
  }
  return _readNewAndOldValue(buf, offset, tokenLength, type);
}
var _default = exports.default = envChangeParser;
module.exports = envChangeParser;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,[encoded data, 15408 characters]