// settings.js
//
// A cache for settings, more or less.
//
var db     = require('circle-blvd/dataAccess').instance();
var errors = require('circle-blvd/errors');
var guard  = errors.guard;
var async  = require('async');

var listeners = [];

module.exports = function () {

	var cache = null;
	
	// Update one setting
	var update = function (setting, callback) {
		db.settings.update(setting, function (err, results) {
			invalidateCache();
			if (!err) {
				handleUpdate(setting);
			}

			if (callback) {
				callback(err, results);
			}
		});
	}; 

	// Update an array of settings
	var set = function (settings, fnCallback) {
		var tasks = [];

		settings.forEach(function (setting) {
			tasks.push(function (callback) {
				update(setting, callback);				
			});
		});

		async.parallel(tasks, function (err, results) {
			invalidateCache();
			fnCallback(err, results)
		});
	};

	// Ensure an array of settings are in the database.
	var init = function (settings, callback) {
		var settingsTable = {};
		var initialized = {};
		settings.forEach(function (setting) {
			settingsTable[setting.name] = setting;
			initialized[setting.name] = undefined;
		});

		var callbackIfAllSettingsReady = function () {
			var isReady = true;
			for (var key in initialized) {
				if (initialized[key] === undefined) {
					isReady = false;
					break;
				}
			}

			if (isReady && callback) {
				callback(null, initialized);
			}
		};

		db.settings.getAll(guard(callback, function (savedSettings) {
			// var savedSetting;
			// var defaultSetting;
			var settingFound;
			var settingReady = function (setting) {
				initialized[setting.name] = setting;
				callbackIfAllSettingsReady();
			};

			for (var defaultName in settingsTable) {
				
				settingFound = false;
				for (var savedName in savedSettings) {
					if (savedName === defaultName) {
						settingFound = true;
						break;
					}
				}

				if (!settingFound) {
					var addSettingToDatabase = function (settingToAdd) {
						db.settings.add(settingToAdd, function (err, body) {
							if (err) {
								return callback({
									message: "Could not set setting: " + settingToAdd.name
								});
							}
							settingReady(settingToAdd);
						});
					}(settingsTable[defaultName]);				
				}
				else {
					settingReady(savedSettings[savedName]);
				}
			}
		}));
	};


	// Wait for the database to be ready before
	// calling init. 
	var initWhenReady = function (settings, callback) {
		// TODO: Put this timeout in a configuration.
		var tenSeconds = 10000;
		db.whenReady(function () {
			init(settings, callback);
		}, tenSeconds);
	};


	// Get all settings, from the cache if there is one, or
	// from the database if there isn't.
	var get = function (callback) {
		if (!cache) {
			db.settings.getAll(guard(callback, function (settings) {
				cache = settings;
				callback(null, settings);
			}));	
		}
		else {
			return callback(null, cache);
		}
	};


	// Adds a settings object to req.app, for
	// use in Express routes. 
	var middleware = function (req, res, next) {
		get(function (err, settings) {
			req.app.set('settings', settings);
			next(err);
		});
	};


	// Use this function if you want to know when 
	// settings are updated.
	var addListener = function (listener) {
		listeners.push(listener);
	};

	// When a setting is updated, call all of the listeners
	// to let them know.
	function handleUpdate (setting) {
		listeners.forEach(function (listener) {
			listener(setting);
		});
	};

	function invalidateCache () {
		cache = null;
	};


	return {
		init: initWhenReady,
		update: update,
		set: set,
		get: get,
		middleware: middleware,
		addListener: addListener,
	};
}();
@@ -287,18 +287,45 @@
 = null;%0A
+%09var isCacheValid = false;%0A
 %09%0A
-
 %09// Upda
@@ -1396,28 +1396,16 @@
 eady
- && callback
 ) %7B%0A%09%09%09%09
 call
@@ -1396,32 +1396,36 @@
 eady) %7B%0A%09%09%09%09
+get(
 callback
 (null, initi
@@ -1416,26 +1416,8 @@
 back
-(null, initialized
 );%0A%09
@@ -2711,18 +2711,8 @@
 t.%0A%09
-var get = 
 func
@@ -2708,32 +2708,36 @@
 sn't.%0A%09function 
+get 
 (callback) %7B%0A%09%09i
@@ -2740,21 +2740,28 @@
 %0A%09%09if (!
-c
+isC
 ache
+Valid
 ) %7B%0A%09%09%09d
@@ -2927,16 +2927,204 @@
 e);%0A%09%09%7D%0A
+%09%7D%0A%0A%09// convenience function to get a value%0A%09var cachedValue = function (settingName) %7B%0A%09%09if (!cache %7C%7C !cache%5BsettingName%5D) %7B%0A%09%09%09return undefined;%0A%09%09%7D%0A%0A%09%09return cache%5BsettingName%5D.value;%0A
 %09%7D;%0A%0A%0A%09/
@@ -3705,28 +3705,36 @@
  () %7B%0A%09%09
-c
+isC
 ache
- = null
+Valid = false
 ;%0A%09%7D;%0A%0A%0A
@@ -3796,16 +3796,16 @@
 t: set,%0A
-
 %09%09get: g
@@ -3808,16 +3808,44 @@
 t: get,%0A
+%09%09cachedValue: cachedValue,%0A
 %09%09middle

Add function to get cached value