var http = require('http'),
	async = require('async'),
	_ = require('underscore');

exports.CheckNPM = function(options) {
	_.extend(this, {
		cache: null,
		dateOffset: 900000, // 15 minutes.	
		packagePageUrl: 'registry.npmjs.org',
		packagePagePath: '/-/all/since'
	}, options);
};

exports.CheckNPM.prototype.checkForUpdates = function(callback) {	
	var _this = this,
		options = {
			host: this.packagePageUrl,
			path: this.packagePagePath + '?stale=update_after&startkey='+ ((new Date().getTime()) - this.dateOffset),
			headers: {
				'User-Agent': 'npm-tweets',
				'Cache-Control': 'max-age=0',
				'Accept': 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
				'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
				'Accept-Encoding': 'text/html',
				'Accept-Language': 'en-US,en;q=0.8'
			}
		},
		req = http.request(options, function(res) {
			res.body = '';

			res.addListener('data', function(chunk) { res.body += chunk; } );
			
			res.addListener('end', function(){
				try {
					var rawPackages = [],
						responseJSON = JSON.parse(res.body);

					Object.keys(responseJSON).forEach(function(key) {
						if (key !== '_updated') rawPackages.push(responseJSON[key]);
					});

					_this.returnNewPackages( rawPackages, callback);
				} catch (e) {
					_this.returnNewPackages([], callback)
				}
			});
		});

		req.addListener('error', function(err) {
			callback(err);
		});

		req.end();
};

exports.CheckNPM.prototype.returnNewPackages = function(rawPackages, callback) {
	this.getNewPackages(rawPackages, function(err, newPackages) {
		callback(err, newPackages);
	});
};

exports.CheckNPM.prototype.getNewPackages = function(rawPackages, callback) {
	var _this = this,
		newPackages = [],
		work = [];

	rawPackages.forEach(function(rawPackage) {
		work.push(function(done) {
			var mungedPackage = _this.mungePackage(rawPackage);

			// Check if this package is a major release.
			if (_this.majorRelease(mungedPackage) && _this.filterPackage(rawPackage)) {

				// Is this key already in the cache?
				_this.cache.inCache(mungedPackage, function(err, inCache) {
					if (!inCache) {

						// if not in cache, add to list of packages to publish.
						_this.cache.add(mungedPackage, function(err) {
							newPackages.unshift(mungedPackage);
							done(err);
						});
					} else {
						done(err);
					}
				});
			} else {
				done();
			}
		});
	});

	// execute work synchronously since
	// for the sake of redis driver.
	async.waterfall(work, function(err) {
		callback(err, newPackages);
	});
};

exports.CheckNPM.prototype.mungePackage = function(rawPackage) {
	
	var distTags = rawPackage['dist-tags'] || {},
		author = rawPackage.author || {};
	
	return {
		author: author.name ? author.name : '',
		version: distTags.latest || false,
		description: rawPackage.description || '',
		name: rawPackage.name,
		url: 'https://npmjs.com/package/' + escape(rawPackage.name)
	}
};

exports.CheckNPM.prototype.majorRelease = function(package) {
	var majorRegex = /([0-9]+\.[0-9]+\.0$)|(0\.0\.1$)/;
	return !!package.version.match(majorRegex);
};

exports.CheckNPM.prototype.filterPackage = function (package) {
  return this.filter ? this.filter(package) : true;
};

@@ -185,17 +185,16 @@
 minutes.
-%09
 %0A%09%09packa
@@ -209,26 +209,24 @@
 l: '
-registry
+skimdb
 .npmjs.
-org
+com
 ',%0A%09
@@ -341,17 +341,16 @@
 lback) %7B
-%09
 %0A%09var _t
@@ -833,21 +833,85 @@
 n;q=0.8'
-%0A%09%09%09%7D
+,%0A%09%09%09%09'host': 'registry.npmjs.org'%0A%09%09%09%7D,%0A%09%09%09rejectUnauthorized: false
 %0A%09%09%7D,%0A%09%09
@@ -1042,19 +1042,16 @@
 k; %7D );%0A
-%09%09%09
 %0A%09%09%09res.
@@ -2699,17 +2699,16 @@
 kage) %7B%0A
-%09
 %0A%09var di
@@ -2783,17 +2783,16 @@
  %7C%7C %7B%7D;%0A
-%09
 %0A%09return

switch to reading skimdb