var http    = require('http'),
    cheerio = require('cheerio'),
    _       = require('lodash'),
    async   = require('async');

function ScraperBoknett() {}

_.extend(ScraperBoknett.prototype, {
    getReviewPage: function(offset, callback) {
        offset   = offset || 0;
        callback = callback || function() {};

        var data = '';

        var options = {
            host: 'www.boknett.no',
            path: '/Anmeldelser/(offset)/' + offset
        };

        http.get(options, function(res) {
            res.on('data', function(chunk) {
                data += chunk;
            }).on('end', function() {
                callback(null, data);
            }).on('error', function(err) {
                callback(true, []);
            });
        });
    },

    normalizeSource: function(source) {
        return source.toLowerCase().replace(" ", "-");
    },

    getReviewLinksFromPage: function(html) {
        var $       = cheerio.load(html),
            reviews = $('.reviews .review');

        if (!reviews.length) {
            return false;
        }

        return _.map(reviews, function(review) {
            var review = $(review);

            return {
                url: review.find('a').attr('href'),
                author: review.find('h2').text(),
                title: review.find('h1').text(),
                source: this.normalizeSource(review.find('.source em').text())
            };
        }.bind(this));
    },

    getReviewUrls: function(limit, sources, callback) {
        var highestOffset = 0,
            result        = [],
            resultLength  = 0,
            stop          = false;

        // Set up the queue and worker
        var queue = async.queue(function(task, done) {
            this.getReviewPage(task.offset, function(err, res) {
                var reviews = this.getReviewLinksFromPage(res);

                if (!reviews) {
                    stop = true;
                    queue.empty();
                    done();

                    return;
                }

                result = result.concat(_.filter(reviews, function(review) {
                    return _.contains(sources, review.source);
                }));

                resultLength = result.length;

                done();
            }.bind(this));
        }.bind(this), 10);

        // Callback called when queue is emptied by the worker
        queue.empty = function() {
            if (stop || resultLength >= limit) {
                if (stop) {
                    queue.kill();
                }

                if (resultLength >= limit) {
                    result = result.slice(0, limit);
                }

                callback(null, result);
            } else if (resultLength < limit) {
                for (var i = 0; i < 10; i++) {
                    queue.push({ offset: (highestOffset += 30)});
                }
            }
        };

        // Add ten tasks to the queue
        for (var i = 0; i < 10; i++) {
            queue.push({ offset: (highestOffset += 30)});
        }
    }
});

module.exports = ScraperBoknett;

@@ -1652,47 +1652,8 @@
 e;%0A%0A
-        // Set up the queue and worker%0A
     
@@ -1924,21 +1924,20 @@
   queue.
-empty
+kill
 ();%0A    
@@ -2307,151 +2307,122 @@
     
-// Callback called when queue is emptied by the worker%0A
+var intervalId = setInterval(function() %7B%0A     
        
- 
+if (!
 queue.
-empty = function() %7B%0A            if (stop %7C%7C resultLength %3E= limit) %7B%0A
+idle()) %7B%0A                return;%0A        
     
+%7D%0A%0A
     
@@ -2461,47 +2461,75 @@
     
-    queue.kill();%0A                %7D%0A%0A  
+clearInterval(intervalId);%0A                callback(null, result);%0A
     
@@ -2532,25 +2532,30 @@
             
- 
+%7D else
  if (resultL
@@ -2592,63 +2592,34 @@
     
-    result = result.slice(0, limit);%0A                %7D%0A
+clearInterval(intervalId);
 %0A   
@@ -2644,32 +2644,48 @@
 ack(null, result
+.slice(0, limit)
 );%0A            %7D
@@ -2876,155 +2876,14 @@
    %7D
-;%0A%0A        // Add ten tasks to the queue%0A        for (var i = 0; i %3C 10; i++) %7B%0A            queue.push(%7B offset: (highestOffset += 30)%7D);%0A        %7D
+, 50);
 %0A   

Revert "Rewrote the logic. No longer using stone age timeout, but the empty callback triggered by async.queue".