if(!window.Bundle){
	Processing.addIgnoredURL("/bundle.action");	
	Processing.addIgnoredURL("/systemProperty.action");
	window.Bundle = {

		cache: {},
	
		getMessage: function(/* key, args... */){
			var args = this.refreshCache($A(arguments)), message = args.shift();
			return this.format(message, args);
		},

		format: function(message, args){
			if(args.length > 0){
				var re = new RegExp("\\{([0-9]+)\\}", "mg");
				var param = message.match(re);
				if(param != null && param.length > 0){	
					for(var i = 0; i < param.length; i++){
						var token = param[i], index = parseInt(token.replace(/[\{\}]/g, ""), 10);
						message = message.replace(token, (index < args.length) ? (args[index]||"") : "");
					}
				}
			}
			return message;
		},

		getSystemProperty: function(){
			var args = $A(arguments), values = [];
			new Ajax.Request(contextPath+"/systemProperty.action", {
				parameters: { keys: args.toJSON() },
				asynchronous: false,
				evalJS: false,
				evalScripts: false,
				onComplete: function(response){
					values = response.responseJSON;
				}
			});
			return values.length == 1 ? values.first() : values;
		},
	
		refreshCache: function(keys){
			var notInCacheKeys = keys.clone().reject(function(k){
				return (this.cache[k] != null);
			}.bind(this));
	
			this.requestFromServer(notInCacheKeys);
			return this.get(keys);
		},
	
		requestFromServer: function(keys){
			if(Array.isNotEmpty(keys)){
				new Ajax.Request(contextPath+"/bundle.action", {
					parameters: { keys: keys.toJSON() },
					asynchronous: false,
					evalJS: false,
					evalScripts: false,
					onComplete: function(response){
						var values = response.responseJSON;
						if(values != null){
							for(var key in values){
								this.cache[key] = values[key];
							}
						}
					}.bind(this)
				});
			}
		},
	
		get: function(keys){
			return keys.collect(function(k){
				return this.cache[k] || k;
			}.bind(this));
		}
	};
}