SelectBox = function(element, scrollable, additionalClassName) {
	element = $(element);

	if (!element) {
		return null;
	}

	var params = {type: 'hidden', name: element.name || ('select_' + SelectBox.id++), value: $F(element)},
		selected = [], options = [], node, span, container, scroll, track, list, input;

	if (element.id) {
		params.id = element.id;
	}

	if (element.onchange) {
		var code = element.onchange;
		params.onchange = code.toString().replace(/^\s*function.*?\r?\n?{\s*/m, '').replace(/\s*}\s*$/, '');
	}

	$A(element.options).each(function(option, iteration) {
		var item, params = {my_value: option.value}, classNames = [];

		if (iteration == 0) {
			classNames.push('first');
		}
		if (option.selected || option.value == element.value) {
			classNames.push('active');
			selected = [option.value, option.innerHTML];
		}
		if (iteration == element.options.length - 1) {
			classNames.push('last');
		}

		params.className = classNames.join(' ');

		options.push(item = Builder.node('li', params, option.innerHTML));
		SelectBox.disableTextSelection(item);
		if (scrollable) {
			item.onclick = function() {
				var span = this.parentNode.parentNode.parentNode.getElementsByTagName('span')[0],
					input = this.parentNode.parentNode.parentNode.getElementsByTagName('input')[0];

				span.innerHTML = this.innerHTML;
				input.value = $(this).readAttribute('my_value');

				$(this.parentNode.parentNode).hide();
				$(document.body).stopObserving('click');

				if (input.onchange) {
					input.onchange();
				}
			};
		} else {
			item.onclick = function() {
				var span = this.parentNode.parentNode.getElementsByTagName('span')[0],
					input = this.parentNode.parentNode.getElementsByTagName('input')[0];

				span.innerHTML = this.innerHTML;
				input.value = $(this).readAttribute('my_value');

				$(this.parentNode).hide();
				$(document.body).stopObserving('click');

				if (input.onchange) {
					input.onchange();
				}
			};
		}

		if (SelectBox.IE6) {
			item.onmouseover = function() {
				this.className = this.className.split(/\s+/).concat(['hover']).join(' ');	//'
			}
			item.onmouseout = function() {
				this.className = this.className.split(/\s*hover\s*/).join(' ');	//'
			}
		}
	});

	list = Builder.node('ul', {}, options);

	if (scrollable) {
		container = Element.Methods.wrap(list, 'div', {className: 'container'});
		container.appendChild(scroll = Builder.node('div', {className: 'scroll'}, [
			track = Builder.node('span')
		]));
		container.setStyle({display: 'none'});
		SelectBox.disableTextSelection(container);
		SelectBox.disableTextSelection(track);
	} else {
		list.setStyle({display: 'none'});
	}

	var classNames = element.className ? element.className.split(' ') : [];

	if (element.className) {
		classNames.concat(element.className.split(' '));
	}
	if (additionalClassName) {
		classNames.push(additionalClassName);
	}

	node = Builder.node('div', {className: 'selectbox' + (classNames.length ? ' ' + classNames.join(' ') : '')}, [
		span = Builder.node('span', {}, selected[1]),
		input = Builder.node('input', params),
		scrollable ? container : list
	]);

	SelectBox.disableTextSelection(span);

	span._input = input;
	span._list = list;
	if (scrollable) {
		span._scrollable = true;
		span._container = container;
		span._scroll = scroll;
		span._track = track;

		span.scrollTo = (function(offset) {
			var area = this._container.getDimensions().height - this._track.getDimensions().height;

			if (offset < 0) {
				offset = 0;
			} else if (offset > area) {
				offset = area;
			}

			this._track.style.top = offset + 'px';
			this._list.style.top = parseInt((-offset / area) * (this._list.getDimensions().height - this._container.getDimensions().height)) + 'px';
		}).bind(span);

		span.scrollBy = (function(offset) {
			this.scrollTo((parseInt(this._track.style.top) || 0) + offset);
		}).bind(span);

		track.observe('mousedown', (function(evt) {
			SelectBox.onTrack = true;
			this._offset = evt.pageY - (parseInt(this._track.style.top) || 0);
			$(document.body).observe('mousemove', this._observer = (function(evt) {
				this.scrollTo(evt.pageY - this._offset);
				evt.stop();
			}).bind(this)).observe('mouseup', (function(evt) {
				$(document.body).stopObserving('mousemove', this._observer);
				SelectBox.onTrack = false;
				evt.stop();
			}).bind(this));
		}).bind(span));

		var _callback = (function(evt) {
			var delta;

			evt = evt || window.event;

			if (evt.wheelDelta) {
				delta = (-evt.wheelDelta / 120) * 15;
			} else if (evt.detail) {
				delta = (evt.detail / 3) * 15;
			} else {
				return;
			}

			this.scrollBy(delta);
			if (evt.preventDefault) {
				evt.preventDefault();
				evt.stopPropagation();
			} else {
				evt.cancelBubble = true;
				evt.returnValue = false;
				return false;
			}
		}).bind(span)

		if (span._container.addEventListener) {
			span._container.addEventListener('DOMMouseScroll', _callback, true);
		}

		span.onmousewheel = _callback;
	}

	span.observe('click', (function(evt) {
		if (this._scrollable) {
			if (evt.target._container.visible()) {
				this._container.hide();
				$(document.body).stopObserving('click');
			} else {
				this._container.show();
				$(document.body).observe('click', (function(evt) {
					if (!SelectBox.onTrack) {
						this._container.hide();
						$(document.body).stopObserving('click');
					}
					SelectBox.onTrack = false;
				}).bind(this));
			}
		} else {
			if (evt.target._list.visible()) {
				this._list.hide();
				$(document.body).stopObserving('click');
			} else {
				this._list.show();
				$(document.body).observe('click', (function(evt) {
					if (!SelectBox.onTrack) {
						this._list.hide();
						$(document.body).stopObserving('click');
					}
					SelectBox.onTrack = false;
				}).bind(this));
			}
		}
		evt.stop();
	}).bind(span));

	element.parentNode.replaceChild(node, element);
}

SelectBox.disableTextSelection = function(element) {
	if (typeof element.style.MozUserSelect != 'undefined') {
		element.style.MozUserSelect = 'none';
	} else if (typeof element.onselectstart != 'undefined') {
		element.onselectstart = function() {
			return false;
		}
	} else {
		element.onmousedown = function() {
			return false;
		}
	}
}

SelectBox.IE6 = navigator.userAgent.indexOf('MSIE 6') + 1;

SelectBox.id = 0;
