var thisNamespace = 'modules.Master';
var thisPackage   = {
	
	initialize: function() {
		
		// Check if we are in debug/development mode
		if(!modules.Master.getData('isDebugRequest')) {
			modules.Master.registerErrorHandler();
		}	
		
		document.observe('yc:div_updated', function(event) {
			modules.Master.registerGlobalEvents(event.target);
			if (event.memo.content) {
				modules.Master.loadInlineScriptTags(event.memo.content, event.target);
			}
		});
		
		modules.Master.registerGlobalEvents();
		modules.Master.executeModulesToInitialize();
	},
	
	// Catch all runtime Javascript errors
	registerErrorHandler: function() {
		window.onerror = function(message, url, line) {
			return true; 
		};
	},

	registerGlobalEvents: function(element) {
		
		var self = modules.Master;
		element = $(element) || $$('body').first();
		
		// target blank
		element.select('a.js-link-target-blank').each(function(element){
			element.writeAttribute('target', '_blank');
		});
		
		// open given url in lightbox window
		element.select('a.js-lightbox-open').invoke('observe', 'click', function(event) {
			event.stop();
			lib.Overlay.showAndLoadFromUrl(event.element().href);
		});
		
		// close the current lightbox window
		element.select('a.js-lightbox-close').invoke('observe', 'click', function(event) {
			event.stop();
			lib.Overlay.hide();
		});
		
		// open given url in lightbox window
		element.select('a.js-lightbox-link').invoke('observe', 'click', function(event) {
			event.stop();
			lib.Overlay.showAndLoadFromUrl(event.element().href);
		});
		
		var linksSelector = 'a[class*=js-ajax-link]';
		var submitsSelector = '.js-ajax-submit';
		
		element.select(linksSelector).invoke('observe', 'click', self.processEvent.curry('link'));
		element.select(submitsSelector).invoke('observe', 'click', self.processEvent.curry('form'));
		
		element.select('.js-hide-delayed').each(function(element) {
			self.hideElementDelayed(element)
		});
		
		// deactivate links
		element.select('a.js-link-deactivate').invoke('observe', 'click', function(event) {
			event.stop();
		});
		
	},
	
	findContainerElement: function(element) {
		
		var match = element.className.match(new RegExp("js-ajax-(link|submit)[:|-]([^\s]*)"));
		var target = (element.href || element.action).toQueryParams().ajax_link_target;
		target = (Object.isArray(target)) ? target[0] : target; 
		return (match) ? match[2] : target ? target : null;
	},
	
	processEvent: function(type, event) {
		
		event.stop();
		
		var self = modules.Master;
		var ok = true;
		var form = (type == 'form') ? event.findElement('form') : null;
		var element = event.element();
		var target_name = self.findContainerElement(form || element);
		
		var target = $(target_name);
		if (target == null) {
			if (form) {
				target = form;
				if (form.getAttribute('enctype') === 'multipart/form-data') {
					var iframeTemplate = new Template('<iframe id="js-ajax-submit-form-iframe" src="about:blank" name="js-ajax-submit-form-iframe" style="display:none"></iframe>');
					form.insert({bottom: iframeTemplate.evaluate({})});
					form.submitIframe = $(document.getElementById('js-ajax-submit-form-iframe'));
					form.submitIframe.src = 'about:blank';
				}
				
			} else {
				Logger.error('modules.Master.ProcessEvent: no target given!', 'name=', target_name, element);
				return;
			}
		}
		
		var fallback = Prototype.emptyFunction;
		var params = null;
		var url = null;
		
		if (type == 'form') {
			var target = form.up('span.js-ajax-submit-form-container');
			if (!target) {
				target = new Element('span').addClassName('js-ajax-submit-form-container');
				form.insert({'before': target});
				target.appendChild(form);
			}
			if (form.submitIframe) {
				
				form.target = form.submitIframe.name;
				form.submitIframe.observe("load", function() {
					
					try {
						var result = lib.Helper.getIFrameContentElement(form.submitIframe);
						if (result.innerHTML) {
							target.update(result.innerHTML);
							target.fire('yc:div_updated');
						}
					} catch(e) {
						alert(e.message);
						Logger.warn(e.message);
					}
				});
				
				form.submit();
				
				return;
			} else {
				params = form.serialize(true);
				params[element.name] = 1;
				url = form.action;
				fallback = function() { form.submit(); }
			}
			
		} else if (type == 'link') {
			url = element.href;
			fallback = function() { location.href = url; }
		}
		
		if (url) {
			new Ajax.Updater(target, url, {
				method: form ? 'post' : 'get',
				requestHeaders: {Accept: 'text/html'},
				parameters: params,
				evalScripts: true,
				onFailure: function(transport) {
				
					var result = transport.headerJSON;
					var errorMessage = null;
					
					if (result != null && result.error) {
						errorMessage = result.error;
					}
					
					Logger.error('modules.Master.processEvent: failure (' + errorMessage + ')');
					
					// call the fallback if something goes wrong
					fallback();
				},
				onComplete: function(transport) {
					target.fire('yc:div_updated', {content: transport.responseText});
				}
			});
		} else {
			Logger.error('modules.Master.processEvent: No url given.');
		}
	},
	
	hideElementDelayed: function(element) {
		element.fade({duration:5.0, from:1, to:0});
	},

	/**
	 * Reads values from the <input type="hidden" name="..." ...> fields of
	 * the <div id="hiddenData"> element. Very handy for easy transportation
	 * of values via the Template/DOM to Javascript.
	 *
	 * @author tb
	 */
	getData: function(name, scope) {
		var id = 'javascriptData';
		if (scope) {
			id = id + "-" + scope;
		}
		var hiddenData = $(id);
		if(hiddenData) {
			var inputElm = hiddenData.down('input[name="' + name + '"]');
			if(inputElm) {
				return inputElm.getValue();
			} else {
				return null;
			}
		}
	},
	
	/**
	 * Only works, if the given content is the original response from ajax request.
	 * This content contains the script tags.
	 */
	loadInlineScriptTags: function(content, element) {

		var self = modules.Master;
		var updatedElement = $(element) || null;
		var matches;
		var scripts = [];
		
		matches = content.match(/<style[^>]*>.*?<\/style>/gi);
		if (matches) {
			matches.each(function(style) {
				var matches = style.match(/url\("(.*?)"\)/i);
				if (matches) {
					var match = matches[1];
					if (!scripts.include(match)) {
						scripts.push(match);
					}
				}
			});
		}
		
		matches = content.match(/<script[^>]*>/gi);
		if (matches) {
			matches.each(function(script) {
				var matches = script.match(/src="(.*?)"/i);
				if (matches) {
					var match = matches[1];
					if (!scripts.include(match)) {
						scripts.push(match);
					}
				}
			});
			
			Yourchance.Invoker.invoke(scripts, self.executeModulesToInitialize.bind(self, updatedElement));
		}
	},
	
	executeModulesToInitialize: function(element) {
		
		var modulesToInitialize = [];
		
		$$("input[name='modulesToInitialize[]']").each(function(input) {
			if (!this.include(input.value)) {
				this.push(input.value);
			}
			input.remove();
		}, modulesToInitialize);
		
		modulesToInitialize.each(function(module) {
			var module = eval(module);
			Logger.log(module);
			if (module && Object.isFunction(module.initialize)) {
				module.initialize(element);
			}
		});
		
	}
};
addPackage(thisNamespace, thisPackage, true);