'use strict';

var github = require('./github');
var npm = require('./npm');
var db = require('./db');
var email = require('./email');

var semver = require('semver');

var cache = {};


db.readSubscriptions(function(error, subscriptions) {
	if (error) {
		console.error(error);
		return;
	}

	cache = {};
	for(var i = 0, n = subscriptions.length; i < n; i++) {
		var subscription = subscriptions[i];

		var user = github.getUserFromUrl(subscription.repourl);
		var repo = github.getRepoFromUrl(subscription.repourl);
		if (!user) {
			console.error('db:readSubscriptions user invalid for ' + subscription.repourl);
		} else if (!repo) {
			console.error('db:readSubscriptions repo invalid for ' + subscription.repourl);
		} else {
			github.getPackageJson(user, repo, processPackage(subscription));
		}
	}
});

function cacheIt(packageName, version, timeStamp, isNewRelease) {
	cache[packageName] = {
		version: version,
		timeStamp: timeStamp,
		isNewRelease: isNewRelease
	};
}

function checkPackage(emailAdress, repourl, packageName, expectedRange) {
	getLatestVersion(packageName, function(error, latestVersion, isNew) {
		if (error) {
			console.error(error);
			return;
		}
		if (isNew && semver.satisfies(latestVersion, expectedRange)) {
			email.send(emailAdress, repourl, packageName, expectedRange, latestVersion);
		}
	});
}

function isStillValid(timeStamp) {
	return new Date(timeStamp) >= new Date().setDate(-1);
}

function getLatestVersion(packageName, callback) {
	var cached = cache[packageName];
	if (cached) {
		callback(null, cached.version, cached.isNewRelease);
		return;
	}

	db.getPackageByName(packageName, function(error, packages) {
		if (error) {
			console.error(error);
			callback(error);
			return;
		}
		if (packages.length === 0) {
			npm.getLatestVersion(packageName, function(error, version) {
				var timeStamp = new Date().toUTCString();
				db.createPackage(packageName, version, timeStamp);
				cacheIt(packageName, version, timeStamp, false);
				callback(null, version, false);
			});
			return;
		}
		// TODO: is this needed, when there's a cache?
		var pack = packages[0];
		if (isStillValid(pack.timestamp)) {
			cacheIt(packageName, pack.version, pack.timeStamp, false);
			callback(null, pack.version, false);
			return;
		}

		npm.getLatestVersion(packageName, function(error, version) {
			var timeStamp = new Date().toUTCString();
			db.updatePackageByName(packageName, version, timeStamp);
			var isNewRelease = semver.gt(version, semver.clean(pack.version));
			cacheIt(packageName, version, timeStamp, isNewRelease);
			callback(null, version, isNewRelease);
		});
	});
}

function processPackage(subscription) {
	return function(error, json) {
		if (error) {
			console.error(error);
			return;
		}

		var packageName;
		for (packageName in json.dependencies) {
			checkPackage(subscription.email, subscription.repourl, packageName, json.dependencies[packageName]);
		}
		for (packageName in json.devDependencies) {
			checkPackage(subscription.email, subscription.repourl, packageName, json.devDependencies[packageName]);
		}
	};
}
'use strict';

var github = require('./github');
var npm = require('./npm');
var db = require('./db');
var email = require('./email');

var semver = require('semver');
var _ = require('underscore');


var cache = {};

var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);

npm.getLatestPackages(yesterday, function(error, packages) {
	if (error) {
		return console.error(error);
	}

	cache = packages;
    console.info('There are ' + cache.length + ' package updates.');

	db.readSubscriptions(function(error, subscriptions) {
		if (error) {
			return console.error(error);
		}

        _.each(subscriptions, function(subscription) {
            var user = github.getUserFromUrl(subscription.repourl);
            var repo = github.getRepoFromUrl(subscription.repourl);
            github.getPackageJson(user, repo, processPackageJson(subscription));
        });
	});
});

function processPackageJson(subscription) {
	return function(error, json) {
		if (error) {
			return console.error(error);
		}

        var packages = _.filter(_.extend(json.dependencies, json.devDependencies), isPackageInCache);

        _.each(packages, function(packageName) {
            var cached = cache[packageName];
            var versionRange = packages[packageName];

            email.send(subscription.email, subscription.repourl, packageName, versionRange, cached.version);
		});
	};
}

function isPackageInCache(dependency) {
    return !!cache[dependency];
}

Improve how npmalert.js checks for new packages