/*
 * NB Select Class
 * 
 * @require 	mootools javascript framework
 * 
 * @author 		Steffen Maechtel <s.maechtel@netzbewegung.com>
 * @version 	2.00 alpha
 */

// IE debug error fix :]
if (!window.console) {
	Console = new Class({});
	Console.implement({log: function(param) {}});
	console = new Console();
}


// Namespace NB
if (!window.NBX) {
	NBX = {};
}

// NB Controller
NBX.Controller = new Class({
	initialize: function() {
		this.objCurrentLayer = {};
	}
});


NBX.Controller.implement({
	hideCurrentLayer: function(objCurrent) {
		if (this.objCurrentLayer && this.objCurrentLayer.hide && objCurrent !== this.objCurrentLayer) {
			this.objCurrentLayer.hide();
		}
	},
	
	registerCurrentLayer: function(objCurrent) {
		if (!this.objBody) {
			this.objBody = $$('body')[0];
		}
		
		if (objCurrent !== this.objCurrentLayer) {
			this.objCurrentLayer = objCurrent;
			
			this.objBody.removeEvents('click');
			this.objBody.addEvent('click', this.objCurrentLayer.hide.create({
				'bind': this.objCurrentLayer,
				'event': true
			}));
		
			// internet explorer
			if (Browser.Engine.trident) {
				var objElement = this.objBody;
			} 
			// firefox and friends
			else {
				var objElement = window;
			}
			
			objElement.removeEvents('keydown');
			objElement.addEvent('keydown', this.objCurrentLayer.key.create({
				'bind': this.objCurrentLayer,
				'event': true
			}));
		}
	}
});

NBX.objController = new NBX.Controller();

// NB Select
NBX.Select = new Class({
	initialize: function(objElement, intMaxItemCount) {
		this.intMaxItemCount = intMaxItemCount || -1;
		
		
		this.bolStatus  = false;
		this.objOrginal = {};
		this.objOrginal.objSelect = objElement;
		this.objOrginal.arrOption = this.objOrginal.objSelect.getChildren('option');

		// get selected
		this.intSelected = this.getSelected();

		// hide orginal select
		this.hideOrginal();
		
		// create custom select
		this.objCustom = this.getCustom();
		
		// add toggle
		this.objCustom.objSelect.addEvent('click', this.toggle.create({'bind': this, 'event': true}));
		
		// add hover
		this.objCustom.arrOption.each(this.optionEvent.bind(this));
		

	}
});

NBX.Select.implement({
	toggle: function(objEvent) {
		objEvent.stop();
		
		// hide other nb layer
		NBX.objController.hideCurrentLayer(this);
		
		// toggle layer (hide/show)
		if (this.bolStatus) {
			this.hide();
		} else {
			this.show();
		}

		// add body hide event
		NBX.objController.registerCurrentLayer(this);
		
		
	},
	
	optionEvent: function(objOption) {
		objOption.addEvent('mouseover', this.mouseover.create({'bind': this, 'arguments': objOption}));
		objOption.addEvent('mouseout',  this.mouseout.create({'bind': this, 'arguments': objOption}));
		objOption.addEvent('click',     this.select.create({'bind': this, 'event': true, 'arguments': objOption}));
	},
	
	mouseover: function(objOption) {
		objOption.addClass('hover');
	},
	
	mouseout: function(objOption) {
		objOption.removeClass('hover');
	},
	
	key: function(objEvent) {
		// layer is not displayed
		if (!this.bolStatus) {
			return true;
		}
		
		// 13: return, 27: esc, 38: arrow up, 40: arrow down
		if (objEvent.code != 13 && 
			objEvent.code != 27 && 
			objEvent.code != 38 && 
			objEvent.code != 40) {
			return true;
		}
		
		objEvent.stop();

		// esc
		if (objEvent.code == 27) {
			this.hide();
			return true;
		}
		
		// get current active
		this.intFocus = -1;
	
		for (var i = 0; i < this.objCustom.arrOption.length; i++) {
			
			if (this.objCustom.arrOption[i].hasClass('selected')) {
				this.intFocus = i;
				this.objCustom.arrOption[i].removeClass('selected');
				break;
			}
			
			if (this.objCustom.arrOption[i].hasClass('hover')) {
				this.intFocus = i;
				this.objCustom.arrOption[i].removeClass('hover');
				break;
			}
		}
		
		// return
		if (objEvent.code == 13) {
			this.select(objEvent, this.objCustom.arrOption[this.intFocus]);
			return true;
		}
				
		// down
		if (objEvent.code == 40) {
			if (this.intFocus + 1 == this.objCustom.arrOption.length) {
				this.intFocus = -1;
			}
			this.intFocus++;
			this.objCustom.arrOption[this.intFocus].addClass('hover');
			return true;
		} 
		
		// up
		if (objEvent.code == 38) {
			if (this.intFocus == 0) {
				this.intFocus = this.objCustom.arrOption.length;
			}
			this.intFocus--;
			this.objCustom.arrOption[this.intFocus].addClass('hover');
			return true;
		}
	},
	
	select: function(objEvent, objOption) {
		objEvent.stop();
		
		var intSelected = 0;
		
		// get current index
		for (i = 0; i < this.objCustom.arrOption.length; i++) {
			if (objOption === this.objCustom.arrOption[i]) {
				intSelected = i;
			}
		}
		
		if (this.intSelected != intSelected) {
			// unset old entry
			this.objCustom.arrOption[this.intSelected].removeClass('selected');
			
			// change current
			this.intSelected = intSelected;
			
			// set new entry
			this.objOrginal.arrOption[this.intSelected].set('selected', 'selected');
			this.objCustom.arrOption[this.intSelected].addClass('selected');
			this.objCustom.objValue.set('html', this.objCustom.arrOption[this.intSelected].get('html'));
		}
		
		
		// fire orginal select event
		this.objOrginal.objSelect.fireEvent('change');
		
		this.hide();
	},
	show: function() {
		this.bolStatus = true;
		// show layer
		this.objListWrapper.setStyle('display', 'block');
		
		
		
		if(this.intMaxItemCount != -1 && this.objOrginal.arrOption.length > this.intMaxItemCount)
        {
            
            this.objListWrapper.setStyle("overflow-x", "hidden");
            this.objListWrapper.setStyle("overflow-y", "scroll");
			
            
            var intHeight = this.objCustom.objList.getFirst().getSize().y * this.intMaxItemCount;
			
            
            this.objListWrapper.setStyle("height", intHeight + "px");
        }
		
	},
	
	hide: function() {
		this.bolStatus = false;
		// hide layer
		this.objListWrapper.setStyle('display', 'none');
	},
	
	getSelected: function() {

		var intSelected = 0;
		
		for (i = 0; i < this.objOrginal.arrOption.length; i++) {
			if (this.objOrginal.arrOption[i].get('selected')) {
				intSelected = i;
				break;
			}
		}
		
		return intSelected;
	},
	
	getCustom: function() {
		var objCustom = {};
		
		// create element object
		var objSelect = new Element('div', {'class': this.objOrginal.objSelect.get('class')});
		
		objCustom.objSelect = objSelect;
		objCustom.arrOption = new Array();
		
		var objValue  = new Element('div', {'class': 'value', html: this.objOrginal.arrOption[this.intSelected].get('html')});
		
		objCustom.objValue = objValue;
		
		this.objListWrapper   = new Element('div', {'class': 'list_wrapper'});
		
		var objList   = new Element('ul', {'class': 'list'});
		
		objCustom.objList = objList;
		
		var objLastOption = null;
		for (i = 0; i < this.objOrginal.arrOption.length; i++) {
			if (i == this.intSelected) {
				strClass = 'option selected';
			} else {
				strClass = 'option';
			}
			
			objOption  = new Element('li', {'class': strClass, 'html': this.objOrginal.arrOption[i].get('html')});
			objCustom.arrOption[i] = objOption;
			objList.grab(objOption);
			
			objLastOption = objOption;
		}
		
		this.objListWrapper.grab(objList);
		objSelect.adopt(objValue, this.objListWrapper);
		
		// insert html in parent node
		this.objOrginal.objSelect.getParent().grab(objSelect);
		
		
		
		
		// return custom
		return objCustom;
	},
	hideOrginal: function() {
		this.objOrginal.objSelect.setStyle('display', 'none');
	}
	
});

