﻿var modMan = function($){
	//=-=-=-=-=-=-=-=-=-=-
	// Local variables
	//=-=-=-=-=-=-=-=-=-=-
	var globals = {}; // Stores section configs and shared observers
	
	// Error messages
	var errorMsgs = {
		defaultLNG:"br",
		br:{
			otherFrameworkFound:"modMan uses jQuery and cant work with other frameworks."
		},
		en:{
			otherFrameworkFound:"modMan uses jQuery and cant work with other frameworks."
		}
	}
	
	// Controlled Vocabulary
	var controlled = {
		defaultLNG:'br',
		defaultRGN:'BR',
		LNG:{
			br:{
				loading:"carregando"
			},
			en:{
				loading:"loading"
			},
			es:{
				loading:"cargando"
			}
		},
		RGN:{
			BR:{
				portalURL:"http://www.terra.com.br/"
			}
		}
	}
	
	var regions = {
		ar:{id:1, country:"AR", lang:"ar", flag:"ARG", gmt:-180},
		br:{id:2, country:"BR", lang:"br", flag:"BRA", gmt:-120},
		cl:{id:3, country:"CL", lang:"es", flag:"CHI", gmt:-240},
		co:{id:4, country:"CO", lang:"es", flag:"COL", gmt:-300},
		ec:{id:5, country:"EC", lang:"es", flag:"ECU", gmt:-300},
		com:{id:6, country:"US", lang:"en", flag:"USA", gmt:-240},
		mx:{id:7, country:"MX", lang:"es", flag:"MEX", gmt:-300},
		pe:{id:8, country:"PE", lang:"es", flag:"PER", gmt:-300},
		ve:{id:9, country:"VE", lang:"es", flag:"VEN", gmt:-270}
	};
	// Local variables //
	
	// Include Plugin
	(function($){ $.extend({ ImportBasePath:'', useBrowserCache:true, loadedFiles:{}, fileinfo:function(data){ data=data.replace(/^\s|\s$/g,""); var m; if(/\.\w+$/.test(data)){ m=data.match(/([^\/\\]+)\.(\w+)$/); if(m){ if(m[2]=='js'){ return{ filename:m[1], ext:m[2], tag:'script' } } else if(m[2]=='css'){ return { filename:m[1], ext:m[2], tag:'link' } } else { return { filename:m[1], ext:m[2], tag:null } } } else { return { filename:null, ext:null } } } else { m=data.match(/([^\/\\]+)$/); if(m){ return { filename:m[1], ext:null, tag:null } } else { return { filename:null, ext:null, tag:null } } } }, checkTemplate:function(){ $.loadedFiles['link'] = {}; var elementsArray=document.getElementsByTagName('link'); for(var i=0;i<elementsArray.length;i++){ if(elementsArray[i].getAttribute('rel').toLowerCase()=='stylesheet' && elementsArray[i].getAttribute('href')){ $.loadedFiles.link[elementsArray[i].getAttribute('href') + ''] = true; } } $.loadedFiles['script'] = {}; var elementsArray=document.getElementsByTagName('script'); for(var i=0;i<elementsArray.length;i++){ if (((/javascript/i).test(elementsArray[i].getAttribute('type')) || (/javascript/i).test(elementsArray[i].getAttribute('language'))) && elementsArray[i].getAttribute('src')){ $.loadedFiles.script[elementsArray[i].getAttribute('src') + ''] = true; } } }, fileExist:function(filename,filetype,attrCheck){ if($.loadedFiles[filetype][$.ImportBasePath+filename +'']) {return true;} else {return false;} }, createElement:function(filename,filetype){ switch(filetype){ case'script': if(!$.fileExist(filename,filetype,'src')){ var src = $.ImportBasePath+filename; $.loadedFiles.script[src] = true; if(!$.useBrowserCache) { src += ((/\?/).test(src)) ? '&' : '?'; src += new Date().getTime();} var scriptTag=document.createElement(filetype); scriptTag.setAttribute('language','javascript'); scriptTag.setAttribute('type','text/javascript'); scriptTag.setAttribute('src',src); scriptTag.setAttribute('charset','UTF-8'); modMan.log.checkpoint('Including new JS:\n ' + $.ImportBasePath+filename); return scriptTag } else { return false } break; case'link': if(!$.fileExist(filename,filetype,'href')){ var href = $.ImportBasePath+filename; $.loadedFiles.link[href] = true; if(!$.useBrowserCache) { href += ((/\?/).test(href)) ? '&' : '?'; href += new Date().getTime();} var styleTag=document.createElement(filetype); styleTag.setAttribute('type','text/css'); styleTag.setAttribute('rel','stylesheet'); styleTag.setAttribute('href',href); $.loadedFiles.link[$.ImportBasePath+filename] = true; modMan.log.checkpoint('Including new CSS:\n ' + $.ImportBasePath+filename); return styleTag } else { return false } break; default: return false; break } }, cssReady:function(index,callback){ function check(){ if(document.styleSheets[index]){ if(typeof callback=='function'){callback()} window.clearInterval(checkInterval) } } var checkInterval=window.setInterval(check,200) }, include:function(file,callback){ var headerTag=document.getElementsByTagName('head')[0]; var fileArray=[]; typeof file=='string'?fileArray[0]=file:fileArray=file; for(var i=0;i<fileArray.length;i++){ var elementTag=$.fileinfo(fileArray[i]).tag; var el=[]; if(elementTag!==null){ el[i]=$.createElement(fileArray[i],elementTag); if(el[i]){ headerTag.appendChild(el[i]); if(typeof callback=='function' && i == fileArray.length - 1){ if($.browser.msie){ el[i].onreadystatechange=function(){ if(this.readyState==='complete' || this.readyState==='loaded'){ callback(); } } } else { if(elementTag =='link'){ $.cssReady(i,callback) } else { el[i].onload=function(){ callback(); } } } } } else if (i == fileArray.length - 1 && typeof callback=='function'){ callback(); } } else { return false } } } }); $.checkTemplate(); })(jQuery);
	
	//=-=-=-=-=-=-=-=-=-
	// Section configs
	//=-=-=-=-=-=-=-=-=-
	(function(){

		//-+-+-+-+-+-+-+-+-+-+
		// Locale detection
		//-+-+-+-+-+-+-+-+-+-+
		var userAgentLocale = (navigator.language) ? navigator.language : navigator.userLanguage;
		var userLang = userAgentLocale.split('-')[0].toLowerCase();
		var userCountry = userAgentLocale.split('-')[1].toUpperCase();
		
		var domainSufix = (document.domain.replace(/.*\./,'') && (/\./).test(document.domain)) ? document.domain.replace(/.*\./,'') : 'br';
		var pageCountry = regions[domainSufix].country;
		var pageLang = regions[domainSufix].lang;
		
		//var underTerra = (/\.terra\.|stages\.com\.br/i).test(document.domain);
		var underTerra = false;
		
		// Converting exeptions
		if(userCountry == 'AR') userLang = 'ar';
		if(userCountry == 'BR') userLang = 'br';
		
		var baseURL = (pageCountry == "BR") ? "http://stf.terra.com.br/portal" : "http://stf.terra.com/portal";
		if((/P\:/).test(document.location)) baseURL = "file:///P:/Atomo/_MAIN%20SITE/05.%20PRODUÇÃO/WebDev/Desenvolvimento/pt-br";
		if((/mainsite\./).test(document.location)) baseURL = "http://mainsite.int.dsv-webx1.terra.com.br/pt-br";

		var startupTime = new Date().getTime();
		/*// Detect framework conflict
		if(window['$'] && !window['jQuery']) {
			throw new Error(errorMsgs.otherFrameworkFound);
		} else if(!window['jQuery']){
			// Inserting jQuery on the fly	
			objHead = document.getElementsByTagName("head")[0];
			objScript = document.createElement("script");
			objScript.type = "text/javascript";
			objScript.src = "http://stages.com.br/terra/main_site/assets/js/core/jquery-latest.js";
			objHead.appendChild(objScript);
		}*/
		
		// FlashDetect
		// http://www.featureblend.com/license.txt
		if(!FlashDetect) var FlashDetect=new function(){var self=this;self.installed=false;self.raw="";self.major=-1;self.minor=-1;self.revision=-1;self.revisionStr="";var activeXDetectRules=[{"name":"ShockwaveFlash.ShockwaveFlash.7","version":function(obj){return getActiveXVersion(obj);}},{"name":"ShockwaveFlash.ShockwaveFlash.6","version":function(obj){var version="6,0,21";try{obj.AllowScriptAccess="always";version=getActiveXVersion(obj);}catch(err){}; return version;}},{"name":"ShockwaveFlash.ShockwaveFlash","version":function(obj){return getActiveXVersion(obj);}}];var getActiveXVersion=function(activeXObj){var version=-1;try{version=activeXObj.GetVariable("$version");}catch(err){}; return version;};var getActiveXObject=function(name){var obj=-1;try{obj=new ActiveXObject(name);}catch(err){}; return obj;};var parseActiveXVersion=function(str){var versionArray=str.split(",");return{"raw":str,"major":parseInt(versionArray[0].split(" ")[1],10),"minor":parseInt(versionArray[1],10),"revision":parseInt(versionArray[2],10),"revisionStr":versionArray[2]};};var parseStandardVersion=function(str){var descParts=str.split(/ +/);var majorMinor=descParts[2].split(/\./);var revisionStr=descParts[3];return{"raw":str,"major":parseInt(majorMinor[0],10),"minor":parseInt(majorMinor[1],10),"revisionStr":revisionStr,"revision":parseRevisionStrToInt(revisionStr)};};var parseRevisionStrToInt=function(str){return parseInt(str.replace(/[a-zA-Z]/g,""),10)||self.revision;};self.majorAtLeast=function(version){return self.major>=version;};self.FlashDetect=function(){if(navigator.plugins&&navigator.plugins.length>0){var type='application/x-shockwave-flash';var mimeTypes=navigator.mimeTypes;if(mimeTypes&&mimeTypes[type]&&mimeTypes[type].enabledPlugin&&mimeTypes[type].enabledPlugin.description){var version=mimeTypes[type].enabledPlugin.description;var versionObj=parseStandardVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revisionStr=versionObj.revisionStr;self.revision=versionObj.revision;self.installed=true;}}else if(navigator.appVersion.indexOf("Mac")==-1&&window.execScript){var version=-1;for(var i=0;i<activeXDetectRules.length&&version==-1;i++){var obj=getActiveXObject(activeXDetectRules[i].name);if(typeof obj=="object"){self.installed=true;version=activeXDetectRules[i].version(obj);if(version!=-1){var versionObj=parseActiveXVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revision=versionObj.revision;self.revisionStr=versionObj.revisionStr;}}}}}();};FlashDetect.release="1.0.3";
		
		// Set free section configs
		globals = {
			page:{
				lang:pageLang,
				country:pageCountry,
				underTerra:underTerra,
				baseURL:baseURL,
				startupTime:startupTime,
				flash:{
					installed:FlashDetect.installed,
					version:FlashDetect.major
				},
				transitionEffects:true
			},
			user:{
				lang:userLang,
				country:userCountry
			},
			regions:regions
		}
		
	})(); // Just once
	
	var load = function(){
		//-+-+-+-+-+-+-+-+
		// Local VARS
		//-+-+-+-+-+-+-+-+
		var firstLoad = true;
		var modulesQueue = [];
		var modTypeInProgress = [];
		var loaded = {};
		// Local VARS //
	
		var modules = function(modulesOBJ){
			var modByType = {};
			
			// Validation loop
			for(var no = 0; no < modulesOBJ.length; no++){
				var mod = modulesOBJ[no];
				
				// Check if there are permission for this module in the library
				if(!modLib.modules[mod.id]) {
					log.critical(mod.id + " - Script não encontrado.");
					continue;
				}
								
				if(!modByType[mod.id]) {
					modTypeInProgress.push(mod.id);
					modByType[mod.id] = [];
				}
				modByType[mod.id].push(mod);				
			}
			
			// Execution loop			
			for(var modType in modByType){
								
				log.checkpoint('Requisitando script para: ' + modType);
				
				new tools.jsonP({
					url:globals.page.baseURL + '/' + modLib.modules.baseDIR + '/' + modLib.modules[modType],
					wrapperName:modType,
					cache:$.useBrowserCache,
					callback:function(moduleOBJ){
						var moduleID = moduleOBJ.info.id;
						log.checkpoint('Executando callback do: ' + moduleID);
						window[moduleID] = moduleOBJ;
						
						var modPrefs = modByType[moduleID].shift();
						
						
						var sameTypeQueue = modByType[moduleID];
						var callModPrefs = !!!modTypeInProgress.length;
						
						//alert(modTypeInProgress.length + '\n' + moduleID + '\n' + callModPrefs);
						
						if (moduleOBJ.dependencies){
							log.checkpoint(moduleID + " - Avaliando pré-requisitos para o seletor " + modPrefs.selector);
							components(moduleOBJ, modPrefs, sameTypeQueue);
						} else {
							modulesQueue.push(modPrefs);
						}
					}
				});
			}	
			
		}
		
		var components = function(modOBJ, modPrefs, sameTypeQueue){
			var loadSkin = modPrefs.loadSkin;
			var dependenciesOBJ = modOBJ.dependencies;
			var urlsOBJ = {};
			//alert('aqui \n' + modOBJ.name);
			
			
			if(dependenciesOBJ.underTerra && !globals.page.underTerra) {
				log.critical(modPrefs.id + ' - Este módulo só pode ser carregado sob o domínio do Terra');
				if(callModPrefs) preferences();
				return false;
			}
			
			if(dependenciesOBJ.flash && !globals.page.flash.installed) {
				log.warning(modPrefs.id + ' - Este módulo precisa de flash para ser instanciado');
				if(callModPrefs) preferences();
				contingency(modPrefs);
				return false;
			}
			
			if(dependenciesOBJ && dependenciesOBJ.js){
				urlsOBJ['js'] = [];
				for(var type in dependenciesOBJ.js){
					var item = dependenciesOBJ.js[type];
					var baseURL = '/' + modLib[type].baseDIR;
					if(typeof(item) == 'string') urlsOBJ['js'].push(baseURL + item);
					else if(typeof(item) == 'object' && item.length){
						for (var i = 0; i < item.length; i++){
							if(!modLib[type][item[i]]) {
								log.critical(item[i] + ' - não encontrado na biblioteca '+ type);
								return false;
							}
							var url = baseURL + '/' + modLib[type][item[i]].file;
							urlsOBJ['js'].push(url);
						}
					}
					/* alert(
						'type : ' + type +'\n'+
						'itemName : ' + itemName +'\n'+
						'baseURL : ' + baseURL +'\n'
					); */
				}
				//alert(urlsOBJ.toSource());
				tools.Components.set(urlsOBJ, function(){
					var shift = modTypeInProgress.shift();
					//log.checkpoint('chamando internalTimer\n' + modPrefs.id);
					modulesQueue.push(modPrefs);
					if(sameTypeQueue.length) {
						for(var i = 0; i < sameTypeQueue.length; i++){
							modulesQueue.push(sameTypeQueue[i]);
						}
					}
					if(!modTypeInProgress.length) {
						//alert('chamando módulos. logo após ' + modPrefs.id);
						preferences();
					}
				});
			} else {				
				var shift = modTypeInProgress.shift();
				modulesQueue.push(modPrefs);
				if(sameTypeQueue.length) {
					for(var i = 0; i < sameTypeQueue.length; i++){
						modulesQueue.push(sameTypeQueue[i]);
					}
				}
				
				if(!modTypeInProgress.length) {
					preferences();
				}
			}
		}
		
		var play = function() {
			var now = function(modPrefs){
				//alert("play para " + modPrefs.id);
				
				var PARAMS = Interface(modPrefs);
				if (!PARAMS) new contingency(modPrefs);
				else {
					log.checkpoint(modPrefs.id + " - Creating new instance.");
					var instance = new window[modPrefs.id].CONSTRUCTOR(PARAMS,jQuery);
					loaded[modPrefs.id + '_' + modPrefs.selector] = true;
					
					if(!modulesQueue.length && globals.page.lazyLoad) {
						$(window).unbind('scroll');
					}
				}
				
			}
			
			var onViewPort = function(modPrefs){
				if($(modPrefs.selector + ":in-viewport").length) {
					play.now(modPrefs); 
				} else {
					log.checkpoint('scrolling');
					
					$(window).scroll(function() { 		
						if(!loaded[modPrefs.id + '_' + modPrefs.selector] && $(modPrefs.selector + ":in-viewport").length) {
							new play.now(modPrefs);
						}
					});
				}
			}
			
			return {
				now:now,
				onViewPort:onViewPort
			}
		}();
		
		var preferences = function(){
			//alert('em preferences: ' + modulesQueue.length + " itens");
				if(firstLoad){		
					$(document).ready(function(){
						while(modulesQueue.length){
							var modPrefs = modulesQueue.shift();
							if(globals.page.lazyLoad) new play.onViewPort(modPrefs);
							else play.now(modPrefs);
							
							if(!modulesQueue.length) firstLoad = false;
						}
					});			
				} else {
					while(modulesQueue.length){
						var modPrefs = modulesQueue.shift();
						play.now(modPrefs);					
					}
				}
		}
		
		var Interface = function (modPrefs){
			log.checkpoint(modPrefs.id + " - Analisando interface.");
			
			
			var moduleOBJ = window[modPrefs.id];
			
			//-+-+-+-+-+-+-+-+-+-+-+-+-+
			// Double-check for basic dependencies
			//-+-+-+-+-+-+-+-+-+-+-+-+-+
			if(!$(modPrefs.selector).length) {
				log.critical(modPrefs.id+' - Recipiente (DOM element) não encontrado. Favor, verificar seletor e template.');
				return false;
			}
					
			// Checking for module object
			if(!moduleOBJ) {
				log.critical(modPrefs.id + ' - Não foi possível localizar o script para este módulo. Confirme a localização do js e o nome do objeto carregado.' )
				return false;
			}
			
			// Checking for constructor
			if (!moduleOBJ.CONSTRUCTOR){
				log.critical(modPrefs.id + ' - Não foi possível localizar um construtor para este módulo. Verifique se o objeto possui um método chamado "CONSTRUCTOR".' )
				return false;
			}	
			
			// Checking for contingency method
			/* if (!moduleOBJ.CONTINGENCY){
				log.warning(modPrefs.id + ' - Este módulo não possui um método de contingência. Em caso de erros, apenas o procedimento padrão será adotado.' );
			}	 */		
			// Double-check for basic dependencies //
			
			
			var PARAMS = {}; // private object - stores valid params		
		
			//-+-+-+-+-+-+-+-+-+-+-+-+-+
			// Validate specific PARAMS
			//-+-+-+-+-+-+-+-+-+-+-+-+-+
			if (moduleOBJ.params) {
				var params = false;
				if(modPrefs.params) params = $.extend({}, modPrefs.params);
				
				var defaults = moduleOBJ.params.defaults;
				if(defaults) params = $.extend(defaults, modPrefs.params);
				
				var needed = moduleOBJ.params.needed;
				if (needed) {
					// Check if there are instructions for needed params (help propertie)
					if (!moduleOBJ.params.helpMsg) {
						log.critical(modPrefs.id + ' - There is no help instructions for needed params. Create an "help" propertie inside that object.');
						return false;
					}
					// if none was set
					if (!params) {
						log.critical(modPrefs.id + ' - Requires some especific params. Documentation: ' + moduleOBJ.params.helpMsg);
						return false;
					}
					for (var paramName in needed){
						// Checking if the needed param was especified
						if(!params[paramName] && typeof(params[paramName]) != 'boolean' && params[paramName] != 0){
							log.critical(modPrefs.id + ' - Param missing: "' + paramName +'". It also should match this model: ' + needed[paramName]);
							return false;
						}
						if(typeof(needed[paramName]) == 'string'){
							switch(needed[paramName].toLowerCase()){
								// Validating normal strings
								case 'string':
									if (typeof(params[paramName]) == 'string') continue;
									else {
										log.critical(modPrefs.id + ' - ' + paramName + ' should be an string');
										return false;
									}
								break;							
								
								// Validating boolean
								case 'boolean':
									if (typeof(params[paramName]) == 'boolean') continue;
									else {
										log.critical(modPrefs.id + ' - "' + paramName + '" should be boolean');
										return false;
									}
								break;
								
								// Validating number
								case 'number':
									if (typeof(params[paramName]) == 'number') continue;
									else {
										log.critical(modPrefs.id + ' - ' + paramName + ' should be an number');
										return false;
									}
								break;
								
								// Validating array
								case 'array':
									if (typeof(params[paramName]) == 'object' && params[paramName].length) continue;
									else {
										log.critical(modPrefs.id + ' - ' + paramName + ' should be an array');
										return false;
									}
								break;
								
								// if its not one of these, but its still string
								default:
									// Double check for RegExp (FIrefox 2)
									if(needed[paramName].exec(params[paramName])) continue;
									log.critical(modPrefs.id + ' - Unknown specified type inside the string "' + paramName + '". Check the constructor object.');
									return false;
								break;
							}
						} else if(typeof(needed[paramName]) == 'object' && (/^\/.*\/.*/).exec(needed[paramName].toString())) {
							// Validating RegExp
							if(needed[paramName].exec(params[paramName])) continue;
							else{
								log.critical(modPrefs.id + ' - ' + paramName + ' should match this RegExp: ' + needed[paramName]);
								return false;
							}
						} else {
							// Double check for RegExp (FIrefox 2)
							if(needed[paramName].exec(params[paramName])) continue;
							log.critical(modPrefs.id + ' - Unknown specified type for "' + paramName + '". Check the constructor object.');
							return false;
						}
					}
				}
				
				// If everything is alright
				for(var paramName in params){
					PARAMS[paramName] = params[paramName];
				}
				log.checkpoint(modPrefs.id + ' - Parâmetros OK.');
			}
			// Validate specific PARAMS //
			
			
			//-+-+-+-+-+-+-+-+-+-+-+-+-+
			// Adjust module language and region
			//-+-+-+-+-+-+-+-+-+-+-+-+-+
			PARAMS["LNG"] = {};
			PARAMS["RGN"] = {};
			if (moduleOBJ.locale) {
				// LNG
				if(moduleOBJ.locale.LNG) {
					if(moduleOBJ.locale.LNG[globals.page.lang.toLowerCase()]) {
						PARAMS["LNG"] = moduleOBJ.locale.LNG[globals.page.lang.toLowerCase()];
						// Check for default specification
						if (!moduleOBJ.locale.defaultLNG) log.warning(modPrefs.id + ' - A propriedade "defaultLNG" não foi encontrada. Este módulo pode não funcionar corretamente em outros idiomas.');
					} else {
						// Check for default specification
						if (!moduleOBJ.locale.defaultLNG) {
							log.critical(modPrefs.id + ' - Não existem variáveis de idioma para "'+globals.user.lang+'". A propriedade "defaultLNG" também não foi definida. ');
							return false;
						}
						else {
							PARAMS["LNG"] = moduleOBJ.locale.LNG[moduleOBJ.locale.defaultLNG.toLowerCase()];
							log.warning(modPrefs.id + ' - Não existem variáveis de idioma para "'+globals.user.lang+'". O padrão foi implementado.')
						}
					}
				} else {
					log.warning(modPrefs.id+ " - O objeto 'LNG' não foi encontrado. Verifique se ele realmente é desnecessário.");
				}
				
				// RGN
				if(moduleOBJ.locale.RGN) {
					if(moduleOBJ.locale.RGN[globals.page.country.toUpperCase()]) {
						PARAMS["RGN"] = moduleOBJ.locale.RGN[globals.page.country.toUpperCase()];
						// Check for default specification
						if (!moduleOBJ.locale.defaultRGN.toUpperCase()) log.warning(modPrefs.id + ' - A propriedade "defaultRGN" não foi encontrada. Este módulo pode não funcionar corretamente em outros idiomas.');
					} else {
						// Check for default specification
						if (!moduleOBJ.locale.defaultRGN.toUpperCase()) {
							log.critical(modPrefs.id + ' - Não existem variáveis de região para "'+globals.page.country+'". A propriedade "defaultRGN" também não foi definida. ');
							return false;
						}
						else {
							PARAMS["RGN"] = moduleOBJ.locale.RGN[moduleOBJ.locale.defaultRGN.toUpperCase()];
							log.warning(modPrefs.id + ' - Não existem variáveis de região para "'+globals.page.country+'". O padrão foi implementado.')
						}
					}
				} else {
					log.warning(modPrefs.id+ " - O objeto 'RGN' não foi encontrado. Verifique se ele realmente é desnecessário.");
				}
				
			}
				
			// Extendind locale objects with controlled vocabulary
			/*
			$.extend(PARAMS['LNG'], controlled.LNG);
			$.extend(PARAMS['RGN'], controlled.RGN); 
			*/
			PARAMS['LNG']['controlled'] = controlled.LNG;
			PARAMS['RGN']['controlled'] = controlled.RGN;
			
			log.checkpoint(modPrefs.id + ' - Configurações de seção (LNG e/ou RGN) foram avaliadas.');			
			// Adjust module language and region //
			
			
			//-+-+-+-+-+-+-+-+-+-+-+-+-+
			// Skin interpretation
			//-+-+-+-+-+-+-+-+-+-+-+-+-+
					
			// Validating skin settings
			if(modPrefs.loadSkin){
				if(!moduleOBJ.skins) {
					log.critical(modPrefs.id + " - o parâmetro 'loadSkin' foi definido como 'true', mas o módulo não possui a propriedade um objeto 'skins'. Certifique-se \que módulo requer arquivos externos para habilitar esta opção.");
					return false;
				}
				
				var skinsOBJ = moduleOBJ.skins;			
				var skin = {};
				// Checking skin presence
				if(modPrefs.skinName && skinsOBJ.items[modPrefs.skinName]) {
					skin.id = modPrefs.skinName;
					log.checkpoint(modPrefs.id + " - Validando skin: " + modPrefs.skinName);
					
				} else if (skinsOBJ.items[skinsOBJ.defaultSkinName]) {				
					skin.id = skinsOBJ.defaultSkinName;
					log.checkpoint(modPrefs.id + " - Validando skin padrão.")
				} else if (skinsOBJ.items[skinsOBJ.backupSkinName]){
					skin.id = skinsOBJ.backupSkinName;
					log.critical(modPrefs.id + " - Validando skin de backup.");
					return false;
				} else {
					if (!skinsOBJ.items[skinsOBJ.defaultSkinName]) {
						log.critical(modPrefs.id + " - O skin padrão não foi localizado. Verifique se o objeto é uma pririedade de 'items' e se o o seu nome tem o sufix 'skn_'.");
						return false;
					}
				}
				
				// Validating skin interface
				var currentSkin = skinsOBJ.items[skin.id]
				if(!currentSkin.tplBody) {
					log.critical(modPrefs.id + " - o parâmetro 'tplBody' não foi encontrado.");
					return false;
				} else {
					if(typeof(currentSkin.tplBody) != 'string') {
						log.critical(modPrefs.id + " - o parâmetro 'tplBody' deve ser uma string contendo a estrutura HTML para o módulo.");
						return false;
					}
				}
				
				// Parsing template
				if (PARAMS["LNG"] || PARAMS["RGN"]) {
					var lngOBJ = (PARAMS["LNG"]) ? PARAMS["LNG"] : false;
					var rgnOBJ = (PARAMS["RGN"]) ? PARAMS["RGN"] : false;
					
					var TPL = tools.parseTPl(currentSkin.tplBody, lngOBJ, rgnOBJ);
				}
				
				// Including styles
				if(currentSkin.css && currentSkin.css.length) {
					var moduleBaseURL = '/' + modLib.modules.baseDIR + '/' + modPrefs.id.toLowerCase().replace('mod','') + '/';
					
					if(typeof(currentSkin.css) == 'string') {
						tools.Components.set({css:moduleBaseURL + currentSkin.css});
					} else {
						var newCssArray = [];
						for(var i = 0; i < currentSkin.css.length;i++){
							var currentCss = moduleBaseURL + currentSkin.css[i];
							newCssArray.push(currentCss);
						}
						tools.Components.set({css:newCssArray});
					}
				}
				
				if(TPL && modPrefs.loadSkin) {
					$(modPrefs.selector).replaceWith(TPL);
					var selectorAttr = TPL.match(/(id=|class=)+('|")[^'"]+['"]/gi)[0];
					var newSelector = ((/id/i).test(selectorAttr)) ? selectorAttr.replace(/(id=)|( )/gi, '#').replace(/['\"]/g,'') : selectorAttr.replace(/(class=)|( )/gi, '.').replace(/['\"]/g,'');
					//alert(newSelector);
				}
			}
			// Deliver recipient
			PARAMS['preLoadedSkin'] = !modPrefs.loadSkin;
			PARAMS['skinName'] = (skin && skin.id) ? skin.id : modPrefs.skinName;
			PARAMS["recipient"] = (newSelector) ? $(newSelector) : $(modPrefs.selector);
			
			// Define loading state
			//PARAMS["recipient"].addClass("loading");
			
			// Applying transition effects
			if(globals.page.transitionEffects) $(modPrefs.selector).hide().fadeIn('slow');
			// Skin interpretation//
			
			//alert(PARAMS.id + '\n' +  $(modPrefs.selector).length);
			return PARAMS;
		}
		
		var contingency = function(modOBJ){
			log.checkpoint(modOBJ.id + ' - Problemas encontratos. Disparando método de contingência.');
			if($(modOBJ.selector).length) {
				var skinsOBJ = window[modOBJ.id].skins;
				var backupSkinName = skinsOBJ.backupSkinName;
				if(backupSkinName && skinsOBJ.items[backupSkinName]){
					log.checkpoint(modOBJ.id + ' - Incluindo template de backup - ' + skinsOBJ.backupSkinName);
					
					tools.Components.set(skinsOBJ.items[backupSkinName].css, function(){
						$(modOBJ.selector).html(skinsOBJ.items[backupSkinName].tplBody);
					});
					
					
				} else $(modOBJ.selector).html('Um problema foi detectado neste módulo.');
			}
			else log.critical(modOBJ.id + ' - Não foi possível localizar um elemento HTML para receber o template de backup.');
		}
		
		return {
			modules:modules
		}
	}();
	
	// Public //
	var start = function(setupOBJ){
		
		//-+-+-+-+-+-+-+-+-+-+-+-+
		// Parsing configs
		//-+-+-+-+-+-+-+-+-+-+-+-+
		if(setupOBJ.configs) {
			if(setupOBJ.configs.debug || (/debug/).test(document.location)) tools.console();
			if(setupOBJ.configs.baseURL) globals.page.baseURL = setupOBJ.configs.baseURL;
			if(setupOBJ.configs.lazyLoad) {
				$.include(globals.page.baseURL + '/_js/jquery.viewport.js');
				globals.page.lazyLoad = true;
			}
			
			globals.page.transitionEffects = setupOBJ.configs.transitionEffects;
			if(setupOBJ.configs.pageCountry && setupOBJ.configs.pageCountry.toLowerCase() != 'auto') globals.page.country = setupOBJ.configs.pageCountry.toUpperCase();
			if(setupOBJ.configs.pageLang && setupOBJ.configs.pageLang.toLowerCase() != 'auto') globals.page.lang = setupOBJ.configs.pageLang;
		}
		
		// Adjusting configs for external files
		$.ImportBasePath = globals.page.baseURL;
		$.useBrowserCache = !(/debug/).test(document.location);
		//$.useBrowserCache = false;
		
		// Set locale objects
		errorMsgs = (errorMsgs[globals.user.lang]) ? errorMsgs[globals.user.lang] : errorMsgs[globals.user.lang];
		controlled.LNG = (controlled.LNG[globals.page.lang]) ? controlled.LNG[globals.page.lang] : controlled.LNG[controlled.defaultLNG.toLowerCase()];
		controlled.RGN = (controlled.RGN[globals.page.country]) ? controlled.RGN[globals.page.country] : controlled.RGN[controlled.defaultRGN.toUpperCase()];
		
		// Forçando imagens para outros idiomas (provisório)
		//$(document.body).addClass(globals.page.lang);
		
		
		//-+-+-+-+-+-+-+-+-+-+-+-+
		// Loading library
		//-+-+-+-+-+-+-+-+-+-+-+-+
		new tools.jsonP({
			url: globals.page.baseURL + "/_js/core.modLib.js",
			wrapperName: "trrModLib",
			cache:$.useBrowserCache,
			callback:function(jsonOBJ){
				window['modLib'] = jsonOBJ;
				if(setupOBJ.modules) load.modules(setupOBJ.modules);
			}
		});
		
		return modMan.start = load.modules;
	}
	
	var tools = {
		console:function(debugMode){
			debugMode = debugMode || "firebug";
			if (!log.console.active) {
				if(!this.console.firstLoad) {
					this.console.items = [];
					this.console.firstLoad = true;
				}
				log.console.active = true;
				log.checkpoint('Modo debug ATIVO');
			}
			else {
				if(!this.console.firstLoad) this.console.items = [];
				var msg = "Modo debug INATIVO";
				log.checkpoint(msg);
				log.console.active = false;
				alert(msg);
			}
		},
		jsonP:function(configsOBJ){
			var callback = configsOBJ.callback;
			if(!callback) {
				log.critical("É preciso indicar um método (callback) para tratar o arquivo:\n" + url );
				return false;
			}
			var wrapperName = configsOBJ.wrapperName || "jsonp";

			var url = configsOBJ.url;
			
			var extraParams = configsOBJ.extraParams || false;

			// Json in body
			if(window[wrapperName]) {
				log.checkpoint(wrapperName + " - Recuperando json do corpo da página.");
				configsOBJ.callback(window[wrapperName], extraParams);
				return true;
			}

			if(!configsOBJ.cache){
				var cache = new Date().getTime();
				url +=  (url.indexOf('?') != -1) ? "&" : "?";
				url += "cache=" + cache;
			}

			if(!window[wrapperName]) {
				window[wrapperName] = function(jsonOBJ){
					if (typeof(jsonOBJ) != 'object') {
						log.critical("Erro no parse do arquivo:\n" + url);
						return false;
					}
					//log.checkpoint('disparando resposta para ' + wrapperName)
					configsOBJ.callback(jsonOBJ, extraParams);
				};
			}

			var objHead = document.getElementsByTagName("head")[0];
			var objScript = document.createElement("script");
			objScript.type = "text/javascript";
			objScript.src = url;
			objScript.charset ="utf-8";
			objHead.appendChild(objScript);

			objScript.onload = objScript.onreadystatechange = function(){
				if(objScript.readyState) {
					if (objScript.readyState == 'complete') objHead.removeChild(objScript);
				} else objHead.removeChild(objScript);

				try {
					if(objScript && objScript.readyState > 3) objHead.removeChild(objScript);
				} catch (err){
					if(objScript) objHead.removeChild(objScript);
					log.critical("Erro ao o arquivo:" + url + ". Descrição: " + err);
				}
			}
		},
		Components:function(callback){
			
			var loaded = {} // Stores references to already loaded files
			
			var matchLibrary = function(ext, url){
				if (!loaded[ext]) return false;
				else {
					for(var i = 0; i < loaded[ext].length; i++){
						if(loaded[ext][i] == url) return true;
					}					
				}
				return false;
			}
			
			var set =function(componentsOBJ, callback){
				if(typeof(componentsOBJ) != 'object' || (!componentsOBJ['js'] && !componentsOBJ['css'])) {
					if(callback) callback();
					return false;
				}
				var componentsARRAY = [];
				if(componentsOBJ['css']) componentsARRAY = componentsARRAY.concat(componentsOBJ['css']);				
				if(componentsOBJ['js']) componentsARRAY = componentsARRAY.concat(componentsOBJ['js']);
			
				log.checkpoint('checking components: \n' + componentsARRAY.join('\n'));
				$.include(componentsARRAY, callback);
			}
			
			var confirm = function(ext, url){
				if(!loaded[ext]) loaded[ext] = [];
				loaded[ext].push(url);
			}
			
			return {
				matchLibrary:matchLibrary,
				set:set,
				confirm:confirm
			}
		}(),
		parseTPl:function(templateSTR, lngOBJ, rgnOBJ){
			var propEXP = /\.[^#]+/gi;
			// Looking for LNG
			var lngEXP = /##LNG\.[^#]+##/gi;
			if(lngEXP.test(templateSTR)) {
				var placeholders = templateSTR.match(lngEXP);
				for(var i = 0; i < placeholders.length; i++){
					var propertie = placeholders[i].match(propEXP)[0].replace('.','');
					if(lngOBJ[propertie] && typeof(lngOBJ[propertie]) == 'string') templateSTR = templateSTR.replace(placeholders[i], lngOBJ[propertie]);
				}				
			}
			
			
			// Looking for RGN
			var rgnEXP = /##RGN\.[^#]+##/gi;
			if(rgnEXP.test(templateSTR)) {
				var placeholders = templateSTR.match(rgnEXP);
				for(var i = 0; i < placeholders.length; i++){
					var propertie = placeholders[i].match(propEXP)[0].replace('.','');
					if(rgnOBJ[propertie] && typeof(rgnOBJ[propertie]) == 'string') templateSTR = templateSTR.replace(placeholders[i], rgnOBJ[propertie]);
				}				
			}
			return templateSTR;
		},
		adjustTime:function(dateOBJ){
			var time = dateOBJ.toLocaleTimeString();
			
			var hours = time.split(':')[0];
			var minutes = time.split(':')[1];
			
			var usa = (modMan.globals.page.country == 'US') ? true : false;
			var sufix = false;
			var sep = "h";
			
			if(modMan.globals.page.country != 'BR') sep = ":";
			if (usa){
				if(parseInt(hours)>12) {
					hours = parseInt(hours) - 12;
					sufix = "pm";
				} else {
					sufix = "am";
				}
			}
			if(parseInt(hours)<10) hours = '0' + hours.match(/\d$/);
			if(parseInt(minutes)<10) minutes = '0'+minutes.match(/\d$/);
			
			var parsedTime = hours + sep + minutes;
			if(sufix) parsedTime += sufix;
			
			return parsedTime;
		}
	}
	
	var log = {
		console:{
			startupTime:globals.page.startupTime,
			lastAlert:0,
			firstLoad:true,
			active:false,
			mode:'firebug', // it could be "false", "firebug" or "console"
			counter:{
				warning:0,
				critical:0
			},
			items:[]
		},
		setItem:function(itemOBJ){
			if (this.console.active && !this.console.firstLoad) this.console.items = [];
			
			var time = (this.console.lastAlert) ? new Date().getTime() - this.console.lastAlert : new Date().getTime() - this.console.startupTime;
			this.console.lastAlert = new Date().getTime();
			itemOBJ['time'] = time;			
			
			this.console.items.push(itemOBJ);
						
			if(typeof(log.console.counter[itemOBJ.type]) == 'number') log.console.counter[itemOBJ.type]++;
			
			this.report();
			//if(itemOBJ.type == 'critical') return false;
		},
		report:function(){
			if (this.console.active) {
			
				if (this.console.mode == 'firebug'){
					for(var item = 0; item < this.console.items.length; item++){
						var logAlert = this.console.items[item];
						if (window.console) console.log(logAlert.time +"ms: [" + logAlert.type.toUpperCase() + "] " + logAlert.msg);
						else alert(logAlert.time +"ms: [" + logAlert.type.toUpperCase() + "] " + logAlert.msg);
					}
				}
				
				this.console.firstLoad = false;
			}
			
			// Report critical errors
			if (this.console.counter.critical > 0) {
				//throw new Error('Erro(s) crítico(s) encontrado(s): '+this.console.counter.critical);
			}
		},
		checkpoint:function(msg){
			var item = { type:'checkpoint', msg:msg }
			this.setItem(item);
		},
		warning:function(msg){
			var item = { type:'warning', msg:msg }
			this.setItem(item);
		},
		critical:function(msg){
			var item = { type:'critical', msg:msg }
			this.setItem(item);
		},
		help:function(msg){
			var item = { type:'help', msg:msg }
			this.setItem(item);
		}		
	}
	
	var help = function(){
		if (!log.console.active) tools.console();
		var publicMethods = [];
		for(method in tools){
			if(method != 'help') publicMethods.push(method);
		}
		var msg = ""+
		"Total de métodos transversais: " + (publicMethods.length)+".\n"+
		"São eles: " + publicMethods.join(', ') + ".";
		log.help(msg);
	}
	
	var observer = {
		list:{}, // stores cross-component methods
		set:function(name, method){
			if(!this.list[name]) this.list[name] = [];
			
			this.list[name].push(method);
		},
		play:function(name){
			if (this.list[name]) {
				for(var no = 0; no < this.list[name].length; no++){
					this.list[name][no].call();
				}
			} else log.warning(LNG.couldntFondMethodsFor + ' "' + name + '"');
		}
	}
	
	return {
		globals:globals,
		start:start,
		load:load.modules,
		log:log,
		tools:tools,
		help:help
	}
}(jQuery);