(function() {

	SL.utils.removeAMP = function(s) {
		while (true) {
			var i = s.indexOf("&amp;");
			if (i == -1)
				break;
			s = s.substring(0, i) + "&" + s.substring(i + "&amp;".length);
		}
		return s;
	};

	SL.utils.addOrReplaceArg = function(url, arg, value) {
		url = SL.utils.removeAMP(url);

		var match = "&args." + arg + "=";
		var matchPos = url.indexOf(match);
		if (matchPos == -1) {
			return value == null ? url : (url + match + value);
		}
		var trailing = url.substring(matchPos + match.length);
		return url.substring(0, matchPos) + (value == null ? "" : (match + value)) + (trailing.indexOf("&") == -1 ? "" : trailing.substring(trailing.indexOf("&")));
	};
	
	SL.utils.addOrReplaceUrlParam = function(url, arg, value) {
		url = SL.utils.removeAMP(url);

		var match = "&" + arg + "=";
		var matchPos = url.indexOf(match);
		if (matchPos == -1) {
			return value == null ? url : (url + match + value);
		}
		var trailing = url.substring(matchPos + match.length);
		return url.substring(0, matchPos) + (value == null ? "" : (match + value)) + (trailing.indexOf("&") == -1 ? "" : trailing.substring(trailing.indexOf("&")));
	};

	SL.utils.getArg = function(url, arg, value) {
		url = SL.utils.removeAMP(url);

		var match = "&args." + arg + "=";
		var matchPos = url.indexOf(match);
		if (matchPos < 0) {
			return undefined;
		}

		var trailing = url.substring(matchPos + match.length);

		matchPos = trailing.indexOf("&");
		if (matchPos < 0) {
			return trailing;
		}

		return trailing.substring(0, matchPos);
	};

	SL.utils.createBodyElement = function(name, attributes) {
		var e = new Element(name, attributes);
		$$('body')[0].appendChild(e);
		return e;
	};

	SL.utils.reparentToBody = function(e) {
		SL.utils.reparent(e, document.getElementsByTagName('body').item(0));
	};

	SL.utils.reparent = function(e, newParent) {
		e.remove();
		newParent.appendChild(e);
	};

	SL.utils._domReady = false;
	SL.utils._domReadyExecuted = false;
	SL.utils._domReadyFunctions = $A();

	document.observe("dom:loaded", function() {
		SL.utils._domReady = true;
		SL.utils._domReadyFunctions.each(function(f) {
			try {
				f();
			} catch (e) {
				console.error("Error executing onDomReady method:", f, e);
			}
		});
		SL.utils._domReadyFunctions = undefined;
		SL.utils._domReadyExecuted = true;
	});

	SL.utils.onDomReady = function(f) {
		if (SL.utils._domReady) {
			try {
				f();
			} catch (e) {
				console.error(e);
			}
		} else {
			SL.utils._domReadyFunctions.push(f);
		}
	};

	SL.utils.isDomReady = function() {
		return SL.utils._domReady;
	};

	SL.utils.focusFormElement = function(form, name) {
		var elements = Form.getElements(form);
		for ( var i = 0; i < elements.length; i++) {
			if (elements[i].readAttribute('name') == name) {
				elements[i].focus();
				return;
			}
		}
		console.log("Form element not found:", form, ":", name);
	};

	SL.utils.toArrayString = function(o) {
		if (!o) {
			return o;
		}

		if (Object.isString(o)) {
			return o;
		}

		if (Object.isArray(o)) {
			return o.toString();
		}

		return $A(o).toString();
	};

	SL.utils.addFormSubmitWorkaround = function(e) {
		$(e).select('form').each(function(f) {
			f.select('input').each(function(e) {
				if (e.readAttribute('type') == 'text' || e.readAttribute('type') == 'password') {
					e.observe('keypress', function(event) {
						if (event.keyCode == Event.KEY_RETURN) {
							var form = event.element().form;
							try {
								if (Object.isFunction(form.submit)) {
									form.submit();
								} else {
									form.submit.click();
								}
							} catch (ex) {
								console.log(ex);
							}
						}
					});
				}
			});
		});
	};

	SL.utils.loadScript = function(url, cb, finishedCB) {

		if (!SL.utils._loadedScripts) {
			SL.utils._loadedScripts = $H();
		} else {
			var h = SL.utils._loadedScripts.get(url);
			if (h) {
				if (h.loaded) {
					cb();
				} else {
					h.cbs.push(cb);
				}
				return;
			}
		}

		console.log('Loading:', url);

		var h = $H();
		h.loaded = false;
		h.cbs = $A();
		h.cbs.push(cb);

		SL.utils._loadedScripts.set(url, h);

		new Ajax.Request(url, {
			method : 'get',
			evalJS : false,
			onSuccess : function(o) {
				try {
					eval(o.responseText);
				} catch (e) {
					console.log(e, ':', o);
				}

				h.loaded = true;
				console.log('Loaded:', url);

				if (finishedCB) {
					finishedCB();
				}

				h.cbs.each(function(cb) {
					cb();
				});
			}
		});
	};

	SL.utils.getFrameElement = function(frame, id) {
		var f = frames[frame];
		if (!f) {
			console.error("No frame:", frame, id);
			return undefined;
		}
		return f.$(id);
	};

	SL.utils.executeAfterFrameDomReady = function(frame, cb) {

		var id = undefined;
		id = setInterval(function() {
			var f = frames[frame];
			if (f && f.SL && f.SL.utils._domReadyExecuted && !f.__slInvalid) {
				try {
					cb();
					clearInterval(id);
				} catch (e) {
					clearInterval(id);
					console.error("Error in frame dom ready func:", e);
					throw e;
				}
			}
		}, 100);
	};

	SL.utils.loadJS = function(url) {
		new Ajax.Request(url, {
			method : 'get',
			evalJS : false,
			onSuccess : function(o) {
				eval(o.responseText);
			}
		});
	};

	SL.utils.endsWithExtension = function(s, extensions) {
		if (s == null || extensions == null) {
			return false;
		}
		for ( var i = 0; i < extensions.length; ++i) {
			if (s.toLowerCase().endsWith("." + extensions[i].toLowerCase())) {
				return true;
			}
		}
		return false;
	};

	SL.utils.supportsFileClick = function() {

		if (Prototype.Browser.IE) {
			return false;
		}

		if (Prototype.Browser.Gecko) {
			if (navigator.userAgent.indexOf("Firefox/3") >= 0) {
				return false;
			}

			var r = /rv:([0-9]*).([0-9]*).([0-9]*)/.exec(navigator.userAgent);
			if (r != null) {
				console.log(r);
				var v1 = parseInt(r[1]);
				var v2 = parseInt(r[2]);
				var v3 = parseInt(r[3]);

				if (v1 > 1) {
					return true;
				}

				if (v1 < 1 || v2 < 9) {
					return false;
				}

				if (v3 < 3) {
					return false;
				}
			}
		}

		return true;
	};

	SL.utils.loadStyle = function(url, cb) {

		if (SL.utils._loadedStyles) {
			if (SL.utils._loadedStyles.get(url)) {
				cb();
				return;
			}
		} else {
			SL.utils._loadedStyles = $H();
		}

		SL.utils._loadedStyles.set(url, true);

		new Ajax.Request(url, {
			method : 'get',
			evalJS : false,
			onSuccess : function(o) {
				var head = $$('head')[0];
				var e = new Element('link', {
					href : url,
					type : 'text/css',
					rel : 'stylesheet'
				});

				head.appendChild(e);

				cb.defer();
			}
		});
	};

	SL.utils.reloadWithPrompt = function(id, reloadURL, arg, defaultValue, message) {
		var v = window.prompt(message, defaultValue);
		if (v) {
			SL.byID(id).load(reloadURL + '&args.' + arg + '=' + v);
		}
	};

	SL.utils.locationReload = function(args) {

		var href = location.href;
		$H(args).each(function(e) {
			href = SL.utils.addOrReplaceUrlParam(href, e.key, e.value);
		});

		location.href = href;
	};

})();

