'use strict';
var Parser = require('./parser.js');
var Streamer = require('./streamer.js');

function reducer(item, memo, sep, prependSep) {
  var foo = ''
  , c = new RegExp(sep, 'g')
  , q = new RegExp('"', 'g')
  , n = new RegExp('\n', 'g');

  if (!item) {
    item = '';
  }
  if (typeof item != 'string') {
    var s = item.toString();
    if (s == '[object Object]') {
      item = JSON.stringify(item);
      if (item == '{}') {
        item = '';
      }
    }
    else {
      item = s;
    }
  }
  if (memo || prependSep) {
    foo = memo + sep;
  }
  if (item.search(c) >= 0 || item.search(q) >= 0 || item.search(n) >= 0) {
    foo += '"' + item.replace(q, '""') + '"';
  }
  else {
    foo += '' + item;
  }
  return foo;
}

exports.eol = "\r\n";
exports.separator = ",";

exports.detect = function (input)
{
  var separators = [{c: 0, v: ','}, {c: 0, v: ';'}, {c: 0, v: '|'}, {c: 0, v: '\t'}, {c: 0, v: ':'}, {c: 0, v: null}];
  separators.forEach(function (item, indice) {
      item.c += input.split(item.v).length;
    }
  );
  var max = 0;
  var separator = separators.reduce(function (prev, cur) {
      if (cur.c >= max) {
        max = cur.c;
        return cur.v;
      }
      else {
        return prev;
      }
    }, null
  );
  return separator;
}


exports.stringify = function (input, sep) {
  var ret = '';
  sep = sep || exports.separator;
  if (Array.isArray(input) && !Array.isArray(input[0])) {
    for (var loop = 0; loop < input.length; loop++) {
      ret = reducer(input[loop], ret, sep, loop > 0);
    }
    ret += exports.eol;
  }
  else if (Array.isArray(input) && Array.isArray(input[0])) {
    input.forEach(function (item, index) {
        ret += exports.stringify(item, sep);
      }
    );
  }
  else if (typeof input == 'object') {
    for (var key in input) {
      if (input.hasOwnProperty(key)) {
        ret = reducer(input[key], ret, sep);
      }
    }
    ret += exports.eol;
  }
  else {
    ret = reducer(input, ret, sep) + exports.eol;
  }
  return ret;
}

exports.parse = function (input, sep) {

  var output = [];
  exports.forEach(input, sep, function (row, index) {
      output.push(row);
    }
  )
  return output;
}


exports.forEach = function (input, sep, callback) {
  if (arguments.length < 3) {
    callback = sep;
    sep = ',';
  }
  var i = 0, s = 0, r;
  while (r = exports.read(input.slice(s), sep, function (fields) {
        callback(fields, i++);
      }
    )
  ) {
    s += r;
  }
}

exports.read = function (input, sep, callback) {
  if (arguments.length < 3) {
    callback = sep;
    sep = ',';
  }
  var csv = new Parser(input, sep);
  var fields = csv.Row();
  callback(fields);
  return csv.pointer;
}

exports.readAll = function (input, sep, callback) {
  if (arguments.length < 3) {
    callback = sep;
    sep = ',';
  }
  var csv = new Parser(input, sep);
  var rows = csv.File();
  callback(rows);
  return csv.pointer;
}


exports.fetch = function (input, sep) {
  var output;
  exports.read(input, sep, function (fields) {
      output = fields;
    }
  );
  return output;

}

exports.createStream = function (options) {
  return new Streamer(options);
}



@@ -2870,46 +2870,142 @@
 ;%0A  
-callback(rows
+var ret = 0;%0A  if (csv.pointer %3C this.buffer.length) %7B%0A    ret = csv.pointer;%0A  %7D%0A  else %7B%0A    rows.pop(
 );%0A
+  
   ret
-urn
+ =
  csv.
-p
+lineP
 ointer;%0A
 %7D%0A%0A%0A
@@ -3000,16 +3000,52 @@
 ointer;%0A
+  %7D%0A  callback(rows);%0A  return ret;%0A
 %7D%0A%0A%0Aexpo

fix return of readAll