// custom select module
jcf.addModule({
	name:'select',
	selector:'select',
	initOptions: function(){
		jcf.lib.extend(this.options,{
			wrapperClass:'select-area',
			focusClass:'select-focus',
			selectedClass:'item-selected',
			disabledClass:'select-disabled',
			valueSelector:'span.center',
			optGroupClass:'optgroup',
			openerSelector:'a.select-opener',
			selectStructure:'<span class="center"></span><a class="select-opener"></a>',
			selectPrefixClass:'select-',
			dropMaxHeight: 200,
			dropHiddenClass:'options-hidden',
			dropScrollableClass:'options-overflow',
			dropClass:'select-options',
			dropClassPrefix:'drop-',
			dropStructure:'<div class="drop-holder"><div class="drop-list"></div></div>',
			dropSelector:'div.drop-list'
		});
	},
	setupWrapper: function(){
		jcf.lib.addClass(this.fakeElement, this.options.wrapperClass);
		this.realElement.parentNode.insertBefore(this.fakeElement, this.realElement);
		if(!jcf.lib.browser.opera) this.realElement.setAttribute('multiple','multiple');
		this.fakeElement.innerHTML = this.options.selectStructure;
		this.fakeElement.style.width = this.realElement.offsetWidth + 'px';
		jcf.lib.addClass(this.fakeElement, jcf.lib.getAllClasses(this.realElement.className, this.options.selectPrefixClass, jcf.baseOptions.hiddenClass));

		// create select body
		this.opener = jcf.lib.queryBySelector(this.options.openerSelector, this.fakeElement)[0];
		this.valueText = jcf.lib.queryBySelector(this.options.valueSelector, this.fakeElement)[0];
		this.opener.jcf = this;

		this.createDropdown();
		this.refreshState();
		this.addEvents();
		this.onControlReady(this);
	},
	addEvents: function(){
		jcf.lib.event.add(this.fakeElement, 'click', this.toggleDropdown);
		jcf.lib.event.add(this.realElement, 'change', this.onChange);
	},
	onFocus: function(){
		jcf.modules[this.jcf.name].superclass.onFocus.apply(this, arguments);
		jcf.lib.event.add(this.jcf.realElement, 'keydown', this.jcf.onKeyDown);
		if(jcf.activeControl && jcf.activeControl != this.jcf) {
			jcf.activeControl.hideDropdown();
		}
	},
	onBlur: function(){
		if(!this.jcf.isActiveDrop() || !this.jcf.isOverDrop()) {
			jcf.modules[this.jcf.name].superclass.onBlur.apply(this, arguments);
		}
		jcf.lib.event.remove(this.jcf.realElement, 'keydown', this.jcf.onKeyDown);
	},
	onChange: function() {
		this.jcf.refreshState();
	},
	onKeyDown: function(e){
		var context = this;
		setTimeout(function(){
			context.jcf.refreshState();
		},10);
		if(e.keyCode == 13) {
			context.jcf.toggleDropdown.apply(context);
			return false;
		}
	},
	onResizeWindow: function(e){
		if(jcf.activeControl) {
			jcf.activeControl.hideDropdown();
		}
	},
	onScrollWindow: function(e){
		if(jcf.activeControl) {
			jcf.activeControl.positionDropdown();
		}
	},
	onOptionClick: function(e){
		var opener = e.target && e.target.tagName && e.target.tagName.toLowerCase() == 'li' ? e.target : jcf.lib.getParent(e.target, 'li');
		if(opener) {
			this.jcf.realElement.selectedIndex = parseInt(opener.getAttribute('rel'));
			this.jcf.realElement.focus();
			this.jcf.refreshState();
			this.jcf.hideDropdown();
			jcf.lib.fireEvent(this.jcf.realElement, 'change');
		}
		return false;
	},
	onClickOutside: function(e){
		if(jcf.activeControl && !jcf.lib.isParent(jcf.activeControl, e.target) && !jcf.lib.isParent(jcf.activeControl.fakeElement, e.target)) {
			jcf.activeControl.hideDropdown();
		}
	},
	onDropHover: function(e){
		if(jcf.activeControl) {
			jcf.activeControl.hoverFlag = true;
			var opener = e.target && e.target.tagName && e.target.tagName.toLowerCase() == 'li' ? e.target : jcf.lib.getParent(e.target, 'li');
			if(opener) {
				jcf.activeControl.realElement.selectedIndex = parseInt(opener.getAttribute('rel'));
				jcf.activeControl.refreshSelectedClass(parseInt(opener.getAttribute('rel')));
			}
		}
	},
	onDropLeave: function(){
		if(jcf.activeControl) {
			jcf.activeControl.hoverFlag = false;
		}
	},
	isActiveDrop: function(){
		return !jcf.lib.hasClass(this.selectDrop, this.options.dropHiddenClass);
	},
	isOverDrop: function(){
		return this.hoverFlag;
	},
	createDropdown: function(){
		// remove old dropdown if exists
		if(this.selectDrop) {
			this.selectDrop.parentNode.removeChild(this.selectDrop);
		}

		// create dropdown holder
		this.selectDrop = document.createElement('div');
		this.selectDrop.className = this.options.dropClass;
		this.selectDrop.innerHTML = this.options.dropStructure;
		this.selectList = jcf.lib.queryBySelector(this.options.dropSelector,this.selectDrop)[0];
		jcf.lib.addClass(this.selectDrop, this.options.dropHiddenClass);
		document.body.appendChild(this.selectDrop);
		this.selectDrop.jcf = this;
		jcf.lib.event.add(this.selectDrop, 'click', this.onOptionClick);
		jcf.lib.event.add(this.selectDrop, 'mouseover', this.onDropHover);
		jcf.lib.event.add(this.selectDrop, 'mouseout', this.onDropLeave);
		this.buildDropdown();
	},
	buildDropdown: function() {
		// build select options / optgroups
		this.buildDropdownOptions();

		// position and resize dropdown
		this.positionDropdown();

		// cut dropdown if height exceedes
		this.buildDropdownScroll();
	},
	buildDropdownOptions: function() {
		this.resStructure = '';
		this.optNum = 0;
		for(var i = 0; i < this.realElement.children.length; i++) {
			this.resStructure += this.buildElement(this.realElement.children[i]) +'\n';
		}
		this.selectList.innerHTML = this.resStructure;
	},
	buildDropdownScroll: function() {
		if(this.options.dropMaxHeight) {
			if(this.selectDrop.offsetHeight > this.options.dropMaxHeight) {
				this.selectList.style.height = this.options.dropMaxHeight+'px';
				this.selectList.style.overflow = 'auto';
				this.selectList.style.overflowX = 'hidden';
				jcf.lib.addClass(this.selectDrop, this.options.dropScrollableClass);
			}
		}
		jcf.lib.addClass(this.selectDrop, jcf.lib.getAllClasses(this.realElement.className, this.options.dropClassPrefix, jcf.baseOptions.hiddenClass));
	},
	buildElement: function(obj){
		// build option
		var res = '';
		if(obj.tagName.toLowerCase() == 'option') {
			if(!jcf.lib.prevSibling(obj) || jcf.lib.prevSibling(obj).tagName.toLowerCase() != 'option') {
				res += '<ul>';
			}
			res += '<li rel="'+(this.optNum++)+'" class="'+(obj.className? obj.className : '')+' jcfcalc"><a href="#">'+(obj.title? '<img src="'+obj.title+'" alt="" />' : '')+'<span>' + obj.innerHTML + '</span></a></li>';
			if(!jcf.lib.nextSibling(obj) || jcf.lib.nextSibling(obj).tagName.toLowerCase() != 'option') {
				res += '</ul>';
			}
			return res;
		}
		// build option group with options
		else if(obj.tagName.toLowerCase() == 'optgroup' && obj.label) {
			res += '<div class="'+this.options.optGroupClass+'">';
			res += '<strong class="jcfcalc"><em>'+(obj.label)+'</em></strong>';
			for(var i = 0; i < obj.children.length; i++) {
				res += this.buildElement(obj.children[i]);
			}
			res += '</div>';
			return res;
		}
	},
	positionDropdown: function(){
		var ofs = jcf.lib.getOffset(this.fakeElement);
		this.selectDrop.style.top = (ofs.top+this.fakeElement.offsetHeight)+'px';
		this.selectDrop.style.left = ofs.left+'px';
		this.selectDrop.style.width = this.fakeElement.offsetWidth+'px';
	},
	showDropdown: function(){
		jcf.lib.removeClass(this.selectDrop, this.options.dropHiddenClass);
		this.positionDropdown();

		// hide active dropdown
		if(jcf.activeControl) {
			jcf.activeControl.hideDropdown();
		}

		// show current dropdown
		jcf.activeControl = this;
		jcf.lib.event.add(window, 'resize', this.onResizeWindow);
		jcf.lib.event.add(window, 'scroll', this.onScrollWindow);
		jcf.lib.event.add(document.body, 'click', this.onClickOutside);
		this.positionDropdown();
	},
	hideDropdown: function(){
		if(jcf.activeControl && typeof jcf.activeControl.origSelectedIndex === 'number') {
			jcf.activeControl.realElement.selectedIndex = jcf.activeControl.origSelectedIndex;
		}
		jcf.lib.addClass(this.selectDrop, this.options.dropHiddenClass);
		jcf.activeControl = null;
		jcf.lib.event.remove(window, 'resize', this.onResizeWindow);
		jcf.lib.event.remove(window, 'scroll', this.onScrollWindow);
		jcf.lib.event.remove(document.body, 'click', this.onClickOutside);
	},
	toggleDropdown: function(){
		this.jcf.dropOpened = true;
		if(!this.jcf.realElement.disabled) {
			if(this.jcf.isActiveDrop()) {
				this.jcf.hideDropdown();
			} else {
				this.jcf.showDropdown();
			}
		}
		this.jcf.refreshState();
	},
	scrollToItem: function(){
		if(this.isActiveDrop()) {
			var dropHeight = this.selectList.offsetHeight;
			var offsetTop = this.calcOptionOffset(this.getFakeActiveOption());
			var sTop = this.selectList.scrollTop;
			var oHeight = this.getFakeActiveOption().offsetHeight;
			//offsetTop+=sTop;

			if(offsetTop >= sTop + dropHeight) {
				this.selectList.scrollTop = offsetTop - dropHeight + oHeight;
			} else if(offsetTop < sTop) {
				this.selectList.scrollTop = offsetTop;
			}
		}
	},
	getFakeActiveOption: function(c) {
		return jcf.lib.queryBySelector('li[rel="'+(typeof c === 'number' ? c : this.realElement.selectedIndex) +'"]',this.selectList)[0];
	},
	calcOptionOffset: function(fake) {
		var h = 0;
		var els = jcf.lib.queryBySelector('.jcfcalc',this.selectList);
		for(var i = 0; i < els.length; i++) {
			if(els[i] == fake) break;
			h+=els[i].offsetHeight;
		}
		return h;
	},
	childrenHasItem: function(hold,item) {
		var items = hold.getElementsByTagName('*');
		for(i = 0; i < items.length; i++) {
			if(items[i] == item) return true;
		}
		return false;
	},
	removeSelectedClass: function(){
		var children = jcf.lib.queryBySelector('li',this.selectList);
		for(var i = children.length - 1; i >= 0; i--) {
			jcf.lib.removeClass(children[i], this.options.selectedClass);
		}
	},
	setSelectedClass: function(c){
		jcf.lib.addClass(this.getFakeActiveOption(c), this.options.selectedClass);
	},
	refreshSelectedClass: function(c){
		this.removeSelectedClass(c);
		this.setSelectedClass(c);
		if(this.realElement.disabled) {
			jcf.lib.addClass(this.fakeElement, this.options.disabledClass);
		} else {
			jcf.lib.removeClass(this.fakeElement, this.options.disabledClass);
		}
	},
	refreshSelectedText: function() {
		if(!this.dropOpened && this.realElement.title) {
			this.valueText.innerHTML = this.realElement.title;
		} else {
			if(this.realElement.options[this.realElement.selectedIndex].title) {
				this.valueText.innerHTML = '<img src="'+this.realElement.options[this.realElement.selectedIndex].title+'" alt="" />' + this.realElement.options[this.realElement.selectedIndex].innerHTML;
			} else {
				this.valueText.innerHTML = this.realElement.options[this.realElement.selectedIndex].innerHTML;
			}
		}
	},
	refreshState: function(){
		if(jcf.activeControl) {
			jcf.activeControl.origSelectedIndex = jcf.activeControl.realElement.selectedIndex;
		}
		this.refreshSelectedClass();
		this.refreshSelectedText();
		this.scrollToItem();
	}
});
