// Generated by CoffeeScript 1.7.1
var BulkLoad, DONE_STATUS, EventEmitter, FLAGS, TOKEN_TYPE, WritableTrackingBuffer,
  __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

EventEmitter = require('events').EventEmitter;

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

TOKEN_TYPE = require('./token/token').TYPE;

FLAGS = {
  nullable: 1 << 0,
  caseSen: 1 << 1,
  updateableReadWrite: 1 << 2,
  updateableUnknown: 1 << 3,
  identity: 1 << 4,
  computed: 1 << 5,
  fixedLenCLRType: 1 << 8,
  sparseColumnSet: 1 << 10,
  hidden: 1 << 13,
  key: 1 << 14,
  nullableUnknown: 1 << 15
};

DONE_STATUS = {
  FINAL: 0x00,
  MORE: 0x1,
  ERROR: 0x2,
  INXACT: 0x4,
  COUNT: 0x10,
  ATTN: 0x20,
  SRVERROR: 0x100
};

BulkLoad = (function(_super) {
  __extends(BulkLoad, _super);

  BulkLoad.prototype.error = null;

  BulkLoad.prototype.canceled = false;

  function BulkLoad(table, options, callback) {
    this.table = table;
    this.options = options;
    this.callback = callback;
    this.columns = [];
    this.columnsByName = {};
    this.rowsData = new WritableTrackingBuffer(1024, 'ucs2', true);
    this.firstRowWritten = false;
  }

  BulkLoad.prototype.addColumn = function(name, type, options) {
    var column, _ref, _ref1, _ref2;
    if (options == null) {
      options = {};
    }
    if (this.firstRowWritten) {
      throw new Error('Columns cannot be added to bulk insert after the first row has been written.');
    }
    column = {
      type: type,
      name: name,
      value: null,
      output: options.output || (options.output = false),
      length: options.length,
      precision: options.precision,
      scale: options.scale,
      objName: options.objName || name,
      nullable: options.nullable
    };
    if ((type.id & 0x30) === 0x20) {
      column.length = (_ref = column.length) != null ? _ref : typeof type.resolveLength === "function" ? type.resolveLength(column) : void 0;
    }
    if (type.hasPrecision) {
      column.precision = (_ref1 = column.precision) != null ? _ref1 : typeof type.resolvePrecision === "function" ? type.resolvePrecision(column) : void 0;
    }
    if (type.hasScale) {
      column.scale = (_ref2 = column.scale) != null ? _ref2 : typeof type.resolveScale === "function" ? type.resolveScale(column) : void 0;
    }
    this.columns.push(column);
    return this.columnsByName[name] = column;
  };

  BulkLoad.prototype.addRow = function(row) {
    var arr, arrTemp, c, i, _i, _j, _len, _len1, _ref, _results;
    this.firstRowWritten = true;
    if (arguments.length > 1 || !row || typeof row !== 'object') {
      arrTemp = new Array(arguments.length);
      for (i = _i = 0, _len = arguments.length; _i < _len; i = ++_i) {
        c = arguments[i];
        arrTemp[i] = c;
      }
      row = arrTemp;
    }
    this.rowsData.writeUInt8(TOKEN_TYPE.ROW);
    arr = row instanceof Array;
    _ref = this.columns;
    _results = [];
    for (i = _j = 0, _len1 = _ref.length; _j < _len1; i = ++_j) {
      c = _ref[i];
      _results.push(c.type.writeParameterData(this.rowsData, {
        length: c.length,
        scale: c.scale,
        precision: c.precision,
        value: row[arr ? i : c.objName]
      }, this.options));
    }
    return _results;
  };

  BulkLoad.prototype.getBulkInsertSql = function() {
    var c, i, sql, _i, _len, _ref;
    sql = 'insert bulk ' + this.table + '(';
    _ref = this.columns;
    for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
      c = _ref[i];
      if (i !== 0) {
        sql += ', ';
      }
      sql += "[" + c.name + "] " + (c.type.declaration(c));
    }
    sql += ')';
    return sql;
  };

  BulkLoad.prototype.getTableCreationSql = function() {
    var c, i, sql, _i, _len, _ref;
    sql = 'CREATE TABLE ' + this.table + '(\n';
    _ref = this.columns;
    for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
      c = _ref[i];
      if (i !== 0) {
        sql += ',\n';
      }
      sql += "[" + c.name + "] " + (c.type.declaration(c));
      if (c.nullable !== void 0) {
        sql += " " + (c.nullable ? "NULL" : "NOT NULL");
      }
    }
    sql += '\n)';
    return sql;
  };

  BulkLoad.prototype.getPayload = function() {
    var done, length, metaData, payload, rows, status, tBuf;
    metaData = this.getColMetaData();
    length = metaData.length;
    rows = this.rowsData.data;
    length += rows.length;
    tBuf = new WritableTrackingBuffer(this.options.tdsVersion < "7_2" ? 9 : 13);
    tBuf.writeUInt8(TOKEN_TYPE.DONE);
    status = DONE_STATUS.FINAL;
    tBuf.writeUInt16LE(status);
    tBuf.writeUInt16LE(0);
    tBuf.writeUInt32LE(0);
    if (this.options.tdsVersion >= "7_2") {
      tBuf.writeUInt32LE(0);
    }
    done = tBuf.data;
    length += done.length;
    payload = new WritableTrackingBuffer(length);
    payload.copyFrom(metaData);
    payload.copyFrom(rows);
    payload.copyFrom(done);
    return payload;
  };

  BulkLoad.prototype.getColMetaData = function() {
    var c, flags, tBuf, _i, _len, _ref;
    tBuf = new WritableTrackingBuffer(100, null, true);
    tBuf.writeUInt8(TOKEN_TYPE.COLMETADATA);
    tBuf.writeUInt16LE(this.columns.length);
    _ref = this.columns;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      c = _ref[_i];
      if (this.options.tdsVersion < "7_2") {
        tBuf.writeUInt16LE(0);
      } else {
        tBuf.writeUInt32LE(0);
      }
      flags = FLAGS.updateableReadWrite;
      if (c.nullable) {
        flags |= FLAGS.nullable;
      } else if (c.nullable === void 0 && this.options.tdsVersion >= "7_2") {
        flags |= FLAGS.nullableUnknown;
      }
      tBuf.writeUInt16LE(flags);
      c.type.writeTypeInfo(tBuf, c, this.options);
      tBuf.writeBVarchar(c.name, 'ucs2');
    }
    return tBuf.data;
  };

  return BulkLoad;

})(EventEmitter);

module.exports = BulkLoad;
