(function($) {
	$.fn.extend({
		StyledSelect: function(config) {
			this.each(function(key, ele) {
				new $.fn.StyledSelect.StyledSelect(ele, config);
			});
			return this;
		}
	});
	$.fn.StyledSelect.StyledSelect = function(ele, config)
	{
		if (typeof(ele) == "string") {
			ele = document.getElementById(ele);
		}
		if (ele.tagName.toLowerCase() != "select") {
			//we can't initialize because we don't have a select box to initialize on
			return;
		}

		if (ele.StyledSelectInstance) {
			//we never want to initialize on the same element twice
			return;
		}
		ele.StyledSelectInstance = this;
		this.ele = ele;

		//setup default config values
		this.config = {
			containerClass: "StyledSelect",
			selectedClass: "selected",
			hoverClass: "hover",
			toggleClass: "toggle",
			disabledClass: "disabled",
			openClass: "open",
			isMultiSelect: (this.ele.multiple) ? true : false,
			showCheckbox: (this.ele.multiple) ? true : false,
			defaultNoneLabel: "No Values Selected",
			defaultAllLabel: "All Selected"
		};

		//extend the default config with any config passed to the init function
		for (var key in config) {
			this.config[key] = config[key];
		}

		//extend the default config with any config in the class of the select element

		var $ele = $(ele);
		if ($ele.ParseClass) {
			var classConfig = $(ele).ParseClass();
			for (var key in classConfig) {
				this.config[key] = classConfig[key];
			}
		}

		this._createElements();
		this._attachEvents();
		this.updateLabel();
	};

	$.extend($.fn.StyledSelect.StyledSelect.prototype, {
		/* Private Methods */
		_createElements: function() {
			this.container = $.extend(document.createElement("div"), {
				className: this.config.containerClass + " " + this.ele.className,
				innerHTML: '<div class="label"><div class="icon"><div class="titleText">&nbsp;</div></div></div><div class="ulContainer" style="display: none;"></div>'
			});

			this.ele.parentNode.insertBefore(this.container, this.ele);

			this.ulcontainer = $("div.ulContainer", this.container)[0];

			this.ele.style.display = "none";
		},
		_attachEvents: function() {
			var _this = this;
			$(this.container).bind("mouseover", function(e) {
				return _this._onMouseOver(e);
			});
			$(this.container).bind("mouseout", function(e) {
				return _this._onMouseOut(e);
			});
			$(document).bind("click", function(e) {
				return _this._onClickDocument(e);
			});
			$(document).bind("blur", function(e) {
				return _this.closeContainer(e);
			});
			$(this.ele.form).bind("reset", function(e) {
				setTimeout(function() {
					_this._onResetForm(e);
				}, 1);
			});
		},
		_onClick: function(e) {
			var ele = e.target,
			temp = ele;

			do {
				if (temp.tagName.toLowerCase() == "li") {
					this.selectOption(temp);
					break;
				} else if ($(temp).hasClass("label")) {
					this.toggleULContainer();
					break;
				}
				temp = temp.parentNode;
			} while(temp && temp != this.container);

			return false;
		},
		_onMouseOver: function(e) {
			var ele = e.target;

			this._removeHoverClass();

			do {
				$(ele).addClass("hover");
				if (ele == this.container) {
					break;
				}
			} while(ele && (ele = ele.parentNode));

			return false;
		},
		_onMouseOut: function(e) {
			this._removeHoverClass();
		},
		_onClickDocument: function(e) {
			if ($(this.container).hasClass(this.config.disabledClass)) {
				return;
			}

			var ele = e.target;

			if (ele.tagName.toLowerCase() == "label" && ele.getAttribute("for") == this.ele.getAttribute("id")) {
				this.toggleULContainer();
			} else if (this._inContainer(ele)) {
				this._onClick(e);
			} else if (ele == this.ele) {
				//do nothing. You can't click a hidden element, but FF sometimes fires the event anyway
			} else {
				this.closeContainer();
			}
		},
		_onResetForm: function(e) {
			this.ulcontainer.innerHTML = '';
			if(this.config.isMultiSelect === false) {
				this.ele.options[this.ele.selectedIndex].selected = true;
			}
			this.updateLabel();

			$(this.ele).trigger("click");
			$(this.ele).trigger("change");
		},
		_removeHoverClass: function() {
			var hoverEles = $(this.container).find(".hover");

			$(this.container).removeClass("hover");
			for (var i=0, hoverEle; hoverEle = hoverEles[i]; i++) {
				$(hoverEle).removeClass("hover");
			}
		},
		_inContainer: function(ele) {
			do {
				if (ele == this.container) {
					return true;
				}
			} while(ele = ele.parentNode);
			return false;
		},
		_selectOption: function(li, selected) {
			if (this.ulcontainer.getElementsByTagName("ul").length <= 0) {
				//hasn't inited yet... do nothing
				return;
			}
			if (li.tagName.toLowerCase() == "option") {
				var lis = this.ulcontainer.getElementsByTagName("li");
				for (var i=0, li2; li2 = lis[i]; i++) {
					if (li2.opt == li) {
						li = li2;
					}
				}
			}
			li.opt.selected = selected;
			var input = li.getElementsByTagName("input")[0];
			if (input) {
				input.checked = selected;
			}
		},
		/* Public Methods */
		closeContainer: function() {
			this.toggleULContainer(false);
		},
		toggleULContainer: function(show) {
			this.buildUL();

			show = (show === true || (typeof(show) == "undefined" && this.ulcontainer.style.display == "none")) ? true : false;
			if (show === true) {
				this.ulcontainer.style.display = "";
				$(this.container).addClass("open");
			} else {
				this.ulcontainer.style.display = "none";
				$(this.container).removeClass("open");
			}
		},
		buildUL: function(forceRefresh) {
			if (!forceRefresh && this.ulcontainer.getElementsByTagName("ul").length > 0) {
				return;
			}
			if (forceRefresh) {
				this.ulcontainer.innerHTML = '';
				return;
			}
			var ul = document.createElement("ul"),
			checkbox = (this.config.showCheckbox) ? '<input type="checkbox" class="checkbox" name="" /> ' : '';
			for (var i=0, opt; opt = this.ele.options[i]; i++) {
				var li = document.createElement("li");
				li.innerHTML = checkbox + opt.innerHTML;
				li.opt = opt;
				ul.appendChild(li);
			}

			this.ulcontainer.appendChild(ul);

			this.updateSelectedClass();
		},
		updateSelectedClass: function() {
			var lis = this.ulcontainer.getElementsByTagName("li");
			for (var i=0, li; li = lis[i]; i++) {
				if (li.opt.selected == true) {
					$(li).addClass("selected");
				} else {
					$(li).removeClass("selected");
				}
			}
		},
		disable: function(dis) {
			var func = (dis === false) ? 'removeClass' : 'addClass';
			this.ele.disabled = (dis === false) ? false : true;
			$(this.container)[func](this.config.disabledClass);
			this.closeContainer();
		},
		selectOption: function(li) {
			if (this.config.isMultiSelect && $(li.opt).hasClass(this.config.toggleClass)) {
				var selected = !(li.opt.selected),
				eles = this.ulcontainer.getElementsByTagName("li");
				for (var i=0, ele; ele = eles[i]; i++) {
					this._selectOption(ele, selected);
				}
			} else if (this.config.isMultiSelect && li.opt.selected) {
				this._selectOption(li, false);
			} else {
				this._selectOption(li, true);
			}
			this.updateLabel();

			this.updateSelectedClass();

			if (!this.config.isMultiSelect) {
				this.toggleULContainer(false);
			}

			$(this.ele).trigger("click");
			$(this.ele).trigger("change");
		},
		updateLabel: function(onlyReturnLabel) {
			var selectedOptions = [],
			selectedToggles = [],
			label = '',
			toggles = [];
			for (var i=0, opt; opt = this.ele.options[i]; i++) {
				if ($(opt).hasClass(this.config.toggleClass)) {
					toggles.push(opt);
					continue;
				}
				if (opt.selected) {
					selectedOptions.push(opt);
					if ($(opt).hasClass(this.config.toggleClass)) {
						selectedToggles.push(opt);
					}
					if (!this.config.isMultiSelect) {
						break;
					}
				}
			}

			if (selectedOptions.length <= selectedToggles.length) {
				label = this.config.defaultNoneLabel;
				for (var i=0, toggle; toggle = toggles[i]; i++) {
					this._selectOption(toggle, false);
				}
			} else if (selectedOptions.length >= (this.ele.options.length - toggles.length)) {
				label = this.config.defaultAllLabel;
				for (var i=0, toggle; toggle = toggles[i]; i++) {
					this._selectOption(toggle, true);
				}
			}

			if (label == ""){
				var selectedText = [];
				for (var i=0, opt; opt = selectedOptions[i]; i++) {
					selectedText.push(opt.innerHTML);
				}
				label = selectedText.join(", ");
			}
			if (onlyReturnLabel === true) {
				return label;
			}
			return this.label(label);

		},
		label: function(val) {
			var h = this.container.offsetHeight,
			labelEle = $(this.container).find("div.titleText")[0],
			temp = document.createElement("div");

			if (val == "") {
				val = "&nbsp;";
			}

			var append = "";
			if (typeof(val) != "undefined") {
				while(true) {
					temp.innerHTML = val+append;

					while(labelEle.firstChild) {
						labelEle.removeChild(labelEle.firstChild);
					}
					while(temp.firstChild) {
						labelEle.appendChild(temp.firstChild);
					}
					if (this.container.offsetHeight <= h) {
						break;
					}
					val = val.substr(0, val.length-1);
					append = "&hellip;";
				}
			}
			return labelEle.innerHTML;
		}
	});
	$(document).ready(function() {
		$("select.styledSelect").StyledSelect({
			defaultAllLabel: false
		}).filter('.StyledSelectJump').change(function() {
			window.location = $(this).val();
		});
		$('#region').click(function() {
			$(this).toggleClass('hover').children('ul');
		});
		$('#region').hover(function(){},function(){
			$(this).removeClass('hover').children('ul');
		});
		$('#mainNav li:not(#search)').hover(function(){
			$(this).addClass('hover').children('ul');
		},function(){
			$(this).removeClass('hover').children('ul');
		});
		$('a.external').attr('target','_blank');
	});
})(jQuery);
