(function($){
	var StyledSelect = function(ele, opts) {
		if (ele.data("StyledSelectInit")) {
			return;
		}
		ele.data("StyledSelectInit", true);
		//jQuery extended select box
		this.select = ele;
		this.container = this.label = this.optionsContainer = this.timeout = this.optionsContainerClickFlag = false;
		this.select.data("StyledSelect", this);
		
		//setup the options
		this.opts = $.extend({
			/* All of these build HTML functions must return one top-level node */
			buildContainer: function(data) {
				var container = $('<div class="styledSelect"></div>');
				container.append(data.label);
				container.append(data.optionsContainer);
				return container;
			},
			buildLabel: function(data) {
				return $('<div class="label"><div class="icon"><span class="text">' + data.value + '</span></div></div>');
			},
			buildOptionsContainer: function(data) {
				var opts = $('<div class="options"><ul></ul></div>')
				opts.find("ul").append(data.opts);
				return opts;
			},
			buildOption: function(data) {
				return $('<li>' + data.value + '</li>');
			},
			focus: function(data) {
				data.container.addClass("open");
			},
			blur: function(data) {
				data.container.removeClass("open");
			},
			selectOption: function(data) {
				data.builtOption[(data.selected == true)? 'addClass' : 'removeClass']("selected");
			}
		}, opts, this.select.ParseClass());
		
		this.buildHTML(false);
		this.close();
		
		this.container.mousedown($.proxy(this._onClick, this));
		this.container.focus($.proxy(this._onFocus, this));
		this.container.blur($.proxy(this._onBlur, this));
		$(document).keydown($.proxy(this._onKeydown, this));
		
		this.optionsBuilt = false;
		$("*").live("click", $.proxy(function(e) {
			var target = $(e.target);
			if (target.closest(".styledSelect")[0] !== this.container[0]) {
				this.container.trigger("blur");
			}
		}, this));
	};
	$.extend(StyledSelect.prototype, {
		//public functions
		buildHTML: function(buildOptions) {
			this.select.data("width", this.select.outerWidth());
			this.select.hide();
			this.buildContainer(buildOptions);
			this.select.before(this.container);
		},
		buildContainer: function(buildOptions) {
			this.buildLabel();
			this.buildOptionsContainer(buildOptions);
			this.container = this.opts.buildContainer({
				label: this.label,
				optionsContainer: this.optionsContainer
			});
			this.container.attr("tabindex", 0);
			this.container.width(this.select.data("width"));
		},
		buildLabel: function() {
			var opt = this.select.find("option:selected"),
			old = this.label;
			this.label = this.opts.buildLabel({
				'key': opt.attr("value"),
				'value': opt.html()
			});
			if (old) {
				old.replaceWith(this.label);
			}
		},
		buildOptionsContainer: function(buildOptions) {
			//do we need to run this function?
			if ((buildOptions === false && this.optionsContainer) || this.optionsBuilt) {
				return;
			}
			var eles = $();
			if (buildOptions !== false) {
				for (var i=0, opts = this.select.find("option"), opt; opt = opts[i]; i++) {
					var $opt = $(opt),
					data = {
						key: $opt.attr("value"),
						value: $opt.html()
					};
					ele = this.opts.buildOption(data);
					ele.data("option", $opt);
					$opt.data("builtOption", ele);
					
					if ($opt.is(":selected")) {
						this.opts.selectOption({
							option: $opt,
							builtOption: ele,
							selected: true
						});
					}
					
					eles = eles.add(ele);
				}
				this.optionsBuilt = true;
			}
			var old = this.optionsContainer;
			this.optionsContainer = this.opts.buildOptionsContainer({
				opts: eles
			});
			if (old) {
				old.replaceWith(this.optionsContainer);
			}
			this.optionsContainer.show();
		},
		selectOption: function(opt) {
			if (opt && opt.length) {
				var old = this.select.find("option:selected");
				this.opts.selectOption({
					option: old,
					builtOption: old.data("builtOption"),
					selected: false
				});
				opt.attr("selected", true);
				this.buildLabel();
				this.opts.selectOption({
					option: opt,
					builtOption: opt.data("builtOption"),
					selected: true
				});
				this.buildOptionsContainer(true);
			}
		},
		open: function() {
			this.buildOptionsContainer();
			this.optionsContainer.show();
			this.select.trigger("focus");
		},
		close: function() {
			this.optionsContainer.hide();
			if (this.optionsBuilt) {
				this.select.trigger("blur");
			}
		},
		isOpen: function() {
			return this.optionsContainer.is(":visible");
		},
		_onClick: function(e) {
			var target = $(e.target);
			do {
				if (!target.length) {
					break;
				}
				if (target[0] == this.label[0]) {
					this._onLabelClick(e);
					break;
				} else if (target[0] == this.optionsContainer[0]) {
					this._onOptionsContainerClick(e);
					break;
				} else if (target[0] == this.container[0]) {
					this._onContainerClick(e);
					break;
				}
			} while(target = target.parent());
		},
		_onLabelClick: function(e) {
			if (this.isOpen()) {
				this.container.blur();
			} else {
				this.container.focus();
			}
			return false;
		},
		_onOptionsContainerClick: function(e) {
			//type of debouncing for options container
			//click, as ie sends blur events any time a 
			//user clicks a container scroll bar
			this.optionsContainerClickFlag = true;
			if(this.timeout) {
				clearTimeout(this.timeout);
			}
			
			var _this = this;
			this.timeout = setTimeout(function() {
				_this.optionsContainerClickFlag = false;
				_this.timeout = false;
			}, 250);
			
			
			var target = $(e.target),
			opt;
			if (target[0].tagName.toLowerCase() != 'li') {
				return;
			}
			do {
				opt = target.data("option");
				if (opt) {
					break;
				}
			} while(target = target.parent());
			if (opt) {
				this.selectOption(opt);
				this.close();
				this.select.trigger("change");
			}
		},
		_onContainerClick: function(e) {
			// do nothing...
		},
		_onKeydown: function(e) {
			if (!this.isOpen()) {
				return;
			}
			if (e.keyCode == 38) {
				//up key pressed
				this.selectOption(this.select.find("option:selected").prev());
				return false;
			} else if (e.keyCode == 40) {
				//down key pressed
				this.selectOption(this.select.find("option:selected").next());
				return false;
			} else if (e.keyCode == 27) {
				//esc key pressed
				this.close();
				return false;
			} else if (e.keyCode == 13) {
				// enter key pressed
				this.close();
				this.select.trigger("change");
				return false;
			}
		},
		_onFocus: function(e) {
			if(this.optionsContainerClickFlag === false) {
				setTimeout($.proxy(function() {
					if (!this.isOpen()) {
						this.open();
						this.opts.focus({
							container: this.container
						});
					}
				}, this), 1);
			}
			
		},
		_onBlur: function(e) {
			if(this.optionsContainerClickFlag === false) {
				this.close();
				this.opts.blur({
					container: this.container
				});
			}
		}
	});
	$.fn.extend({
		StyledSelect: function(opts) {
			this.each(function() {
				new StyledSelect($(this), opts);
			});
		}
	});
	$.StyledSelect = {
		init: function(sel) {
			//$(sel || "select:not(.noStyledSelect):visible").StyledSelect();
			$("div.myEnergyDashboardGrid, div.filtersMED, div.graphNew").find("select:not(.noStyledSelect):visible").StyledSelect();
		}
	};
	$(function() {
		$.StyledSelect.init();
		//$("select:not(.noStyledSelect)").StyledSelect();
	});
})(jQuery);

