// Generated by CoffeeScript 1.7.1
(function() {
  var exports, isArrayOfArrays, printer;

  exports = module.exports = function(arr, opts) {
    if ((typeof arr) === 'object') {
      if (!Array.isArray(arr)) {
        return exports.tablifySingleDict(arr, opts);
      } else if (isArrayOfArrays(arr)) {
        return exports.tablifyArrays(arr, opts);
      } else {
        return exports.tablifyDicts(arr, opts);
      }
    } else {
      throw new Error('tablify cannot handle non-objects');
    }
  };

  exports.tablify = exports;

  exports.tablifySingleDict = function(o, opts) {
    var arr, k, v;
    arr = [];
    for (k in o) {
      v = o[k];
      arr.push([k, v]);
    }
    arr.sort(function(r1, r2) {
      return r1[0].localeCompare(r2[0]);
    });
    return exports.tablifyArrays(arr, opts);
  };

  exports.tablifyArrays = function(arr, opts) {
    var c, row, _i, _len;
    c = new printer(opts);
    for (_i = 0, _len = arr.length; _i < _len; _i++) {
      row = arr[_i];
      c.push(row);
    }
    return c.stringify();
  };

  exports.tablifyDicts = function(arr, opts) {

    /*
    takes an array of dictionaries that may have different keys
     */
    var c, dict, i, k, known_keys, row, _i, _j, _k, _len, _len1, _len2, _ref;
    opts = opts || {};
    if (opts.has_header == null) {
      opts.has_header = true;
    }
    if (opts.show_index == null) {
      opts.show_index = true;
    }
    if (!opts.keys) {
      known_keys = {};
      for (_i = 0, _len = arr.length; _i < _len; _i++) {
        dict = arr[_i];
        for (k in dict) {
          known_keys[k] = true;
        }
      }
      opts.keys = (function() {
        var _results;
        _results = [];
        for (k in known_keys) {
          _results.push(k);
        }
        return _results;
      })();
      opts.keys.sort();
    }
    c = new printer(opts);
    if (opts.has_header) {
      row = (function() {
        var _j, _len1, _ref, _results;
        _ref = opts.keys;
        _results = [];
        for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
          k = _ref[_j];
          _results.push(k);
        }
        return _results;
      })();
      c.push(row);
    }
    for (i = _j = 0, _len1 = arr.length; _j < _len1; i = ++_j) {
      dict = arr[i];
      row = [];
      _ref = opts.keys;
      for (_k = 0, _len2 = _ref.length; _k < _len2; _k++) {
        k = _ref[_k];
        row.push((dict[k] != null ? dict[k] : null));
      }
      c.push(row);
    }
    return c.stringify();
  };

  printer = (function() {
    function printer(opts) {
      this.opts = opts || {};
      this.opts.spacer = this.opts.spacer != null ? this.opts.spacer : " | ";
      this.opts.row_start = this.opts.row_start != null ? this.opts.row_start : "| ";
      this.opts.row_end = this.opts.row_end != null ? this.opts.row_end : " |";
      this.opts.row_sep_char = this.opts.row_sep_char != null ? this.opts.row_sep_char : "-";
      this.opts.has_header = this.opts.has_header != null ? this.opts.has_header : false;
      this.opts.show_index = this.opts.show_index != null ? this.opts.show_index : false;
      this.rows = [];
      this.col_widths = [];
      if (this.opts.border === false) {
        opts.spacer = ' ';
        this.opts.row_start = this.opts.row_end = this.opts.row_sep_char = '';
      }
    }

    printer.prototype.push = function(row_to_push) {
      var cell, i, row, row_num, _i, _len, _results;
      row = (function() {
        var _i, _len, _results;
        _results = [];
        for (_i = 0, _len = row_to_push.length; _i < _len; _i++) {
          cell = row_to_push[_i];
          _results.push(cell);
        }
        return _results;
      })();
      if (this.opts.show_index) {
        row_num = this.rows.length;
        if (this.opts.has_header) {
          row_num--;
        }
        if (row_num < 0) {
          row.splice(0, 0, "#");
        } else {
          row.splice(0, 0, row_num);
        }
      }
      this.rows.push(row);
      _results = [];
      for (i = _i = 0, _len = row.length; _i < _len; i = ++_i) {
        cell = row[i];
        if ((this.col_widths[i] == null) || (this.col_widths[i] < this.len(cell))) {
          _results.push(this.col_widths[i] = this.len(cell));
        } else {
          _results.push(void 0);
        }
      }
      return _results;
    };

    printer.prototype.stringify = function() {
      var i, j, line, row, strs, total_width, width, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
      strs = [];
      total_width = this.opts.row_start.length + this.opts.row_end.length;
      _ref = this.col_widths;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        width = _ref[_i];
        total_width += width;
      }
      total_width += this.opts.spacer.length * (this.col_widths.length - 1);
      if (this.opts.row_sep_char.length) {
        strs.push(this.chars(this.opts.row_sep_char, total_width));
      }
      _ref1 = this.rows;
      for (j = _j = 0, _len1 = _ref1.length; _j < _len1; j = ++_j) {
        row = _ref1[j];
        line = this.opts.row_start;
        _ref2 = this.col_widths;
        for (i = _k = 0, _len2 = _ref2.length; _k < _len2; i = ++_k) {
          width = _ref2[i];
          line += this.ljust((row[i] != null ? row[i] : ""), width);
          if (i < this.col_widths.length - 1) {
            line += this.opts.spacer;
          }
        }
        line += this.opts.row_end;
        strs.push(line);
        if (this.opts.row_sep_char) {
          if ((j === 0) && this.opts.has_header) {
            strs.push(this.chars(this.opts.row_sep_char, total_width));
          }
        }
      }
      if (this.opts.row_sep_char.length) {
        strs.push(this.chars(this.opts.row_sep_char, total_width));
      }
      return strs.join("\n");
    };

    printer.prototype.toStr = function(o) {
      var e;
      if (o === null) {
        return "null";
      } else if ((typeof o) === "undefined") {
        return "";
      } else if ((typeof o) === "object") {
        try {
          return JSON.stringify(o);
        } catch (_error) {
          e = _error;
          return "[" + e.message + "]";
        }
      } else {
        return o.toString();
      }
    };

    printer.prototype.len = function(o) {
      return this.toStr(o).length;
    };

    printer.prototype.chars = function(c, num) {
      var i;
      return ((function() {
        var _i, _results;
        _results = [];
        for (i = _i = 0; 0 <= num ? _i < num : _i > num; i = 0 <= num ? ++_i : --_i) {
          _results.push(c);
        }
        return _results;
      })()).join("");
    };

    printer.prototype.ljust = function(o, num) {
      return "" + (this.toStr(o)) + (this.chars(' ', num - this.len(o)));
    };

    printer.prototype.rjust = function(o, num) {
      return "" + (this.chars(' ', num - this.len(o))) + (this.toStr(o));
    };

    return printer;

  })();

  isArrayOfArrays = function(arr) {
    var x, _i, _len;
    for (_i = 0, _len = arr.length; _i < _len; _i++) {
      x = arr[_i];
      if (!(Array.isArray(x))) {
        return false;
      }
    }
    return true;
  };

}).call(this);
