'use strict';

var through = require('through');
var mergeStream = require('mergesort-stream');
var offset = require('offset-stream');
var limit = require('limit-stream');
var extend = require('xtend');

function defaultComparator(x, y) {
  return x > y ? 1 : x < y ? -1 : 0;
}

function makeComparator(options) {
  var comparator = options.comparator || defaultComparator;
  if (options.values) {
    return function (x, y) {
      return comparator(x.key, y.key);
    };
  }
  return comparator;
}

function createMergedReadStream(db, options) {
  options = options || {};

  if (!options.ranges || options.ranges.length === 0) {
    return db.createReadStream(options);
  }

  options = extend({ keys: true, values: true }, options);
  var comparator = makeComparator(options);

  var sourceStreams = options.ranges.map(function (range) {
    // Force keys for comparison
    return db.createReadStream(extend(options, range, { keys: true }));
  });
  var stream = mergeStream(comparator, sourceStreams);
  if (options.skip) {
    stream = stream.pipe(offset(options.skip));
  }
  if (options.limit) {
    stream = stream.pipe(limit(options.limit));
  }
  if (!options.keys && options.values) {
    stream = stream.pipe(through(function (data) {
      this.queue(data.value);
    }));
  }
  stream.on('end', function () {
    sourceStreams.forEach(function (source) {
      source.destroy();
    });
  });
  return stream;
}

function setup(db) {
  db.createMergedReadStream = db.mergedReadStream = function (options) {
    return createMergedReadStream(db, options);
  };
  db.createMergedKeyStream = db.mergedKeyStream = function (options) {
    return createMergedReadStream(db, extend(options, { keys: true, values: false }));
  };
  db.createMergedValueStream = db.mergedValueStream = function (options) {
    return createMergedReadStream(db, extend(options, { keys: false, values: true }));
  };

  return db;
}

module.exports = setup;

@@ -51,22 +51,16 @@
 ar merge
-Stream
  = requi
@@ -562,17 +562,16 @@
  %7C%7C %7B%7D;%0A
-%0A
   if (!o
@@ -663,17 +663,16 @@
 s);%0A  %7D%0A
-%0A
   option
@@ -725,52 +725,8 @@
 ns);
-%0A  var comparator = makeComparator(options);
 %0A%0A  
@@ -735,22 +735,16 @@
 r source
-Stream
 s = opti
@@ -809,12 +809,12 @@
 mpar
-ison
+ator
 %0A   
@@ -912,16 +912,14 @@
 erge
-Stream(c
+(makeC
 ompa
@@ -927,16 +927,25 @@
 ator
+(options)
 , source
 Stre
@@ -940,22 +940,16 @@
 , source
-Stream
 s);%0A  if
@@ -1089,24 +1089,81 @@
 imit));%0A  %7D%0A
+  // If we forced keys for the comparator, drop them now%0A
   if (!optio
@@ -1328,22 +1328,16 @@
   source
-Stream
 s.forEac
@@ -1893,17 +1893,16 @@
 );%0A  %7D;%0A
-%0A
   return

tweak names and add comments