var FormStyler = Class.create();
FormStyler.prototype = {
	// ******************************************************************************
	// Constants
	// ******************************************************************************
	Version : '0.2',


	// ******************************************************************************
	// vars
	// ******************************************************************************

	root : {}, // root element

	toggle : {},
	content : {},
	closeTimer : [],	
	active: {},
	

	//
	//  Initialize the langs
	//
	initialize: function(options) {
		//Object.extend(this.options, options || {});
		
	    this.options = Object.extend({
	    	
			root : false, // carousel element eg div
		    duration : 0.1,

		    // selectors
			selectors : {
		    	root : '#content',

		    	textBox : 'i',
		    	textField : 'label',
		    	selectBox : 'select:not([multiple="true"])',
				checkBox : 'label',
				radioBox : 'option',
				
				toggle : '#langToggle',
				content : '#langContent',
				
				dummy : '#dummy'
			},
			classNames : {
				toggleActive : 'selectBoxStyledToggleActive',
				optionActive : 'selectBoxStyledOptionActive',
				
				dummy : '#dummy'
			},

			dummy : '#dummy'
		}, options || {});
		
	
		//document.observe('dom:loaded', this.start.bind(this));
		//this.start();

	},


	start : function(){

		if(this.options.root) {
            this.root = this.options.root;
        } else {
            this.root = $$(this.options.selectors.root).first();
        }

		if(!this.root) return;
		
		
		
		this.selectBoxArr = this.root.select(this.options.selectors.selectBox);
		this.selectBoxArr.each(this.styleSelectBox.bind(this));

		return;
		
	},
	

	styleSelectBox : function(selectBox, index){
	
		//console.info('selectBox' , selectBox, index);
		//console.info('selectBox tab index' , selectBox.tabIndex);
		
		var selectBoxToggleTemplate = new Template('<a id="#{id}" href="#" class="selectBoxStyledToggle #{className}" ><span class="label">#{toggleLabel}</span><span class="button"></span></a>');
		var selectBoxTemplate = new Template('<div id="#{id}" style="#{style}" class="selectBoxStyled"><ul>#{optionsStr}</ul></div>');
		var optionTemplate = new Template('<li><a class="#{className}#{active}" href="#">#{text}</a></li>');

		var optionsStr = '';
		var options = selectBox.select('option');
		//console.info(options);
		
		var toggleLabel;		
		options.each(function(option, i){
			if(i == 0){
				toggleLabel = option.innerHTML;
			}
			if(option.selected == true){
				toggleLabel = option.innerHTML;
				option.active = ' ' + this.options.classNames.optionActive;
				this.active[index] = i;
				//console.info('this.options.classNames.optionActive=' + this.options.classNames.optionActive);
			} else {
				option.active = '';
			}
			optionsStr += optionTemplate.evaluate(option);
		}.bind(this));

		
		//console.info('optionsStr' , optionsStr);


		var selectBoxToggleObj = {
				toggleLabel : toggleLabel,
				id : 'styledSelectToggle_' + index,
				className : selectBox.className
		};
		var selectBoxToggleStr = selectBoxToggleTemplate.evaluate(selectBoxToggleObj);
		//console.info('selectBoxToggleStr' , selectBoxToggleStr);

		selectBox.insert({
			after : selectBoxToggleStr 
		});
		selectBox.hide();
		var selectBoxToggle = $('styledSelectToggle_' + index);
		
		// ***********************************************************************
		var selectBoxStyle = new Array(
				'height: 0px'
				//,'min-width:' + selectBoxToggle.getWidth() + 'px'
		);
		
		if(selectBox.id) {
			var selectBoxId = selectBox.id;
		} else {
			var selectBoxId = selectBox.id;
		}
		
		var selectBoxObj = {
				optionsStr : optionsStr,
				id : 'styledSelectBox_' + index,
				style : selectBoxStyle.join(';')
		};
		var selectBoxStr = selectBoxTemplate.evaluate(selectBoxObj);
		
		//console.info('selectBoxStr' , selectBoxStr);

		document.body.insert(selectBoxStr);
		var selectBoxStyled = $('styledSelectBox_' + index);
		
		var minWidth = selectBoxStyled.getWidth() 
			- parseInt(selectBoxToggle.getStyle('padding-left'))
			- parseInt(selectBoxToggle.getStyle('padding-right'))
			- parseInt(selectBoxToggle.getStyle('border-left-width'))
			- parseInt(selectBoxToggle.getStyle('border-right-width'))
			;
		
		
		//selectBoxToggle.setStyle('min-width:' + minWidth + 'px;');
		//console.info('selectBoxStyled', selectBoxStyled);
		

        // selectBox  change
        Event.observe(selectBox, 'change', this.selectBoxChangeHandler.bindAsEventListener(this, selectBox, selectBoxToggle, selectBoxStyled, index), false);
        Event.observe(selectBox, 'formstyler:change', this.selectBoxChangeHandler.bindAsEventListener(this, selectBox, selectBoxToggle, selectBoxStyled, index), false);
		
		//console.info('test' , this.toggle);
		Event.observe(selectBoxToggle, 'click', this.toggleClickHandler.bindAsEventListener(this, selectBoxToggle, selectBoxStyled), false);
		Event.observe(selectBoxToggle, 'keydown', this.keydownHandler.bindAsEventListener(this, selectBoxToggle, selectBoxStyled, selectBox, index), false);
		Event.observe(selectBoxToggle, 'keypress', this.keypressHandler.bindAsEventListener(this, selectBoxToggle, selectBoxStyled, selectBox, index), false);


        /*
        Event.observe(selectBoxToggle, 'keypress', function(ev){
            console.info('keypress');

            var charCode = (ev.charCode) ? ev.charCode : ev.keyCode;
            var x =String.fromCharCode(charCode);
            console.info(x);
            
            //ev.stop();
        }.bindAsEventListener());
        */

        /*
        Event.observe(selectBoxToggle, 'keydown', function(ev){
            console.info('keydown');

            switch (ev.keyCode) {
                case Event.KEY_TAB:
                    console.info('tab');
            }
            //ev.stop();
        }.bindAsEventListener());
        */


		Event.observe(selectBoxToggle, 'mouseover', this.mouseoverHandler.bind(this, selectBoxToggle, selectBoxStyled), false);
		Event.observe(selectBoxStyled, 'mouseover', this.mouseoverHandler.bind(this, selectBoxToggle, selectBoxStyled), false);
		
		Event.observe(selectBoxToggle, 'mouseout', this.mouseoutHandler.bind(this, selectBoxToggle, selectBoxStyled), false);
		Event.observe(selectBoxStyled, 'mouseout', this.mouseoutHandler.bind(this, selectBoxToggle, selectBoxStyled), false);

		selectBoxStyled.select('a').each(function(elm, i){
			Event.observe(elm, 'click', this.linkClickHandler.bindAsEventListener(this, elm, i, selectBox, selectBoxToggle, selectBoxStyled, index), false);
		}.bind(this));
		
	},

    selectBoxChangeHandler : function(ev, selectBox, selectBoxToggle, selectBoxStyled, index){

        //console.info('selectBox', selectBox);
        //console.info(selectBox.selectedIndex);

        var i = selectBox.selectedIndex;

        this.selectOption(i, selectBox, selectBoxToggle, selectBoxStyled, index);
    },


	linkClickHandler : function(ev, elm, i, selectBox, selectBoxToggle, selectBoxStyled, index) {
		ev.stop();
		//console.info(selectBox.options[index].value);
		this.close(selectBoxToggle, selectBoxStyled);
		
		this.selectOption(i, selectBox, selectBoxToggle, selectBoxStyled, index);

		this.blurInput(selectBox);
	},
	
	selectOption : function(i, selectBox, selectBoxToggle, selectBoxStyled, index) {

        if(!selectBoxStyled.select('a')[i]){
            return;
        }
        selectBoxStyled.select('a')[this.active[index]].removeClassName(this.options.classNames.optionActive);
        selectBoxStyled.select('a')[i].addClassName(this.options.classNames.optionActive);
		
		this.active[index] = i;

		selectBox.value = selectBox.options[i].value;
		selectBoxToggle.select('.label').first().update(selectBox.options[i].text);
	},
	
	
	blurInput : function(inputField){
		if( document.createEvent ) {
			var evObj = document.createEvent('MouseEvents');

			evObj.initEvent( 'change', true, false );
			inputField.dispatchEvent(evObj);

			//evObj.initEvent( 'blur', true, false );
			//inputField.dispatchEvent(evObj);
		} else if( document.createEventObject ) {
			inputField.fireEvent('onchange');
			//inputField.fireEvent('onblur');
		}
	},
	
	keydownHandler : function(ev, selectBoxToggle, selectBoxStyled, selectBox, index) {
		//console.info('keydown', ev.keyCode);

        switch (ev.keyCode) {
            case Event.KEY_RETURN:
				this.toggleClickHandler(ev, selectBoxToggle, selectBoxStyled);
                Event.stop(ev);
                break;
            case 0: // space
				this.toggleClickHandler(ev, selectBoxToggle, selectBoxStyled);
                Event.stop(ev);
                break;
            case Event.KEY_TAB:
            	if(selectBoxToggle.hasClassName(this.options.classNames.toggleActive)){
            		this.close(selectBoxToggle, selectBoxStyled);
            	}
				
				this.blurInput(selectBox);
                break;
            case Event.KEY_UP:
            case Event.KEY_RIGHT:
            
            	if(this.active[index] > 0) {
            		var i = this.active[index] - 1;
            		this.selectOption(i, selectBox, selectBoxToggle, selectBoxStyled, index);
            	}
            
                Event.stop(ev);
                break;
            case Event.KEY_DOWN:
            case Event.KEY_LEFT:
            
            	if(this.active[index] < selectBox.options.length-1) {
            		var i = this.active[index] + 1;
            		this.selectOption(i, selectBox, selectBoxToggle, selectBoxStyled, index);
            	}
            
                Event.stop(ev);
                break;

            default:
                if(!is.ie) Event.stop(ev);
        }

	},
	
    keypressHandler : function(ev, selectBoxToggle, selectBoxStyled, selectBox, index) {
        //console.info('keypress', ev);

        var charCode = (ev.charCode) ? ev.charCode : ev.keyCode;

        if(charCode){
            var keyChar = String.fromCharCode(ev.charCode);
            //console.info('zeichen', keyChar, ev.charCode, ev);

            var options = selectBox.select('option');
            var hits = options.findAll(function(option){
                return option.innerHTML.charAt(0).toLowerCase() == keyChar.toLowerCase();
            });
            //console.info('hits', hits);
            if(hits.size()){
                var activeIndex = this.active[index];
                var activeHit = hits.find(function(option){
                    return option.index == activeIndex;
                });

                if(activeHit){
                    if(this.active[index] == activeHit.index) {
                        var nextIndex = activeHit.index + 1;
                        var nextHit = hits.find(function(option){
                            return option.index == nextIndex;
                        });
                        if(nextHit) {
                            this.selectOption(nextIndex, selectBox, selectBoxToggle, selectBoxStyled, index);
                        } else {
                            this.selectOption(hits.first().index, selectBox, selectBoxToggle, selectBoxStyled, index);
                        }
                    }
                } else {
                    this.selectOption(hits.first().index, selectBox, selectBoxToggle, selectBoxStyled, index);
                }

            }
        }
    },
	
	//
	//  Activate an lang 
	//
	toggleClickHandler : function(ev, selectBoxToggle, selectBoxStyled) {
		ev.stop();
		//console.info(selectBoxToggle, selectBoxStyled);
		if(selectBoxToggle.hasClassName(this.options.classNames.toggleActive)){
			// close
			this.close(selectBoxToggle, selectBoxStyled);

		} else {
			this.open(selectBoxToggle, selectBoxStyled);
		}
	},

	mouseoverHandler : function(selectBoxToggle, selectBoxStyled) {
		//console.info('mouseover');
		if(typeof(this.closeTimer[selectBoxStyled.id]) != 'undefined') window.clearTimeout(this.closeTimer[selectBoxStyled.id]);
	},

	mouseoutHandler : function(selectBoxToggle, selectBoxStyled) {
		//console.info('mouseout');
		this.closeTimer[selectBoxStyled.id] = window.setTimeout(this.timerAfterFinish.bind(this, selectBoxToggle, selectBoxStyled), 1000);
	},
	
	timerAfterFinish : function(selectBoxToggle, selectBoxStyled) {

		//console.info('closetimer');
		
		if(selectBoxToggle.hasClassName(this.options.classNames.toggleActive)){
			this.close(selectBoxToggle, selectBoxStyled);
		}
	},

	
	open : function(selectBoxToggle, selectBoxStyled) {
		
		selectBoxStyled.setStyle({
				left : selectBoxToggle.cumulativeOffset().left +'px',
				top : selectBoxToggle.cumulativeOffset().top +'px',
                minWidth : selectBoxToggle.getWidth() + 'px'
		});  
		
		
		selectBoxToggle.addClassName(this.options.classNames.toggleActive);
		startHeight = 0;
		endHeight = selectBoxStyled.scrollHeight;

		this.getEffect(selectBoxStyled, startHeight, endHeight);		
	},
	
	close : function(selectBoxToggle, selectBoxStyled) {
		selectBoxToggle.removeClassName(this.options.classNames.toggleActive);
		startHeight = selectBoxStyled.scrollHeight;
		endHeight = 0;
		
		this.getEffect(selectBoxStyled, startHeight, endHeight);
	},
	
	
	// 
	// open an active lang
	//
	getEffect : function(content) {

		effect = new Effect.Tween(content, startHeight, endHeight, {
			duration: this.options.duration,
			transition: Effect.Transitions.sinoidal,
			queue: {
				position: 'end', 
				scope: 'langAnimation'
			},
			beforeStart: function() {
				this.animating = true;
			}.bind(this),
			afterFinish: function() {
				this.animating = false;
			}.bind(this)
		}, function(p){
				content.setStyle({height : p + 'px'});
			}.bind(this)
		);
		return effect;
	}

}


