var fs  = require('fs');
var pth = require('path');




function FASTAReader(fpath) {
  this.fpath = fpath;
  this.result = fparse(fpath);
}




FASTAReader.prototype.fetch = function(id, start, length) {
  if (!this.result[id]) {
    return false;
  }
  var unit = this.result[id];
  return ffetch(this.fpath, unit, start, length);
}





function ffetch(fpath, unit, start, length) {
  var fd        = fs.openSync(fpath, 'r');
  var startIdx  = pos2index(start, unit.id.length + 2, unit.linelen);
  var endIdx    = Math.min(unit.length, pos2index(length + start, unit.id.length + 2, unit.linelen));
  if (endIdx - startIdx <= 0) {
    return '';
  }
  try {
    var read      = fs.readSync(fd, endIdx - startIdx, startIdx + unit.start);
  }
  catch(e) {
    return '';
  }
  fs.closeSync(fd);
  return read[0].split('\n').join('');
}




function pos2index(pos, prelen, linelen) {
  return prelen + pos -1 + Math.floor( (pos -1)/linelen );
}







function fparse(fpath) {
  if (pth.existsSync(!fpath)) {
    process.stderr.write(config_file + ': No such file.\n');
    return false;
  }

  var fd        = fs.openSync(fpath, 'r');
  var read      = '';
  var pos       = 0;
  var start     = 0;
  var remnant   = '';
  var result    = {};
  var buffsize  = 1000;
  var summary   = null;
  var length    = 0;
  var emptyline = 0;
  do {
    read = fs.readSync(fd, buffsize, pos);

    var lines = (remnant + read[0]).split('\n');
    remnant = lines.pop();

    lines.forEach(function(line) {
      if (line == '') {
        emptyline++;
      }
      else if (line.charAt(0) == '>') {
        // register a previous summary
        if (summary) {
          summary.length = length - emptyline;
          result[summary.id] = summary;
        }
        start += length;
        emptyline = 0;
        length    = 0;
        // make a new summary
        summary = {id: line.slice(1), start: start, linelen: 0};
      }
      else {
        if (!summary.linelen) {
          summary.linelen = line.length;
        }
      }
      length += line.length + 1;
    });
    pos = pos + read[1];
  }
  while (read[1] > 0);

  // end
  summary.length += remnant.length;
  result[summary.id] = summary;

  fs.closeSync(fd);
  return result;
}




FASTAReader.parse = fparse;
FASTAReader.fetch = ffetch;
FASTAReader.pos2index = pos2index;

module.exports = FASTAReader;

@@ -836,108 +836,793 @@
 %0A%0A%0A%0A
-%0Afunction pos2index(pos, prelen, linelen) %7B%0A  return prelen + pos -1 + Math.floor( (pos -1)/linelen 
+/**%0A * FASTAReader.pos2index%0A * convert DNA base position to character index%0A * @param number  pos     : DNA base position%0A * @param number  prelen  : header data length%0A * @param number  linelen : one line length%0A * @return number : character index%0A */%0Afunction pos2index(pos, prelen, linelen) %7B%0A  return prelen + pos -1 + Math.floor( (pos -1)/linelen );%0A%7D%0A%0A%0A/**%0A * FASTAReader.idx2pos%0A * convert charcter index to DNA base position%0A * @param number  idx     : character index%0A * @param number  prelen  : header data length%0A * @param number  linelen : one line length%0A * @return number : DNA base position%0A */%0Afunction idx2pos(idx, prelen, linelen) %7B%0A  prelen = prelen %7C%7C 0;%0A  linelen = linelen %7C%7C 50;%0A  return Math.max(0, idx +1 - prelen - Math.floor((idx +1 - prelen)/(linelen + 1))
 );%0A%7D
@@ -3009,16 +3009,46 @@
 s2index;
+%0AFASTAReader.idx2pos= idx2pos;
 %0A%0Amodule

add idx2pos