/**
 * SelectoMoo - form select fields replacement with style
 * @version		1.0.0
 * @MooTools version 1.2
 * @author Constantin Boiangiu <constantin.b [at] gmail.com>
 * @copyright Constantin Boiangiu
 * MIT-style license.
 */
var SelectoMoo = new Class({
	Implements: [Options, Events],

	options: {
		element: null,
		css: 'selectoMoo',
		//listHeight:190
		listHeight: 'auto'
	},

	initialize: function(options){

		this.setOptions(options);
		this.visible = 0;


		$$('html')[0].addClass('stylish-select');

		/* the select box */
		this.selBox = $(this.options.element);
		this.selBoxContainer = new Element('div', {
			'styles':{
				'opacity':.00001,
				'position':'absolute',
				'top':-5000
			}
		})
		this.opt = this.selBox.getElements('option');
		this.currentOption = 0;

		/* selected option container */
		this.selectedOption = new Element('div', {
			'class':this.options.css+'_selectedOption'
		});

		/* create a wrapper around the select */
		this.container = new Element('div',{
			'class':this.options.css+'_container',
			'events':{
				'click': function(event){
					event.stopPropagation();
					//ix remove blbne to :) this.selBox.focus();
					this.showList();
				}.bind(this),
				'mouseover': function(event){
					this.addClass('hover');
				},
				'mouseout': function(event){
					this.removeClass('hover');
				}
			},
			'styles':{
				'overflow':'hidden'
			}
		}).injectAfter(this.selBox).adopt( this.selBoxContainer.adopt(this.selBox) , this.selectedOption );

		/* options container */
		this.outerOptContainer = new Element('div',{
			'class':this.options.css+'_options',
			'styles':{
				'opacity':0,
				'height':this.options.listHeight,
				'top':0
			},
			'events':{
				click: function(event){
					event.stopPropagation();
				}.bind(this),
				'mousewheel': function(event){
					/* event.wheel holds direction. Up returns 1, down returns -1 */
					new Event(event).stop();
					var elem = this.currentOption-event.wheel;
					if( event.wheel > 0 && elem < 0 ) elem = 0;
					if( event.wheel < 0 && elem >= this.totalOptions-1 ) elem = this.totalOptions-1;
					this.scrollFx.toElement(this.fakeOptions[elem]);
					this.fakeOptions[this.currentOption].removeClass(this.options.css+'_naved');
					this.fakeOptions[elem].addClass(this.options.css+'_naved');
					this.currentOption = elem;
				}.bind(this)
			}
		}).injectInside(this.container);

		this.optContainer = new Element('div',{
			'class':this.options.css+'_options_inner'
		}).injectInside(this.outerOptContainer);

		this.outerOptContainer.set('morph',{'duration':300, 'transition':'back:out', 'wait':false});

		this.scrollFx = new Fx.Scroll(this.outerOptContainer, {
			wait: false,
			duration: 300,
			wheelStops: false,
			transition: Fx.Transitions.Sine.easeOut
		});

		/* IE hack to work for labels */
		if ($(document).getElement('label[for='+this.options.element+']')){
			$(document).getElement('label[for='+this.options.element+']').addEvent('click', function(event){
				event.stopPropagation();
				new Event(event).stop();
				if( this.visible )
					this.hideList();
				else {
					this.selBox.focus();
					this.showList();
				}
			}.bind(this))
		}


		this.addOptions();
		this.totalOptions = this.fakeOptions.length;

		/* close list when clicked outside the options list */
		$(document).addEvent('click', function(event){
			if( this.visible )
				this.hideList();
		}.bind(this));
		/* open the list when tab used for navigation */
		this.selBox.addEvents({
			'focus': function(event){
				if( this.visible ) return;
				this.showList();
			}.bind(this),
			'blur': function(event){
				/* delay list hiding in case an option from list was clicked */
				if( !this.visible ) return;
				this.hideList.delay(100, this);

			}.bind(this),
			'keydown':function(evt){
				if( evt.key == 'enter' ){
					this.fakeOptions[this.currentOption].fireEvent('click');
					return;
				}
				if( evt.key!=='up' && evt.key!=='down' ) return;

				var step = evt.key == 'up' ? -1 : 1;
				var elem = this.currentOption+step;
				if( evt.key == 'up' && elem < 0 ) elem = 0;
				if( evt.key == 'down' && elem >= this.totalOptions-1 ) elem = this.totalOptions-1;
				this.scrollFx.toElement(this.fakeOptions[elem]);
				this.fakeOptions[this.currentOption].removeClass(this.options.css+'_naved');
				this.fakeOptions[elem].addClass(this.options.css+'_naved');
				this.currentOption = elem;
			}.bind(this),
			'mousewheel': function(event){
				new Event(event).stop();
				var elem = this.currentOption-event.wheel;
				if( event.wheel > 0 && elem < 0 ) elem = 0;
				if( event.wheel < 0 && elem >= this.totalOptions-1 ) elem = this.totalOptions-1;
				this.scrollFx.toElement(this.fakeOptions[elem]);
				this.fakeOptions[this.currentOption].removeClass(this.options.css+'_naved');
				this.fakeOptions[elem].addClass(this.options.css+'_naved');
				this.currentOption = elem;
			}.bind(this)
		});
	},

	addOptions: function(){
		this.fakeOptions = new Array();
		this.opt.each(function(el, i){
			/* add selected option text */
			if( el.selected == true ){
				this.selectedOption.set({'text':el.get('text')});
			}

			if( el.get('value') !== '' ){
				/* set options in options container */
				var optionWrapper = new Element('span',{
					'text': el.get('text')
					});
				var option = new Element('div', {
					'class':this.options.css+'_option'+( el.selected == true ? ' '+this.options.css+'_selected':'' ),
					'events':{
						'click': function(event){
							if( event )
								event.stopPropagation();
							this.setOption(i, el.get('text'));
						}.bind(this),
						'mouseenter': function(){
							option.addClass(this.options.css+'_hovered');
						}.bind(this),
						'mouseleave': function(){
							option.removeClass(this.options.css+'_hovered');
						}.bind(this)
					}
				});
				optionWrapper.injectInside(option);
				option.injectInside(this.optContainer);
				this.fakeOptions.include(option);
				if( el.selected == true )
					this.currentOption = this.fakeOptions.indexOf(option);
				this.opt[i]['fakeOption'] = option;
			}

		}.bind(this))
	},

	showList: function(){
		/*
		if( !Browser.Engine.trident )
			this.selBox.focus();
		*/

		if(this.visible == 1) return;
		this.visible = 1;
		this.container.setStyle('overflow', 'visible');
		//this.outerOptContainer.morph({'height':[0,this.options.listHeight], 'opacity':[.5,1], 'top':-this.options.listHeight/2});

		if( Browser.Engine.trident ){
			// IE problemy s png na pozadi ....
			this.outerOptContainer.morph({
									'height':[this.options.listHeight - 10,this.options.listHeight]
									,'opacity':[1,1]
									,'top':-this.options.listHeight/2
									});
		}else {
			this.outerOptContainer.morph({
									'height':[this.options.listHeight - 10,this.options.listHeight]
									,'opacity':[.3,1]
									,'top':-this.options.listHeight/2
									});
		}




		this.scrollFx.toElement(this.fakeOptions[this.currentOption]);
	},

	hideList: function(){
		/*
			Note: when using back, bounce or elastic as transition and play with height,
			in IE you can't morph to 0 because size goes out of bounds and errors are issued
		*/
		if(this.visible == 0) return;
		this.visible = 0;
		this.outerOptContainer.morph({'height':30, 'opacity':0, 'top':0});
		this.container.setStyle('overflow', 'hidden');
		//if( !Browser.Engine.trident )
			this.selBox.blur();
	},

	setOption: function(key, optValue){
		this.opt.each(function(el, i){

			if( el.selected == true )
				el.selected = false;
			if( i == key )
				el.set({'selected':true});

		}.bind(this));



		$$('.'+this.options.css+'_selected').removeClass(this.options.css+'_selected');
		this.opt[key]['fakeOption'].addClass(this.options.css+'_selected');
		this.selectedOption.set({'text':optValue});
		this.hideList();
		// pepsi mix
		this.fireEvent('onGo');
	}
})
