define([], function() {
	'use strict';
	var module = {};

	function getRequestRandom() {
		return Math.floor(Math.random() * (10000000000000 + 1));
	}

	function loadScripts(uris, whenDone) {
		if (!uris.length)
			whenDone && whenDone();
		else {
			for (var wait = [], i = uris.length; i--;) {
				var tag = document.createElement('script');
				tag.type = 'text/javascript';
				tag.src = uris[i];
				if (whenDone) {
					wait.push(tag);
					tag.onload = maybeDone;
					tag.onreadystatechange = maybeDone; // For IE8-
				}
				document.head.appendChild(tag);
			}
		}
		function maybeDone() {
			if (this.readyState === undefined || this.readyState === 'complete') {
				for (var i = wait.length; i--;)
					if (wait[i] == this)
						wait.splice(i, 1);
				if (!wait.length)
					whenDone();
			}
		}
	}

	module.require = function(uris, whenDone) {
		// disable cache
		var i;
		for (i = 0; i < uris.length; i += 1) {
			uris[i] = uris[i] + '?_=' + getRequestRandom();
		}

		loadScripts(uris, whenDone);
	};

	module.getPrototypeName = function(obj) {
		var funcNameRegex = /function (.{1,})\(/;
		var results = (funcNameRegex).exec((obj).constructor.toString());
		return (results && results.length > 1) ? results[1] : "";
	};

	module.isFunction = function(functionToCheck) {
		var getType = {};
		return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
	};
	var isFunction = module.isFunction;

	module.getWindowFromElement = function(element) {
		var $e = window.jQuery(element);
		var e = $e[0];
		var doc = e.ownerDocument;
		var win = doc.defaultView || doc.parentWindow;
		return win;
	};

	module.del = function(obj, prop) {
		if (obj && obj[prop]) {
			if (obj[prop].unload && isFunction(obj[prop].unload)) {
				obj[prop].unload();
			}
			delete obj[prop];
		}
	};

	module.deleteObject = function(obj) {
		for ( var member in obj)
			delete obj[member];
	};

	module.waitFor = function(condition, callback, interval) {
		interval = interval || 100;
		var isLoaded = condition();
		if (isLoaded) {
			callback();
		} else {
			setTimeout(function() {
				module.waitFor(condition, callback, interval);
			}, interval);
		}
	};

	module.supportsStorage = function() {
		try {
			return 'localStorage' in window && window['localStorage'] !== null;
		} catch (e) {
			return false;
		}
	};

	module.setLocal = function(key, obj) {
		if (module.supportsStorage()) {
			var item = obj;
			if (obj != null) {
				item = JSON.stringify(obj);
			}
			window.localStorage.setItem(key, item);
		}
	};

	module.getLocal = function(key) {
		if (module.supportsStorage()) {
			var item = window.localStorage.getItem(key);
			if (item) {
				return JSON.parse(item);
			}
		}
		return null;
	};

	module.limitOpacity = function(opacity) {
		if (opacity < 0.001)
			return 0.001;
		if (opacity > 0.999)
			return 1;
		return opacity;
	};

	module.isInternetExplorer = function() {
		return window.navigator.appVersion.indexOf('MSIE') != -1;
	};

	module.preventEvent = function(e) {
		e.preventDefault();
		return false;
	};

	module.format = function(str) {
		var i;
		for (i = 1; i < arguments.length; i++) {
			str = str.replace('{' + (i - 1) + '}', arguments[i]);
		}
		return str;
	};

	module.pad = function(number, length) {
		var str = '' + number;
		while (str.length < length) {
			str = '0' + str;
		}
		return str;
	};

	var pad = module.pad;

	module.getTimeStr = function() {
		var time = new Date();
		return module.format('{0}:{1}:{2}.{3}', pad(time.getHours(), 2), pad(time.getMinutes(), 2), pad(time.getSeconds(), 2), pad(time.getMilliseconds(), 3));
	};

	var seen = [];
	var jsonReplacer = function(key, val) {
		if (val != null && typeof val == "object") {
			if (seen.indexOf(val) >= 0) {
				return;
			}
			seen.push(val);
		}
		return val;
	};

	module.toJson = function(obj) {
		try
		{
			return JSON.stringify(obj, jsonReplacer);
		}
		catch(e)
		{
			module.log(obj);
			module.log(e);
		}
	};

    var debug = false;
	if (window && window.location && window.location.href && window.location.href.indexOf('debug=1') >= 0) {
		debug = true;
	}
	module.log = function() {
        if (!debug) return;
		var args = [].slice.call(arguments);
		var error = null;
		var i;
		for (i = 0; i < args.length; i += 1) {
			if (typeof args[i] === 'object') {
				try {
					if (args[i] instanceof Error) {
						error = args[i];
						console.warn(error.stack);
					} else {
						args[i] = JSON.stringify(args[i]);
					}
				} catch (e) {
					// Could not convert to JSON
					args[i] = args[i].toString();
				}
			}
		}
		args.unshift(module.getTimeStr());
		console.info(args);
	};

	/**
	 * Overwrites obj1's values with obj2's and adds obj2's if non existent in
	 * obj1
	 *
	 * @param obj1
	 * @param obj2
	 * @returns obj3 a new object based on obj1 and obj2
	 */
	module.mergeOptions = function(a, b) {
		var c = {}, at;
		for (at in a) {
			c[at] = a[at];
		}
		for (at in b) {
			c[at] = b[at];
		}
		return c;
	};

	/*
	 * function globalErrorHandler(message, url, lineNumber) { // save error and
	 * send to server for example.
	 *
	 * if (!scriptDbg) { console.info('deactivate the global error handler to
	 * see errors'); return true; }
	 *
	 * return false; }; window.addEventListener('error' //window.onerror =
	 * globalErrorHandler;
	 */

	module.trimr = function(str, ch) {
		for (var i = str.length - 1; i >= 0; i--) {
			if (ch != str.charAt(i)) {
				str = str.substring(0, i + 1);
				break;
			}
		}
		return str;
	};

  module.guid = function(){
    var d = new Date().getTime();
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = (d + Math.random()*16)%16 | 0;
        d = Math.floor(d/16);
        return (c=='x' ? r : (r&0x3|0x8)).toString(16);
    });
    return uuid;
  };

	return module;
});
