var Classy = {
	String: {
		supplant:function(str,o,regexp){
			regexp = regexp || new RegExp(/{([^{}]*)}/g);
			return str.replace(regexp,
				function (a, b) {
					var r = o[b];
					return typeof r === 'string' || typeof r === 'number' ? r : a;
				}
			);
		}
	}
};


/**
 * Classy.SelectInput
 *
 * @author		Charles Demers (charles.demers6@gmail.com)
 * @requires	[classy.js, jquery-1.4.2.js]
 * @provides 	[classy.SelectInput]
 *
 */

Classy.SelectInput = function(selectElement, opts) {
	
	var realSelect = this.realSelect = $(selectElement);
	var realSelectHtml = this.realSelectHtml = realSelect.get(0);
	
	this.onCreation = opts.onCreation || false;
	this.onChange = opts.onChange || false;
	
	this.id = opts.id || false;
	this.optionsAreVisible = false;
	this.isAnimated = opts.isAnimated || false;
	this.hasOptGroups = false;
	
	var markup = {
		id:""
	};
	
	
	var mainUl = $("<ul class='classy-select-input-options'>");
	
	var markupOptions = [];
	
	var realOptGroups = realSelectHtml.getElementsByTagName("optgroup");
	
	if(realOptGroups.length > 0) {
		this.hasOptGroups = true;
		
		for(var i=0, l=realOptGroups.length; i<l; i++) {
			markupOptions.push("<li class='classy-select-input-optgroup'>"+realOptGroups[i].label+"<ul>");
			var realOpts = realOptGroups[i].getElementsByTagName("option");
			for(var ind=0, len=realOpts.length; ind<len; ind++) {
				markupOptions.push("<li><span class='classy-select-input-check'></span>"+realOpts[ind].text+"</li>");
			}
			markupOptions.push("</ul></li>");
		}
	} else {
		var realOptions = realSelectHtml.getElementsByTagName("option");
	
		for(var j=0,k=realOptions.length; j<k; j++) {
			markupOptions.push("<li><span class='classy-select-input-check'></span>"+realOptions[j].text+"</li>");
		}
	}
	mainUl.html(markupOptions.join(''));
	this.options = $(mainUl).appendTo("body");
	
	if(this.id) {
		markup.id = "id='"+this.id+"' ";
	}
	var html = "<div {id}class='classy-select-input'><p class='classy-select-input-selected'></p><div class='classy-select-input-arrow'></div></div>";
	
	this.select = select = $(Classy.String.supplant(html, markup)).insertAfter(realSelect);
	
	realSelect.css('display','none');
	
	this.index(this.defaultIndex());
	
	if(!opts.isDelayedEnabled) {
		this.enable();
	}
	
	if(this.onCreation) {
		this.onCreation.call(this);
	}
};
Classy.SelectInput.prototype = {
	add:function(opts) {
		var realOpt = "<option value='"+opts.value+"'>"+opts.text+"</option>",
			fakeOpt = "<li><span class='classy-select-input-check'></span>"+opts.text+"</li>";
		if(typeof opts.index == "undefined" || opts.index == this.length()) {
			this.realSelect.append(realOpt);
			this.options.append(fakeOpt);
		} else {
			var realIndex = this.realSelect.find("option:eq("+opts.index+")");
			var fakeIndex = this.options.find("li:not(.classy-select-input-optgroup)").filter("li:eq("+opts.index+")");
			realIndex.before(realOpt);
			fakeIndex.before(fakeOpt);
		}
	},
	remove:function(index) {
		this.realSelect.get(0).remove(index);
		this.options.find("li:eq("+index+")").remove();
	},
	enable:function() {
		var _this = this;
		var select = $(this.select);
		select.bind("click",function() {
			_this.toggleOptionsVisibility();
		});

		select.bind("mouseover",function() {
			$(this).css("cursor","pointer");
		});
		select.bind("mouseout",function() {
			$(this).css("cursor","default");
		});
		this.options.delegate("li:not(.classy-select-input-optgroup)", 'mouseover', function() {
			$(this).addClass('hover');
		});
		this.options.delegate("li:not(.classy-select-input-optgroup)", 'mouseout', function() {
			$(this).removeClass('hover');
		});
		this.options.delegate("li:not(.classy-select-input-optgroup)", 'click', function() {
			if(_this.hasOptGroups) {
				var options = _this.getOptions();
				for(var i=options.length; i--; ) {
					if($(options[i]).filter(this).length > 0) {
						_this.index(i);
					}
				}
			} else {
				_this.index($(this).index());
			}
			_this.hideOptions();
			return false;
		});
		
		$(window).bind('resize', $.proxy(this, "hideOptions"));
		
		// handle click outside
		$(document).bind('click', $.proxy(this, "manageClickOutside"));
	},
	manageClickOutside:function(e) {
		if(this.optionsAreVisible) {
			var parentElement = this.realSelect.next('.classy-select-input').get(0);
			if($.contains(parentElement,e.target) === false && parentElement !== e.target) {
				this.hideOptions();
			}
		}
	},
	disable:function() {
		var select = $(this.select);
		select.unbind("click");
		select.unbind("mouseover");
		select.unbind("mouseout");
		this.options.undelegate("li","mouseover");
		this.options.undelegate("li","mouseout");
		this.options.undelegate("li","click");
		$(document).unbind("click", this.manageClickOutside);
		$(window).unbind('resize', this.hideOptions);
	},
	length:function() {
		return this.realSelectHtml.length;
	},
	defaultIndex:function() {
		var defaultSelected;
		for(var i=0,l=this.realSelectHtml.options.length; i<l; i++) {
			if(this.realSelectHtml.options[i].defaultSelected) {
				return i;
			}
		}
		return 0;
	},
	defaultValue:function() {
		var index = this.defaultIndex;
		return this.realSelectHtml.options[index].value;
	},
	index:function(index) {
		if(typeof index == "undefined") {
			return this.realSelectHtml.selectedIndex;
		} else {
			this.realSelect.find("option:selected").removeAttr('selected');
			var selected = this.realSelect.find("option:eq("+index+")");
			
			var thisSelected = this.getOptions()[index];
			this.options.find("li.selected").removeClass("selected");
			$(thisSelected).addClass("selected");
			
			selected.attr('selected','selected');
			this.select.find(".classy-select-input-selected").text(selected.get(0).text);
			if(this.onChange) {
				this.onChange.call(this,this.value());
			}
		}
	},
	value:function(value) {
		if(typeof value == "undefined") {
			return this.realSelectHtml.value;
		} else {
			this.realSelect.find(":selected").removeAttr('selected');
			var selected = this.realSelect.find("option[value="+value+"]");

			var index = selected.get(0).index;
			
			var thisSelected = this.getOptions()[index];
			this.options.find("li.selected").removeClass("selected");
			$(thisSelected).addClass("selected");
			
			selected.attr('selected','selected');
			this.select.find(".classy-select-input-selected").text(selected.get(0).text);
			if(this.onChange) {
				this.onChange.call(this,this.value());
			}
		}
	},
	toggleOptionsVisibility:function() {
		if(this.optionsAreVisible) {
			this.hideOptions();
		} else {
			this.showOptions();
		}
	},
	showOptions:function() {
		
		var offset = this.select.offset(),
			height = this.select.outerHeight();
		
		this.options.css({
			top:offset.top + height,
			left:offset.left
		});
		
		this.optionsAreVisible = true;
		if(!this.isAnimated) {
			$(this.options).css('display','block');
		} else {
			$(this.options).slideDown(150);
		}
	},
	hideOptions:function() {
		this.optionsAreVisible = false;
		if(!this.isAnimated) {
			$(this.options).css('display','none');
		} else {
			$(this.options).slideUp(150);
		}
	},
	getOptions:function() {
		return this.options.find("li:not(.classy-select-input-optgroup)");
	}
};


/*
	Radio Input,
*/

Classy.RadioInput = function(radiosElement, opts){
	var _this = this;
	
	this.radiosName = radiosElement;
	
	var realRadios = this.realRadios = $('input[name='+radiosElement+']');
	var realRadiosHtml = this.realRadiosHtml = [];
	realRadios.each(function(i, el) {
		if(this.checked) { _this.defaultIndex = i; }
		_this.realRadiosHtml[i] = this;
	});
	
	this.onCreation = opts.onCreation || false;
	this.onChange = opts.onChange || false;
	
	this.cssClass = opts.cssClass || "";
	
	var html = "";
	
	this.radios = [];
	var checkedClass = '';
	for(var i=0;i<realRadios.length;i++) {
		if(i == _this.defaultIndex) { checkedClass = ' classy-radio-input-checked'; }
		else { checkedClass = '' }
		this.radios[i] = $("<div id='classy-radio-input-"+i+"' class='classy-radio-input"+checkedClass+" "+this.cssClass+"' rel='"+realRadios[i].value+"'></div>").insertAfter(realRadios[i]);
	}
	
	realRadios.css('display','none');
	
	if(!opts.isDelayedEnabled){
		this.enable();
	}
	
	if(this.onCreation){
		this.onCreation.call(this);
	}
};
Classy.RadioInput.prototype = {
	enable:function(){
		var _this = this;
		var radios = $(this.radios);
		
		radios.each(function(i) {
			this.bind('click', function() {
				var radio = _this.realRadios[i];
				if(!radio.checked) {
					_this.setValue(radio.value);
				}
			});
		});
		
		_this.realRadios.bind('change', function() {
			_this.setValue(this.value);
		});
		
	},
	disable:function(){ // TO DO
		var radios = $(this.radios);
		radios.unbind("click");
	},
	defaultValue:function(){ // TO DO
		var index = this.defaultIndex;
		var defaultValue = false;
		if(index) { this.setValue(index, true); }
		
		return defaultValue;
	},
	value:function(){
		return this.realRadiosHtml.filter(':checked').value;
	},
	setValue:function(val, isIndex) {
		var radios = $(this.radios);
		
		if(isIndex && this.realRadios[val]) {
			radios.removeClass('classy-radio-input-checked');
			
			this.realRadios[val].checked = true;
			radios[val].addClass('classy-radio-input-checked');
			
			rtn = true;
		}
		else {
			var rtn = false;
			var valRadio = $('input[name='+this.radiosName+'][value='+val+']');
			if(valRadio.length > 0) {
				
				valRadio.attr('checked', 'checked');
				radios.each(function() {
					var r = $(this);
					if(r.attr('rel') == val) { r.addClass('classy-radio-input-checked'); }
					else { r.removeClass('classy-radio-input-checked'); }
				});
				
				rtn = true;
			}
		}
		
		return rtn;
	}
};
