var _ = require('lodash');

var backboneFormatter = require('../formatters/backbone');
var bkOptionsFormatter = require('../formatters/bookshelf-options');
var whereFormatter = require('../formatters/where');
var executeCount = require('../utils/count');

// Bookshelf options keys.
var OPTIONS_KEYS = ['sortBy', 'sortDirection', 'limit', 'offset', 'count', 'withRelated'];

/**
 * Get multiple records from a table.
 *
 * @param options.collection {Collection} a Bookshelf Collection
 * @param options.omit {String[]} a list of req.query parameters to omit
 * from bookshelf's 'where' object
 * @return {function} findAll middleware
 */

module.exports = function (options) {
  options.omit = options.omit || [];

  /**
   * @param {Object} req.where used to query Bookshelf.Model
   * @param {Integer} req.params.offset pagination offset
   * @param {Integer} req.params.limit pagination limit
   * @param {string} req.params.sortBy
   * @param {string} req.params.sortDirection
   * @param {Boolean} req.params.count wether to return result count in
   * metadata
   */
  return function (req, res, next) {
    var bkOpts = bkOptionsFormatter(OPTIONS_KEYS, req.query, options, {
      sortBy: 'id',
      sortDirection: 'desc',
      limit: 20,
      offset: 0
    });

    var where = whereFormatter(_.union(OPTIONS_KEYS, options.omit), req.query);
    var collection = options.collection ? collection.collection.forge() : options.model.collection();

    // Pick array values from where.
    var whereIn = _.pick(where, isArrayFilter);
    where = _.omit(where, isArrayFilter);

    function isArrayFilter(value) {
      return _.isArray(value);
    }

    collection.query('where', where);

    _.forIn(whereIn, function (val, key) {
      collection.query('whereIn', key, val);
    });

    var countQuery = collection.query().clone();

    collection
    .query('offset', bkOpts.offset)
    .query('limit', bkOpts.limit)
    .query('orderBy', bkOpts.sortBy, bkOpts.sortDirection)
    .fetch(bkOpts)
    .exec(function (err, output) {
      if (err) return next(err);

      res.body = backboneFormatter.formatCollection(output);

      // Set metadata on output.
      res.metadata = {
        offset: bkOpts.offset,
        limit: bkOpts.limit,
        count: null
      };

      // If count is not asked, return null as count.
      if (! bkOpts.count) return next(err);

      // Else fetch count then return it.
      executeCount(countQuery, function (err, count) {
        if (err) return next(err);
        res.metadata.count = count;
        next();
      });
    });
  };
};

@@ -1533,16 +1533,56 @@
 Filter);
+%0A%0A    // Remove array values from where.
 %0A    whe
@@ -1726,24 +1726,240 @@
 ', where);%0A%0A
+    var emptyWhereIn = _.some(whereIn, function (val) %7B%0A      return !val.length;%0A    %7D);%0A%0A    // If a whereIn is empty, we return no results.%0A    if (emptyWhereIn) %7B%0A      res.body = %5B%5D;%0A      return next();%0A    %7D%0A%0A
     _.forIn(
@@ -2108,24 +2108,26 @@
 lection%0A    
+  
 .query('offs
@@ -2146,24 +2146,26 @@
 offset)%0A    
+  
 .query('limi
@@ -2182,24 +2182,26 @@
 .limit)%0A    
+ 
+ 
 .query('orde
@@ -2247,16 +2247,18 @@
 on)%0A    
+  
 .fetch(b
@@ -2268,16 +2268,18 @@
 ts)%0A    
+ 
+ 
 .exec(fu
@@ -2303,24 +2303,26 @@
 ut) %7B%0A      
+  
 if (err) ret
@@ -2339,24 +2339,26 @@
 rr);%0A%0A      
+ 
+ 
 res.body = b
@@ -2407,16 +2407,18 @@
 %0A%0A      
+  
 // Set m
@@ -2438,24 +2438,26 @@
 tput.%0A      
+ 
+ 
 res.metadata
@@ -2461,16 +2461,18 @@
 ata = %7B%0A
+  
         
@@ -2498,24 +2498,26 @@
 et,%0A        
+ 
+ 
 limit: bkOpt
@@ -2533,16 +2533,18 @@
         
+  
 count: n
@@ -2557,12 +2557,16 @@
     
+ 
+ 
 %7D;%0A%0A
+  
     
@@ -2625,14 +2625,15 @@
     
+ 
+ 
 if (!
- 
 bkOp
@@ -2657,24 +2657,26 @@
 next(err);%0A%0A
+  
       // Els
@@ -2711,16 +2711,18 @@
 .%0A      
+  
 executeC
@@ -2758,24 +2758,26 @@
 r, count) %7B%0A
+  
         if (
@@ -2799,32 +2799,34 @@
 t(err);%0A        
+  
 res.metadata.cou
@@ -2845,16 +2845,18 @@
         
+  
 next();%0A
@@ -2861,20 +2861,24 @@
 ;%0A      
+  
 %7D);%0A
+  
     %7D);%0A

send no results if whereIn is empty