(function($) {
	$.log = function(message) {
		if (window.console) {
			console.debug(arguments);
		} else {
			alert(message);
		}
	};

	$.fn.toggleText = function(a, b) {
		return this.each(function() {
			$(this).text($(this).text() == a ? b : a);
		});
	};
	
	
	$.leadingZeros = function(theNumber, max) {
		var numStr = String(theNumber);

		while ( numStr.length < max) {
			numStr = '0' + numStr;
		}

		return numStr;
	};
	

	$.reFullUrl = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?/gim;
	$.createHtmlAnchor = function(s, ext) {
		ext = ext ? ' rel="external"' : '';
		return s.replace($.reFullUrl, '<a href="$&"' + ext + '>$&</a>');
	}
		 


	$.stringFullDate = function(year, month, date, seperator){
		var retYear = year.toString().length === 2 ? '20'+year.toString() : year.toString();
		var retMonth = month.toString().length === 1 ? '0'+ month.toString() : month.toString();
		var retDate = date.toString().length === 1 ? '0'+date.toString() : date.toString();
		seperator = typeof seperator == 'undefined' ? '-' : seperator;
		
		return retYear + seperator + retMonth + seperator + retDate;
	};
	
	$.fn.validate = function (opt) {
		var options = {
			eventType: {
				input: 'click'
			},
			validate_form : false,
			rules : {
				required : function (elem) {
					if ($(elem).val().length === 0 && $(elem).hasClass('required')) {
						return false;
					}
					
					return true;
				},
				
				alpha_numeric : function (elem) {
					if (!(/^[A-Za-z\u00c4\u00c5\u00d6\u00e4\u00e5\u00f6\d]+$/).test($(elem).val()) && $(elem).hasClass('alpha_numeric')) {
						return false;
					}
					
					return true;
				},
				
				alpha : function (elem) {
					if (!(/^[A-Za-z\u00c4\u00c5\u00d6\u00e4\u00e5\u00f6]+$/).test($(elem).val()) && $(elem).hasClass('alpha')) {
						return false;
					}
					
					return true;
				},

				alphawithspace : function (elem) {
					if (!(/^[A-Za-z\u00c4\u00c5\u00d6\u00e4\u00e5\u00f6]+([ ]?[A-Za-z\u00c4\u00c5\u00d6\u00e4\u00e5\u00f6]+)+$/).test($(elem).val()) && $(elem).hasClass('alphawithspace')) {
						return false;
					}
					
					return true;
				},
				
				numeric : function (elem) {
					if (!(/^\d+$/).test($(elem).val()) && $(elem).hasClass('numeric')) {
						return false;
					}
					
					return true;
				},
				
				email : function (elem) {
					if (!(/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i).test($(elem).val()) && $(elem).hasClass('email')) {
						return false;
					}
					
					return true;
				}
			},
			
			validate : function (e) {
				
				if (this.valid) {
					e.data.validated_controlls -= 1;	
				}
				
				this.valid = true;
				var i;
				for (i in e.data.rules) {
					if (!e.data.rules[i](this)) {
						this.valid = false;
					}
				}
				
				e.data.validated_controlls += 1;
				
				if (this.valid) {
					e.data.onValidate(this);
				} else {
					e.data.validated_controlls -= 1;
					e.data.onError(this);
				}
				
				/* $.log(e.data.validated_controlls, e.data.controlls_to_validate, this.valid); */
				
				if (e.data.validated_controlls === e.data.controlls_to_validate){
					e.data.onValidated();
				} else {
					e.data.onFailure();
				}
			},
			
			onError : function (elem) {
				$('#' + elem.id +'_validate').addClass('validatederror');
				$('#' + elem.id +'_validate').removeClass('validated');
			},
			
			onValidate : function (elem) {
				$('#' + elem.id +'_validate').addClass('validated');
				$('#' + elem.id +'_validate').removeClass('validatederror');
			},
			
			onValidated : function(){
				$('#' + options.form_button + ', .' + options.form_button).removeClass(options.form_button_css);
				$('#' + options.form_button + ', .' + options.form_button).attr('disabled', '');
			},
			
			onFailure : function(){
				$('#' + options.form_button + ', .' + options.form_button).addClass(options.form_button_css);
				$('#' + options.form_button + ', .' + options.form_button).attr('disabled', 'disabled');
			}
		};

		if (typeof opt !== 'undefined') {
			$.extend(true, options, opt);
		}

		if (typeof options.form_button !== 'undefined'){
			$('#' + options.form_button + ', .' + options.form_button).addClass(options.form_button_css);
			$('#' + options.form_button + ', .' + options.form_button).attr('disabled', 'disabled');
		} 

		this.each(function (index, elem) {
			var controlls_to_validate = $(elem).find('.validate'), i, isCheckBox = false;
			if (typeof options.eventType.checkbox !== 'undefined') {
				isCheckBox = true;
			}
			
			options.validated_controlls = 0;
			options.controlls_to_validate = controlls_to_validate.length;
			controlls_to_validate.each(function (i, child) {
				
				
				/** HACK due to .net <div><span> wrapping the captcha control. **/
				if (child.nodeName === 'DIV'){
					child = $(child).find('span input:first').get(0);
				}
				
				
				for (i in options.eventType) {
					/** HACK due to .net <span> wrapping input[checkbox] **/
					if (i == 'checkbox' && child.nodeName === 'SPAN') { child = $(child).find('input:first').get(0); }
					
					if (child.nodeName === i.toUpperCase() && isCheckBox && child.type !== 'checkbox') {
						$(child).bind(options.eventType[i], options, options.validate);
					} else if (child.nodeName === 'INPUT' && isCheckBox && child.type === 'checkbox') {
						$(child).bind(options.eventType[i], options, options.validate);
					} else if (child.nodeName === i.toUpperCase()) {
						$(child).bind(options.eventType[i], options, options.validate);
					}
				}
			});
		});
	};

	$.j = function(selectors, j) {
		var ret = [], p = [], value, selector, parent = false, getValue = false;
		var selectorArray = selectors.split(' ');

		function add(obj, n) {
			if (parent) {
				ret.push(obj);
			} else {
				ret.push(obj[n]);
			}
		}

		var find = function(selector, obj, target) {
			if (typeof obj == 'array' || typeof obj.length == 'number') {
				for (var i = 0; i < obj.length; i++) {
					if (getValue && obj[i] == value) { add(obj, i); }
					else { find(selector, obj[i], target); }
				}
			} else if (typeof obj == 'object') {
				for (var x in obj) {
					if (typeof x != 'undefined') {
						if (!target && !getValue && x == selector && typeof obj[x] != "string") { p.push(obj[x]); }
						else if (!getValue && x == selector && target) { add(obj, x); }
						else if (getValue && x == selector && obj[x] == value) { add(obj, x); }
						else if (typeof obj[x] == "object" || typeof obj[x] == "array") { find(selector, obj[x], target); }
					}
				}
			}
		};

		for (var i = 0, l = selectorArray.length; i < l; i++) {
			selector = selectorArray[i];
			if (selector.indexOf(':') != -1) {
				parent = true;
				selector = selector.substring(0, selector.indexOf(':'));
			}

			var re = /\[[a-zA-Z]+\]/;
			getValue = re.test(selector);
			if (getValue) {
				value = selector.substring(re.exec(selector).index + 1, (selector.length - 1));
				selector = selector.substring(0, re.exec(selector).index);
			}

			var d = i == (l - 1) && p.length !== 0 ? p : j;
			var t = (i == (l - 1) ? true : false);
			find(selector, d, t);
		}

		return ret.length == 1 ? ret[0] : ret;
	};

	$.memberOf = function(val, ary) {
		var _ary = typeof ary == 'string' ? (ary.indexOf(',') != -1 ? ary.split(',') : ary) : ary;
		var ret = false;
		var i, s;
		for (i = 0, s = _ary.length; i < s; i++) {
			if (_ary[i] == val) {
				ret = true;
			}
		}

		return ret;
	};

	$.arrayIndex = function(val, array) {
		for (var i = 0, l = array.length; i < l; i++) {
			if (array[i] == val) {
				return i;
			}
		}

		return -1;
	};

	$.fn.bindEvent = function() {
		var _event = arguments[0].event, _callback = arguments[0].callback;
		for (var i = 0; i < _callback.length; i++) {
			var __callback = _callback[i];
			$(this).bind(_event, __callback, function(e) { 
				eval(e.data.n)[e.data.f](arguments); 
			});
		}
	};

	var m = {
		'\b': '\\b',
		'\t': '\\t',
		'\n': '\\n',
		'\f': '\\f',
		'\r': '\\r',
		'"': '\\"',
		'\\': '\\\\'
	},
        s = {
        	'array': function(x) {
        		var a = ['['], b, f, i, l = x.length, v;
        		for (i = 0; i < l; i += 1) {
        			v = x[i];
        			f = s[typeof v];
        			if (f) {
        				v = f(v);
        				if (typeof v == 'string') {
        					if (b) {
        						a[a.length] = ',';
        					}
        					a[a.length] = v;
        					b = true;
        				}
        			}
        		}
        		a[a.length] = ']';
        		return a.join('');
        	},
        	'boolean': function(x) {
        		return String(x);
        	},
        	'null': function(x) {
        		return "null";
        	},
        	'number': function(x) {
        		return isFinite(x) ? String(x) : 'null';
        	},
        	'object': function(x) {
        		if (x) {
        			if (x instanceof Array) {
        				return s.array(x);
        			}
        			var a = ['{'], b, f, i, v;
        			for (i in x) {
        				v = x[i];
        				f = s[typeof v];
        				if (f) {
        					v = f(v);
        					if (typeof v == 'string') {
        						if (b) {
        							a[a.length] = ',';
        						}
        						a.push(s.string(i), ':', v);
        						b = true;
        					}
        				}
        			}
        			a[a.length] = '}';
        			return a.join('');
        		}
        		return 'null';
        	},
        	'string': function(x) {
        		if (/["\\\x00-\x1f]/.test(x)) {
        			x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
        				var c = m[b];
        				if (c) {
        					return c;
        				}
        				c = b.charCodeAt();
        				return '\\u00' +
                            Math.floor(c / 16).toString(16) +
                            (c % 16).toString(16);
        			});
        		}
        		return '"' + x + '"';
        	}
        };

	$.toJSON = function(v) {
		var f = isNaN(v) ? s[typeof v] : s.number;
		if (f) {
			return f(v);
		}
	};

	$.parseJSON = function(v, safe) {
		if (safe === undefined) {
			safe = $.parseJSON.safe;
		}
		if (safe && !/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(v)) {
			return undefined;
		}
		return eval('(' + v + ')');
	};

	$.parseJSON.safe = false;
	
	if (typeof $.datepicker != 'undefined') {
		$.datepicker.regional.sv = {
			closeText: 'St' + unescape('%E4') + 'ng',
			prevText: 'F' + unescape('%F6') + 'rra',
			nextText: 'N' + unescape('%E4') + 'sta',
			currentText: 'Idag',
			monthNames: ['Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni',
			'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December'],
			monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun',
			'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'],
			dayNamesShort: ['S' + unescape('%F6') + 'n', 'M' + unescape('%E5') + 'n', 'Tis', 'Ons', 'Tor', 'Fre', 'L' + unescape('%F6') + 'r'],
			dayNames: ['S' + unescape('%F6') + 'ndag', 'M' + unescape('%E5') + 'ndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag', 'L' + unescape('%F6') + 'rdag'],
			dayNamesMin: ['S' + unescape('%F6') + '', 'M' + unescape('%E5') + '', 'Ti', 'On', 'To', 'Fr', 'L' + unescape('%F6') + ''],
			dateFormat: 'yy-mm-dd', firstDay: 1,
			isRTL: false
		};
		$.datepicker.setDefaults($.datepicker.regional.sv);
	}
})(jQuery);

