AVE.SelectFormatter = Class.create({
	initialize: function(el, options) {
		var select = $(el);
		// if nothing is found cancel.
		if(!select || select.tagName.toUpperCase() != "SELECT") return false;
		
		this.options = Object.extend({
		    textAttributes: ["text"],
		    valueAttribute: "value",
		    nameAttribute: "name",
		    textFormatter: "#{text}",
		    onchange: Prototype.emptyFunction
		},options || {})
		
		this.selectClickObserver = this.selectOption.bindAsEventListener(this);
		this.replacement = this.createUL(select);
		
		this.select = this.replacement.down('ul');
		
		document.observe('click', function(e){
		    var clickedEle = e.element();
		    if( clickedEle != this.replacement && !clickedEle.descendantOf(this.replacement) )
		        this.hideOptions();
		}.bind(this));
	},
	
	enable: function(select) {
		Event.observe(select,'click',this.toggleSelect.bind(this));
		var lis = $A(select.getElementsByTagName('li'));
		
		lis.each(function(li){
			Event.observe(li,'mouseover',this._optionOver);
			Event.observe(li,'mouseout',this._optionOut);
			Event.observe(li,'click',this.selectClickObserver);
		}.bind(this));
	},
	
	disable: function(select) {
		Event.stopObserving(select, 'click', this.selectClickObserver);
	},
	
	toggleSelect: function(e) {
		var select = Event.element(e).up('div.selectReplacement') || Event.element(e);
		select = select.down('ul');
		
		if(select.hasClassName('open')) {
			this.hideOptions();
		} else {
		    this.showOptions();
		}
	},
	
	showOptions : function(){
	    this.select.addClassName('open');
	},
	
	hideOptions : function(){
	    this.select.removeClassName('open');
	},
	
	_optionOver: function(e) {
		var li = Event.element(e);
			li.addClassName('hover');
	},
	
	_optionOut: function(e) {
	    var li = e.element();
	    var relTarg = e.relatedTarget || e.toElement;
	    
	    if(!$(relTarg).descendantOf(li) && li.hasClassName('hover')) 
	        li.removeClassName('hover');
	},
	
	selectOption: function(e) {
		var li = Event.findElement(e,'li');
		var ul = li.up('ul');
		var selection = li.innerHTML;
		var value = li.EP_value;
		
		$A(ul.getElementsByTagName('li')).each(function(li) {
			if(li.hasClassName('selected')) li.removeClassName('selected');
		});
		
		li.addClassName('selected');
		li.up('div').down('div').innerHTML = selection;
		this.hidden.value = value;
		this.selected = li;
		this.options.onchange(this);
	},
	
	createUL: function(select) {
	    var div = new Element('div').addClassName('selectReplacement');
	    div.attrs = new Hash();
	    var i = 0;
	    var attrs = $H(select.attributes);
	    while( i < select.attributes.length ){
	        div.attrs.set(attrs.get(i).name, attrs.get(i).nodeValue);
	        i++;
	    }
		
		var activeText	= new Element('div').addClassName('activeText');
		
		var ul = new Element('ul');
		
		var selected = false;
		$A(select.options).each(function(option){
		    
		    var o = {}
		    var template = new Template(this.options.textFormatter);
		    this.options.textAttributes.each(function(attr){
		        // browsers won't access the custom attributes the same.
		        o[attr] = (option[attr] != undefined) ? option[attr] : option.readAttribute(attr);
		        });
		    
		    var text = template.evaluate(o);
		   
			var li = new Element('li');
			li.EP_value = (option[this.options.valueAttribute] != undefined) ? option[this.options.valueAttribute] : option.readAttribute(this.options.valueAttribute); //custom attribute. use at your own risk
			li.innerHTML = text;
			ul.appendChild(li);
			
			
			if(option.selected && !selected) {
				activeText.innerHTML = (li.down("span.prompt-text")) ? li.down("span.prompt-text").innerHTML : text;
				li.className = 'selected';
				selected = true;
			}
		}.bind(this));
		
		div.insert(activeText);
		div.insert(ul);
		
		
		if(!selected) {
			activeText.innerHTML = (ul.down("li").down("span.prompt-text")) ? ul.down("li").down("span.prompt-text").innerHTML : ul.down("li").innerHTML;
			ul.down("li").className = 'selected';
		}
		
		select.insert({before: div});			
		
		// IE Doesn't make all the li's the same width. ;P
		if(Prototype.Browser.IE) {
			var width = $(ul).getWidth();
			width = (width < div.getWidth()) ? div.getWidth() : width;
			$A(div.getElementsByTagName('li')).each(function(li){
			//	li.style.width = div.getWidth() + 'px';
			});
		}
		
		this.createHidden(select);
		this.enable(div);
		
		return div;
	},
	
	createHidden: function(select) {
		var hidden = document.createElement('input');
		hidden.type = 'hidden';
		hidden.name = select.name || 'selectReplace';
		hidden.id 	= select.id || select.name || 'selectReplace';
		hidden.value = select.options[select.selectedIndex].value;
		this.hidden = select.parentNode.insertBefore(hidden,select);
		Element.remove(select); // bug? can't use select.remove()
	}/*,
	
	reset : function(wrapper){
	    var replacement = wrapper || this.replacement;
	    replacement.stopObserving('click');
	    var select = Builder.node('select');
	    replacement.attrs.each(function(attr){
	        select.writeAttribute(attr.key, attr.value);
	    });
        replacement.select('li').each(function(li){
            var option = Builder.node('option', { 'value': li.EP_value }, li.innerHTML );
            if( li.hasClassName('selected') )
                option.writeAttribute('selected', 'selected');
            select.insert(option);
        });
        replacement.insert({'after': select}).remove();
	}*/
});

document.observe('dom:loaded', function(){
	new AVE.SelectFormatter()
});
/** Used on Formula Field Creation Page **/
AVE.SelectFormatterFieldFormula = Class.create(AVE.SelectFormatter, {
    initialize: function($super, el, options) {
        $super(el, options);
        if( options.textarea )
            this.textarea = $(options.textarea);
        else
            throw( 'A textarea must be supplied.' );
    },
    
    selectOption: function($super, e) {
        $super(e);
        var li = e.element();
        this.addText(li.readAttribute('name'));
        setCursor(this.textarea);
        this.resetOptions();
    },
    
    resetOptions : function(){
        var li = this.replacement.down('li');
		var ul = li.up('ul');
		var selection = li.innerHTML;
		var value = li.EP_value;
		
		$A(ul.getElementsByTagName('li')).each(function(li) {
			if(li.hasClassName('selected')) li.removeClassName('selected');
		});
		
		li.addClassName('selected');
		li.up('div').down('div').innerHTML = selection;
		this.hidden.value = value;
		this.selected = li
		this.options.onchange(this);
    },
    
    createUL: function(select) {
			var div = new Element('div').addClassName('selectReplacement');
			var activeText	= new Element('div').addClassName('activeText');
			
			var ul = new Element('ul');
			
			var selected = false;
			$A(select.options).each(function(option){
			    
			    var o = {}
			    var template = new Template(this.options.textFormatter);
			    this.options.textAttributes.each(function(attr){
			        // browsers won't access the custom attributes the same.
			        o[attr] = (option[attr] != undefined) ? option[attr] : option.readAttribute(attr);
			        });
			    
			    var text = template.evaluate(o);
			   
				var li = new Element('li');
				li.EP_value = (option[this.options.valueAttribute] != undefined) ? option[this.options.valueAttribute] : option.readAttribute(this.options.valueAttribute); //custom attribute. use at your own risk
				
				// This is the only difference between the SuperClass method
				if( option.value !== undefined ) li.writeAttribute('name', option.value);
				
				li.innerHTML = text;
				ul.appendChild(li);
				
				if(option.selected && !selected) {
					activeText.innerHTML = (li.down("span.prompt-text")) ? li.down("span.prompt-text").innerHTML : text;
					li.className = 'selected';
					selected = true;
				}
			}.bind(this));
			
			div.insert(activeText);
			div.insert(ul);
			
			
			if(!selected) {
				activeText.innerHTML = (ul.down("li").down("span.prompt-text")) ? ul.down("li").down("span.prompt-text").innerHTML : ul.down("li").innerHTML;
				ul.down("li").className = 'selected';
			}
			
			select.insert({before: div});			
			
			// IE Doesn't make all the li's the same width. ;P
			if(Prototype.Browser.IE) {
				var width = $(ul).getWidth();
				width = (width < div.getWidth()) ? div.getWidth() : width;
				$A(div.getElementsByTagName('li')).each(function(li){
				//	li.style.width = div.getWidth() + 'px';
				});
			}
			
			this.createHidden(select);
			this.enable(div);
			
			return div;
	},
	
    addText: function(text){
        this.textarea.value = this.textarea.value + text + ' ';
    }
});
/** Used on Formula Field Creation Page **/
AVE.SelectFormatterArea = Class.create(AVE.SelectFormatter, {
    initialize: function($super, el, options) {
        $super(el, options);
        
        this.options = Object.extend({
		    textAttributes: ["text"],
		    valueAttribute: "value",
		    textFormatter: "#{text}",
		    onchange: Prototype.emptyFunction,
		    fields : '.field',
		    textarea : 'textarea'
		},options || {});
				
		this.textarea = $(this.options.textarea);
		
		$$(this.options.fields).invoke('hide');
		//console.log($(this.replacement.next().value).previous());
		$(this.replacement.next().value).previous().show();
    },
    
    selectOption: function(e) {
		var editable = true;
		
		var li = Event.findElement(e,'li');
		
		if( this.textarea.value.length > 0 && !li.hasClassName('selected')){
		    var msg = "By changing sections you will delete the current formula. Do you wish to continue?";
		    var con = confirm(msg);
		    if(con == true){
		        this.textarea.value = '';
		    }
		    else
		        editable = false;
		}
		
		if( editable === true ) {
		    // setup this select
		    var ul = li.up('ul');
		    var selection = li.innerHTML;
		    var value = li.EP_value;
    		
		    $A(ul.getElementsByTagName('li')).each(function(li) {
			    if(li.hasClassName('selected')) li.removeClassName('selected');
		    });
    		
		    li.addClassName('selected');
		    li.up('div').down('div').innerHTML = selection;
		    this.hidden.value = value;
		    this.selected = li;
		    this.options.onchange(this);
		    
		    // setup fields select
		    var val = li.readAttribute('name');
		    $$(this.options.fields).invoke('hide');
		    $(val).previous().show();
		}
	},
	
	createUL: function(select) {
			var div = new Element('div').addClassName('selectReplacement');
			var activeText	= new Element('div').addClassName('activeText');
			
			var ul = new Element('ul');
			
			var selected = false;
			$A(select.options).each(function(option){
			    
			    var o = {}
			    var template = new Template(this.options.textFormatter);
			    this.options.textAttributes.each(function(attr){
			        // browsers won't access the custom attributes the same.
			        o[attr] = (option[attr] != undefined) ? option[attr] : option.readAttribute(attr);
			        });
			    
			    var text = template.evaluate(o);
			   
				var li = new Element('li');
				li.EP_value = (option[this.options.valueAttribute] != undefined) ? option[this.options.valueAttribute] : option.readAttribute(this.options.valueAttribute); //custom attribute. use at your own risk
				
				// This is the only difference between the SuperClass method
				if( option.value !== undefined ) li.writeAttribute('name', option.value);
				
				li.innerHTML = text;
				ul.appendChild(li);
				
				if(option.selected && !selected) {
					activeText.innerHTML = (li.down("span.prompt-text")) ? li.down("span.prompt-text").innerHTML : text;
					li.className = 'selected';
					selected = true;
				}
			}.bind(this));
			
			div.insert(activeText);
			div.insert(ul);
			
			
			if(!selected) {
				activeText.innerHTML = (ul.down("li").down("span.prompt-text")) ? ul.down("li").down("span.prompt-text").innerHTML : ul.down("li").innerHTML;
				ul.down("li").className = 'selected';
			}
			
			select.insert({before: div});			
			
			// IE Doesn't make all the li's the same width. ;P
			if(Prototype.Browser.IE) {
				var width = $(ul).getWidth();
				width = (width < div.getWidth()) ? div.getWidth() : width;
				$A(div.getElementsByTagName('li')).each(function(li){
				//	li.style.width = div.getWidth() + 'px';
				});
			}
			
			this.createHidden(select);
			this.enable(div);
			
			return div;
	}
});