/*/
 * @class 	toolmanager.js
 *
 * @desc 	Create objects to broadcast messages using events,
 *			a diiferent object for each section of the app classes
 *			Run the app.
 *
 * @author Jonathan Lee-White
/*/


// 888888ba                                       dP                        oo                 
// 88    `8b                                      88                                           
// 88     88.d8888b.88d888b..d8888b.88d888b..d888b88.d8888b.88d888b..d8888b.dP.d8888b..d8888b. 
// 88     8888ooood888'  `8888ooood888'  `8888'  `8888'  `8888'  `8888'  `""8888ooood8Y8ooooo. 
// 88    .8P88.  ...88.  .8888.  ...88    8888.  .8888.  .8888    8888.  ...8888.  ...      88 
// 8888888P `88888P'88Y888P'`88888P'dP    dP`88888P8`88888P8dP    dP`88888P'dP`88888P'`88888P' 
//                  88                                                                         
//                  dP   
var events = require('events');
// events could be secured by issuing a token to each group... 
// groups e.g. calc, client, admin... so client could never listen to calc or admin sockets
// token needs to be send to register event.on(token, 'eventName', callback)
// event.emit(token, 'eventName', data, callback) - could be a little expensive

//  .d888888   888888ba  dP 
// d8'    88   88    `8b 88 
// 88aaaaa88a a88aaaa8P' 88 
// 88     88   88        88 
// 88     88   88        88 
// 88     88   dP        dP 
this.spawnEventRoom = function(){
	return new events.EventEmitter();
};
this.errorHandler = function(){
	return new events.EventEmitter()
}().on('Fatal', function(errorBody){
	console.log('[Error: Fatal! '+errorBody+' ]')
	console.log('HAULTING!')
	throw new Error(errorBody);
}).on('Warn', function(errorBody){
	if(__log){
		console.log(new Error('Warning! '+errorBody));
	}
})
this.spawnTimer = function(startMessage){
	var start = new Date().getTime();
	return function(endMessage){
		end = new Date().getTime();
		if(startMessage&&endMessage&&__log){
			console.log("["+endMessage+"]"+
				"\n    Time from: "+startMessage+
				"\n    Runtime: "+(end-start)
			);
		}
		return (end-start);
	}
}
this.spawnPrettyLog = function(){
	
}


this.spawnKeyGen = function(){
	var seed = keySeed()
	,	incr = seedIncr();
	return function(){
			var key = (seed).toString(36);
			seed = seed+incr;
			return key;
		}
}

var baseSeed = 1000000000
,	baseSeedIncr = 1000000
,	seedIncr = function(){ 
		return 1
	}
,	currentSeed = baseSeed
,	keySeed = function(){
		currentSeed = currentSeed+baseSeedIncr;
		// add int between 0-9 to make colisions less likely
		return currentSeed+(Math.floor(Math.random()*10));
	};

/* Used to monitor a bulk of asyncronous loads, calls onComplete when all packages loaded (successfully or not) */
this.spawnAsyncCounter = function(onComplete, onSuccess, onFailure){
	var counts = {};
	counts.needed = 0;
	counts.successful = 0;
	counts.failed = 0;

	var isComplete = function(){
			if(counts.needed == counts.successful+counts.failed){
				onComplete(counts.needed, counts.successful, counts.failed);
			}
		}
	,	setTotalcount = function(total, modify){
			counts.needed = (modify?counts.needed+total:total);
		}
	,	modifier = function(data, callback){
			if(callback != undefined){
				var callbackResponse = callback(data);
				if(callbackResponse === true || callbackResponse === undefined){
					return true;
				}
				else{
					return callbackResponse;
				}
			}
			else{
				return true;
			}
		}
	,	succ = function(data){
			var modiferResponce = modifier(data, onSuccess);
			// modifier responce will always be a number > 0 unless callback fails it ,
			//	then it will be false, and we should change it's status to failed, and let whoever called succ know about its failure
			if(modiferResponce === true){
				counts.successful++;
				isComplete();
			}
			else{
				//	the modifier returned false, the onSuccess callback failed the data item, let's fail it and maybe onFailure callback will fix problem... keey trying untill failure threashold is reached
				fail(data);
			}
		}
	,	fail  = function(data, failCounter){
			var modiferResponce = counts.failed = modifier(data, onFailure);
			// modifier responce will always be a number > 0 unless callback fails it ,
			//	then it will be false, and we should change it's status to failed, and let whoever called succ know about its failure
			if(modiferResponce === true){
				counts.failed++
				isComplete();
			}
		}
	var counterHandle = {
		required : setTotalcount
	,	failed : fail
	,	success : succ
	}
	return counterHandle;
}

this.inheritInterfaces = function(dependencies, inheritObject){
	console.log('!!!!!!DEPS', dependencies)
	console.log('!!!!!!inheritObject', inheritObject)
	for(var i in inheritObject){
		if(!dependencies[i]){
			_error.emit('Warn', 'Error inheriting interfaces for '+i+'. Dependancy '+i+' not existing.');
		}
		else{
			if(typeof dependencies[i].inheritInterfaces == 'function'){
				var len = inheritObject[i].length;
				for(var j = 0; j<len; j++){
					if(!dependencies[inheritObject[i][j]]){
						_error.emit('Warn', 'Error inheriting interfaces for '+i+'. Dependancy '+inheritObject[i][j]+' not existing.');
					}
					else{
						//all good, can inherit interface
						dependencies[i].inheritInterfaces(inheritObject[i][j].interface);
					}
				}

			}
		}
	}
}