/*
 * Some rights reserved (cc) 2006, TPI - Telefonica Publicidade e Informatica Ltda
 * @autor: Alexandre (amf) / Flavio Crispim
 * http://creativecommons.org/licenses/by-sa/2.5/
 */

/**
 * Resolve class library dependencies througt a 'newInstance' method built automaticaly
 * to the class. All YUI libraries are already set.
 * 
 * How to use:
 *	Suppose a widget class named MoveDiv, whose main funcionality is just create and move
 *	a div by 50px towards SW.
 *
 * // MoveDiv class implementation.
 * var MoveDiv = createClass(function() {
 * 	var _div = {};
 * 	var $Y = YAHOO.util;
 * 
 * 	this.init = function() {
 * 		_div = document.createElement('div');
 * 		_div.innerHTML = 'asdasdasdas';
 * 		_div.className = 'aniDiv';
 * 		_div.id = 'aniDiv' + MoveDiv.id++;
 * 		document.body.appendChild(_div);
 * 
 * 		this.anim();
 * 	}
 * 
 * 	this.anim = function() {
 * 		var animMap = new $Y.Anim(_div);
 * 
 * 		animMap.method = $Y.Easing.easeOut;
 * 		animMap.attributes.left = { by: 50 };
 * 		animMap.attributes.top = { by: 50 };
 * 		animMap.animate();
 * 	}
 * });
 * // Configure itīs dependencies.
 * MoveDiv.depends('YUI.animation.animation');
 * MoveDiv.id = 0;
 * 
 * // Hereīs the magic. classīs newInstance will resolve the dependencies
 * // before creating the new instance.
 * var md = MoveDiv.newInstance();
 * 
 * // Here we go...
 * md.init();
 * 
 * @param {Object} pDependencies
 */

function Require(pDependencies){
	var _path = '';
	var _dependencies = pDependencies ||
	{};
	
	function _toKey(pPath){
		var _k = '';
		
		_k = pPath.split('js/'); // ../js/dir/file.js -> dir/file.js
		_k = _k[1].split('.'); // dir/file.js -> dir/file
		_k = _k[0].split('/'); // dir/file -> [dir, file]
		return _k.join('.'); // dir.file
	}
	
	function _toPath(pKey){
		var _p = '';
		
		_p = pKey.split('.'); // dir.file -> [dir, file]
		_p = _p.join('/'); // [dir, file] -> dir/file
		_p = _p + '.js'; // dir/file -> js/dir/file.js
		return _p;
	}
	
	function _checkDependencies(pKey){
		var _key = pKey;
		var $RD = _dependencies[_key];
		var _stack = [];
		
		if (!$RD) {
			if (!Require.isLoaded[_key]) {
				_stack.push(_key);
			}
		}
		else {
			for (var cI = 0, lA = $RD.length; cI < lA; cI++) {
				if (!Require.isLoaded[$RD[cI]]) {
					if ($RD[cI] != _key) {
						var _s = _checkDependencies($RD[cI]);
						
						while (_s.length) {
							_stack.push(_s.shift());
						}
					}
					
					_stack.push($RD[cI]);
				}
			}
		}
		
		return _stack;
	}
	
	
	this.setPath = function(pPath){
		_path = pPath || '/';
	}
	
	this.loadBuiltIn = function(pObj){
		var _toLoad = pObj;
		if (!_toLoad) {
			return false;
		}
		
		function _loadFile(pFile){
			var _key = (pFile.indexOf('/') == -1) ? pFile : _toKey(pFile);
			var _stack = _checkDependencies(_key);
			
			_loadStack(_stack);
		}
		
		function _loadStack(pStack){
			var _stack = pStack;
			
			while (_stack.length) {
				var _k = _stack.shift();
				
				if (!Require.isLoaded[_k]) {
					Require.isLoaded[_k] = true;
					document.write('<script type="text/javascript" src="' + _path + _toPath(_k) + '"></' + 'script>');
				}
			}
		}
		
		for (var cI = 0, lF = _toLoad.length; cI < lF; cI++) {
			_loadFile(_toLoad[cI]);
		}
	}
	
	this.loadFile = function(pObj){
		var _toLoad = (typeof pObj === 'object') ? pObj.file : pObj;
		if (!_toLoad) {
			return false;
		}
		var _stack = [];
		
		function _loadFile(pFile){
			var _key = (pFile.indexOf('/') == -1) ? pFile : _toKey(pFile);
			_stack = _checkDependencies(_key);
			
			_loadStack();
		}
		
		function _loadStack(){
			var _k = _stack.shift();
			
			if (_k && !Require.isLoaded[_k]) {
				Require.isLoaded[_k] = true;
				
				var rnd = (new Date().getTime()) + (Math.random() * 37);
				var r = YAHOO.util.Connect.createXhrObject(rnd);
				
				r.conn.open('GET', _path + _toPath(_k), false);
				r.conn.send('');
				
				if (r.conn.status < 400) {
					_loadSuccess(r.conn);
				}
				else {
					_loadFailure(_k, r.conn);
				}
			}
			else {
				_loadSuccess();
			}
		}
		
		function _loadSuccess(o){
			if (o) {
				eval(o.responseText);
			}
			
			if (_stack.length) {
				_loadStack();
			}
			else {
				return true;
			}
		}
		
		function _loadFailure(pKey, pErr){
			Require.isLoaded[pKey] = false;
			throw new Error('HTTPError [' + pErr.status + '] ' + pErr.statusText + ': ' + pKey);
			
			return false;
		}
		
		if (typeof _toLoad === 'string') {
			_loadFile(_toLoad);
		}
		else {
			return false;
		}
	}
}

Require.isLoaded = {}; // static var

/**
 * The TPI global namespace
 * @constructor
 */
window.TPI = window.TPI || {};


/**
 * Import YAHOO.util
 * @type object
 */
var $Y = {};


/*
 * YUI Dependencies
 */
var requiredDependencies = {
	'library.yui.animation.animation': [
		'library.yui.yahoo.yahoo',
		'library.yui.dom.dom',
		'library.yui.event.event',
		'library.yui.animation.animation'
	],
	'library.yui.autocomplete.autocomplete': [
		'library.yui.yahoo.yahoo',
		'library.yui.dom.dom',
		'library.yui.event.event',
		'library.yui.connection.connection',
		'library.yui.animation.animation',
		'library.yui.autocomplete.autocomplete'//,
		//'library.yui.autocomplete-mod'
	],
	'library.yui.connection.connection': [
		'library.yui.yahoo.yahoo',
		'library.yui.event.event',
		'library.yui.connection.connection'
	],
	'library.yui.dom.dom': [
		'library.yui.yahoo.yahoo',
		'library.yui.dom.dom'
	],
	'library.yui.dragdrop.dragdrop': [
		'library.yui.yahoo.yahoo',
		'library.yui.dom.dom',
		'library.yui.event.event',
		'library.yui.dragdrop.dragdrop'//,
//		'library.yui.dragdrop-mod'
	],
	'library.yui.event.event': [
		'library.yui.yahoo.yahoo',
		'library.yui.event.event'//,
//		'library.yui.event-mod'
	],
	'library.yui.slider.slider': [
		'library.yui.yahoo.yahoo',
		'library.yui.event.event',
		'library.yui.dragdrop.dragdrop',
		'library.yui.animation.animation',
		'library.yui.slider.slider'
	]
};

TPI.require = new Require(requiredDependencies);

/**
 * 
 * @param {Object} obj
 */
var createClass = function(obj) {
	obj['dependencies'] = [];

	var _depends = function(dependence) {
		obj.dependencies.push(dependence); 
	}

	var _loadDependencies = function() {
		for (var cI = 0, lD = obj.dependencies.length; cI < lD; cI++) {
			var f = obj.dependencies[cI];
			var r = TPI.require || new Require(TPI.path);

			r.loadFile({file: f});
		}
	}

	var _newInstance = function() {
		_loadDependencies();
		return new obj;
	}

	obj['newInstance'] = _newInstance;
	obj['depends'] = _depends;

	return obj;
}