// Generated by CoffeeScript 1.10.0
(function() {
  var JSON_COLUMN_ID, MAX, TYPES, Table, declare, ref,
    slice = [].slice;

  ref = require('./datatypes'), TYPES = ref.TYPES, declare = ref.declare;

  MAX = 65535;

  JSON_COLUMN_ID = 'JSON_F52E2B61-18A1-11d1-B105-00805F49916B';

  Table = (function() {
    function Table(name) {
      var buffer, char, cursor, escaped, length, path;
      if (name) {
        length = name.length;
        cursor = -1;
        buffer = '';
        escaped = false;
        path = [];
        while (++cursor < length) {
          char = name.charAt(cursor);
          if (char === '[') {
            if (escaped) {
              buffer += char;
            } else {
              escaped = true;
            }
          } else if (char === ']') {
            if (escaped) {
              escaped = false;
            } else {
              throw new Error("Invalid table name.");
            }
          } else if (char === '.') {
            if (escaped) {
              buffer += char;
            } else {
              path.push(buffer);
              buffer = '';
            }
          } else {
            buffer += char;
          }
        }
        if (buffer) {
          path.push(buffer);
        }
        switch (path.length) {
          case 1:
            this.name = path[0];
            this.schema = null;
            this.database = null;
            break;
          case 2:
            this.name = path[1];
            this.schema = path[0];
            this.database = null;
            break;
          case 3:
            this.name = path[2];
            this.schema = path[1];
            this.database = path[0];
        }
        this.path = "" + (this.database ? "[" + this.database + "]." : "") + (this.schema ? "[" + this.schema + "]." : "") + "[" + this.name + "]";
        this.temporary = this.name.charAt(0) === '#';
      }
      this.columns = [];
      this.rows = [];
      Object.defineProperty(this.columns, "add", {
        value: function(name, column, options) {
          if (options == null) {
            options = {};
          }
          if (column == null) {
            throw new Error("Column data type is not defined.");
          }
          if (column instanceof Function) {
            column = column();
          }
          column.name = name;
          column.nullable = options.nullable;
          return this.push(column);
        }
      });
      Object.defineProperty(this.rows, "add", {
        value: function() {
          var values;
          values = 1 <= arguments.length ? slice.call(arguments, 0) : [];
          return this.push(values);
        }
      });
    }


    /*
    	@private
     */

    Table.prototype._makeBulk = function() {
      var col, i, len, ref1;
      ref1 = this.columns;
      for (i = 0, len = ref1.length; i < len; i++) {
        col = ref1[i];
        switch (col.type) {
          case TYPES.Xml:
            col.type = TYPES.NVarChar(MAX).type;
            break;
          case TYPES.UDT:
          case TYPES.Geography:
          case TYPES.Geometry:
            col.type = TYPES.VarBinary(MAX).type;
        }
      }
      return this;
    };

    Table.prototype.declare = function() {
      var col;
      return "create table " + this.path + " (" + (((function() {
        var i, len, ref1, results;
        ref1 = this.columns;
        results = [];
        for (i = 0, len = ref1.length; i < len; i++) {
          col = ref1[i];
          results.push("[" + col.name + "] " + (declare(col.type, col)) + (col.nullable === true ? " null" : col.nullable === false ? " not null" : ""));
        }
        return results;
      }).call(this)).join(', ')) + ")";
    };

    Table.fromRecordset = function(recordset) {
      var col, i, j, len, len1, name, ref1, ref2, row, t;
      t = new this;
      ref1 = recordset.columns;
      for (name in ref1) {
        col = ref1[name];
        t.columns.add(name, {
          type: col.type,
          length: col.length,
          scale: col.scale,
          precision: col.precision
        }, {
          nullable: col.nullable
        });
      }
      if (t.columns.length === 1 && t.columns[0].name === JSON_COLUMN_ID) {
        for (i = 0, len = recordset.length; i < len; i++) {
          row = recordset[i];
          t.rows.add(JSON.stringify(row));
        }
      } else {
        for (j = 0, len1 = recordset.length; j < len1; j++) {
          row = recordset[j];
          (ref2 = t.rows).add.apply(ref2, (function() {
            var k, len2, ref2, results;
            ref2 = t.columns;
            results = [];
            for (k = 0, len2 = ref2.length; k < len2; k++) {
              col = ref2[k];
              results.push(row[col.name]);
            }
            return results;
          })());
        }
      }
      return t;
    };

    return Table;

  })();

  module.exports = Table;

}).call(this);
