/**
 * SelectsManager.js (SelectsManager, Select, SelectBaseItemRenderer classes)
 *
 * @version: 1.0
 * @author: WGU Team (www.web-go-up.com)
 *
 * @TODO: Redesign without Mootools
 * @TODO: more robust testing!!!
 */

/**
 * SelectsManager
 *
 * When instance of this class created it will automatically attaching selects to each select with class == selector option.
 *
 * Options:
 *  id					String		<default = select> prefix for ids of Select's elements (container, handler, list and
 *									items), for example: first list will have id - 'select-0-list'
 *  selector			String		<default = select> css selector for attaching default selects
 *	cssClass			String		<default = select> prefix for classes of Select's elements (container, handler, list,
 *									and items), for example: list will have class - 'select_list'
 *	itemRenderer		Class		<default = SelectBaseItemRenderer> class which represent each item of lists.
 *									See description of this class below
 *	showDuration		int			<default = 200> duration of the list transition when showing, in milliseconds
 *	showTransition		Function	<default = Fx.Transitions.linear> transition, to be used when showing list
 *	hideDuration		int			<default = 100> duration of the list transition when hiding, in milliseconds
 *	hideTransition		Function	<default = Fx.Transitions.linear> transition, to be used when hiding list
 *
 * Public methods:
 *	attach					attach Select to select
 *		return				SelectsManager		current instance of SelectsManager class
 *		params:
 *			options			Object				object with options for new Select. Required option is 'select' - it is
 *												id or Element of select tag to which new Select will be attached. Other
 *												options look above
 *
 *	detach					detach Select from select if such Select exist
 *		return				SelectsManager		current instance of SelectsManager class
 *		params:
 *			input			String or Element	id or Element of input for detaching Select
 *
 *	getSelectBySelect		return Select associated with select
 *		return				Select				instance of Select class associated with select
 *		params:
 *			select			String or Element	id or Element of select
 *
 *	attachDefaultSelects	automatically attach all selects with class == selector
 *		return				SelectsManager		current instance of SelectsManager class
 *
 *	getId					return current id property
 *		return				String				current id property
 *
 *	setId					set new id property for all Selects of this manager
 *		return				SelectsManager		current instance of SelectsManager class
 *		params:
 *			value			String				new id property (see id option above)
 *
 *	getSelector				return current selector property
 *		return				String				current selector property
 *
 *	setSelector				set new selector property
 *		return				SelectsManager		current instance of SelectsManager class
 *		params:
 *			value			String				new selector property (see selector option above)
 *
 *	getCSSClass				return current cssClass property
 *		return				String				current cssClass property
 *
 *	setCSSClass				set new cssClass property for all Selects of this manager
 *		return				SelectsManager		current instance of SelectsManager class
 *		params:
 *			value			String				new cssClass property (see cssClass option above)
 *
 *	getItemRenderer			return current itemRenderer property
 *		return				Class				current itemRenderer property
 *
 *	setItemRenderer			set new itemRenderer property for all Selects of this manager
 *		return				SelectsManager		current instance of SelectsManager class
 *		params:
 *			value			Class				new itemRenderer property (see itemRenderer option above)
 *
 *	getShowDuration			return current showDuration property
 *		return				int					current showDuration property
 *
 *	setShowDuration			set new showDuration property for all Selects of this manager
 *		return				SelectsManager		current instance of SelectsManager class
 *		params:
 *			value			int					new showDuration property (see showDuration option above)
 *
 *	getShowTransition		return current showTransition property
 *		return				Function			current showTransition property
 *
 *	setShowTransition		set new showTransition property for all Selects of this manager
 *		return				SelectsManager		current instance of SelectsManager class
 *		params:
 *			value			Function			new showTransition property (see showTransition option above)
 *
 *	getHideDuration			return current hideDuration property
 *		return				int					current hideDuration property
 *
 *	setHideDuration			set new hideDuration property for all Selects of this manager
 *		return				SelectsManager		current instance of SelectsManager class
 *		params:
 *			value			int					new hideDuration property (see hideDuration option above)
 *
 *	getHideTransition		return current hideTransition property
 *		return				Function			current hideTransition property
 *
 *	setHideTransition		set new hideTransition property for all Selects of this manager
 *		return				SelectsManager		current instance of SelectsManager class
 *		params:
 *			value			Function			new hideTransition property (see hideTransition option above)
 */

/**
 * Select
 *
 * Single Select see description of SelectsManager class above. Currently, element of Select is ul tag
 *
 * Options:
 *	select			String or Element	input (or it's id) with which this Select will be associated
 *  id				String				<default = select> prefix for ids of Select's elements (container, handler, list and
 *										items), for example: list will have id - 'select-0-list'
 *	cssClass		String				<default = select> prefix for classes of Select's elements (container, handler, list
 *										and items), for example: list will have class - 'select_list'
 *	itemRenderer	Class				<default = SelectBaseItemRenderer> class which represent each item of lists.
 *										See description of this class below
 *	showDuration	int					<default = 200> duration of the list transition when showing, in milliseconds
 *	showTransition	Function			<default = Fx.Transitions.linear> transition, to be used when showing list
 *	hideDuration	int					<default = 100> duration of the list transition when hiding, in milliseconds
 *	hideTransition	Function			<default = Fx.Transitions.linear> transition, to be used when hiding list
 *
 * Public methods:
 *	destroy					remove all events from items and list and destroy all parts of this Select
 *		return				Select		current instance of Select class
 *
 *	show					send request and show list with result
 *		return				Select		current instance of Select class
 *
 *	hide					hide list and destroy all it's items
 *		return				Select		current instance of Select class
 *
 *	getId					return current id property
 *		return				String		current id property
 *
 *	setId					set new id property
 *		return				Select		current instance of Select class
 *		params:
 *			value			String		new id property (see id option above)
 *
 *	getCSSClass				return current cssClass property
 *		return				String		current cssClass property
 *
 *	setCSSClass				set new cssClass property
 *		return				Select		current instance of Select class
 *		params:
 *			value			String		new cssClass property (see cssClass option above)
 *
 *	getItemRenderer			return current itemRenderer property
 *		return				Class		current itemRenderer property
 *
 *	setItemRenderer			set new itemRenderer property
 *		return				Select		current instance of Select class
 *		params:
 *			value			Class		new itemRenderer property (see itemRenderer option above)
 *
 *	getShowDuration			return current showDuration property
 *		return				int			current showDuration property
 *
 *	setShowDuration			set new showDuration property
 *		return				Select		current instance of Select class
 *		params:
 *			value			int			new showDuration property (see showDuration option above)
 *
 *	getShowTransition		return current showTransition property
 *		return				Function	current showTransition property
 *
 *	setShowTransition		set new showTransition property
 *		return				Select		current instance of Select class
 *		params:
 *			value			Function	new showTransition property (see showTransition option above)
 *
 *	getHideDuration			return current hideDuration property
 *		return				int			current hideDuration property
 *
 *	setHideDuration			set new hideDuration property
 *		return				Select		current instance of Select class
 *		params:
 *			value			int			new hideDuration property (see hideDuration option above)
 *
 *	getHideTransition		return current hideTransition property
 *		return				Function	current hideTransition property
 *
 *	setHideTransition		set new hideTransition property
 *		return				Select		current instance of Select class
 *		params:
 *			value			Function	new hideTransition property (see hideTransition option above)
 */

/**
 * SelectBaseItemRenderer
 *
 * Class which represent 'interface' for itemRenderers for Select. Required methods is: getElement, getLabel, getValue, destroy,
 * select, deselect and isSelected (see description of all this methods below). This class must fire next events:
 * itemFocus, itemBlur and itemSelectInternal and must pass with this events current instance of this class (this property, see
 * description of all this events below). Also this class will get next required options: __id__ and __cssClass__
 * (see description of all this options below). Currently, element must be li tag
 *
 * Options:
 *  __id__				String		<default = ''> id of element
 *	__cssClass__		String		<default = autocompleter_item> class of element
 *	label				String		<default = ''> label of this item. Will be displayed in item and in handler if this item
 *									will be selected
 *	value				String		<default = ''> value of this item
 *	overDuration		int			<default = 500> duration of the mouse over effect, in milliseconds
 *	overTransition		Function	<default = Fx.Transitions.linear> transition, to be used whith mouse over effect
 *	outDuration			int			<default = 300> duration of the mouse out effect, in milliseconds
 *	outTransition		Function	<default = Fx.Transitions.linear> transition, to be used whith mouse out effect
 *
 * Public methods:
 *	getElement			return element (li tag)
 *		return			Element		current li tag
 *
 *	getLabel			return label of current element
 *		return			String		label of current element. Will be displayed in select
 *
 *	getValue			return value of current element
 *		return			String		value of current element
 *
 *	destroy				destroy current element and removes all Events from it
 *		return			SelectBaseItemRenderer	current instance of SelectBaseItemRenderer class
 *
 *	select				select (highlight) element. !!!Must fire event 'itemFocus' and pass this property, like this:
 *						this.fireEvent('itemFocus', this);!!!
 *		return			SelectBaseItemRenderer	current instance of SelectBaseItemRenderer class
 *
 *	deselect			deselect element. !!!Must fire event 'itemBlur' and pass this property, like this:
 *						this.fireEvent('itemBlur', this);!!!
 *		return			SelectBaseItemRenderer	current instance of SelectBaseItemRenderer class
 *
 *	isSelected			return true if this element selected (highlighted) and false in other case
 *		return			Boolean		true if this element selected (highlighted) and false in other case
 *
 * Private methods:
 *	onClick				reacts on clicking on element. !!!Must fire event 'itemSelectInternal' and pass this property, like this:
 *						this.fireEvent('itemSelectInternal', this);!!!
 */

var SelectBaseItemRenderer = new Class({
	Implements: [Options, Events],

	options: {
		'__id__':			'',
		'__cssClass__':		'select_item',
		'label':			'',
		'value':			'',
		'background-image':	'none',
		'overDuration':		500,
		'overTransition':	Fx.Transitions.linear,
		'outDuration':		300,
		'outTransition':	Fx.Transitions.linear
	},

	initialize: function(options) {
		this.setOptions(options);

		// private properties

		this.selected			= false;
		this.element			= null;
		this.onClickBound		= this.onClick.bind(this);
		this.onMouseEnterBound	= this.onMouseEnter.bind(this);
		this.onMouseLeaveBound	= this.onMouseLeave.bind(this);

		// visual components

		this.createElement();

		// private effects

		this.mouseOverEffect	= new Fx.Morph(this.element, {
			'link':			'cancel',
			'duration':		this.options.overDuration,
			'transition':	this.options.overTransition
		});
		this.mouseOutEffect		= new Fx.Morph(this.element, {
			'link':			'cancel',
			'duration':		this.options.outDuration,
			'transition':	this.options.outTransition
		});
	},

	getElement: function() {
		return this.element;
	},

	getLabel: function() {
		return this.options.label;
	},

	getValue: function() {
		return this.options.value;
	},

	getPassedParams: function() {
		var params	= {};

		for (var i in this.options) {
			if ((i != '__id__') &&
				(i != '__cssClass__') &&
				(i != 'overDuration') &&
				(i != 'overTransition') &&
				(i != 'outDuration') &&
				(i != 'outTransition')) {
				params[i] = this.options[i];
			}
		}

		return params;
	},

	destroy: function() {
		this.element.removeEvents();
		this.element.destroy();

		this.element			=
		this.onClickBound		=
		this.onMouseEnterBound	=
		this.onMouseLeaveBound	=
		this.mouseOverEffect	=
		this.mouseOutEffect		= null;

		return this;
	},

	select: function() {
		if (!this.selected) {
			this.selected	= true;

			this.mouseOutEffect.cancel();
			this.mouseOverEffect.start('.' + this.options.__cssClass__ + '_active');

			this.fireEvent('itemFocus', this);
		}

		return this;
	},

	deselect: function() {
		if (this.selected) {
			this.selected	= false;

			this.mouseOverEffect.cancel();
			this.mouseOutEffect.start('.' + this.options.__cssClass__);

			this.fireEvent('itemBlur', this);
		}

		return this;
	},

	isSelected: function() {
		return this.selected;
	},

	/**
	 * Private function!
	 */
	createElement: function() {
		this.element	= new Element('li', {
			'id':					this.options.__id__,
			'class':				this.options.__cssClass__,
			'styles': {
				'background-image':	((this.options['background-image'] != 'none') ? this.options['background-image'] : 'url(images/icons/' + this.options['value'] + '.gif)')
			},
			'events': {
				'mousedown':		this.onClickBound,
				'mouseenter':		this.onMouseEnterBound
			}
		}).set('html', this.options.label);
	},

	/**
	 * Private function! Reacts on clicking on item
	 */
	onClick: function() {
		this.fireEvent('itemSelectInternal', this);
	},

	/**
	 * Private function! Reacts on entering mouse to item
	 */
	onMouseEnter: function() {
		this.select();

		this.element.removeEvent('mouseenter',	this.onMouseEnterBound);
		this.element.addEvent('mouseleave',		this.onMouseLeaveBound);
	},

	/**
	 * Private function! Reacts on leaving mouse from item
	 */
	onMouseLeave: function() {
		this.deselect();

		this.element.removeEvent('mouseleave',	this.onMouseLeaveBound);
		this.element.addEvent('mouseenter',		this.onMouseEnterBound);
	}
});

var SelectsManager = new Class({
	Implements: [Options, Events],

	options: {
		'id':				'select',
		'selector':			'select',
		'cssClass':			'select',
		'itemRenderer':		SelectBaseItemRenderer,
		'showDuration':		200,
		'showTransition':	Fx.Transitions.linear,
		'hideDuration':		100,
		'hideTransition':	Fx.Transitions.linear
	},

	initialize: function(options) {
		this.setOptions(options);

		this.onItemSelectInternalBound	= this.onItemSelectInternal.bind(this);

		this.selects					= new Array();

		this.attachDefaultSelects();
	},

	attach: function(options) {
		if (options.select) {
			options		= $merge(this.options, options);
			delete options.selector;

			var id		= ($type(options.select) == 'string') ? options.select : $(options.select).get('id') || this.selects.length.toString();
			options.id	= options.id + '-' + id;

			var slct	= new SelectsManager.Select(options);
			slct.addEvent('itemSelectInternal', this.onItemSelectInternalBound);

			this.selects.push(slct);

			id			= null;
			slct		= null;
		}

		return this;
	},

	detach: function(select) {
		if (select) {
			var slct	= $(select).retrieve('select');

			if (slct) {
				this.selects.splice(this.selects.indexOf(slct), 1);

				slct.destroy();

				slct	= null;
			}
		}

		return this;
	},

	getSelectBySelect: function(select) {
		return $(select).retrieve('select');
	},

	attachDefaultSelects: function() {
		$$('select.' + this.options.selector).each(function(el) {
			if (!el.retrieve('select')) {
				this.attach({ 'select': el });
			}
		}, this);

		return this;
	},

	getId: function() {
		return this.options.id;
	},

	setId: function(value) {
		this.options.id	= value;

		this.selects.each(function(el) {
			el.setId(value);
		});

		return this;
	},

	getSelector: function() {
		return this.options.selector;
	},

	setSelector: function(value) {
		this.options.selector = value;

		return this;
	},

	getCSSClass: function() {
		return this.options.cssClass;
	},

	setCSSClass: function(value) {
		this.options.cssClass	= value;

		this.selects.each(function(el) {
			el.setCSSClass(value);
		});

		return this;
	},

	getItemRenderer: function() {
		return this.options.itemRenderer;
	},

	setItemRenderer: function(value) {
		this.options.itemRenderer	= value;

		this.selects.each(function(el) {
			el.setItemRenderer(value);
		});

		return this;
	},

	getShowDuration: function() {
		return this.options.showDuration;
	},

	setShowDuration: function(value) {
		this.options.showDuration = value;

		this.selects.each(function(el) {
			el.setShowDuration(value);
		});

		return this;
	},

	getShowTransition: function() {
		return this.options.showTransition;
	},

	setShowTransition: function(value) {
		this.options.showTransition = value;

		this.selects.each(function(el) {
			el.setShowTransition(value);
		});

		return this;
	},

	getHideDuration: function() {
		return this.options.hideDuration;
	},

	setHideDuration: function(value) {
		this.options.hideDuration = value;

		this.selects.each(function(el) {
			el.setHideDuration(value);
		});

		return this;
	},

	getHideTransition: function() {
		return this.options.hideTransition;
	},

	setHideTransition: function(value) {
		this.options.hideTransition = value;

		this.selects.each(function(el) {
			el.setHideTransition(value);
		});

		return this;
	},

	/**
	 * Private function! React on item selecting
	 */
	onItemSelectInternal: function(select, params) {
		this.fireEvent('itemSelect', [select, params]);
	}
});

SelectsManager.Select = new Class({
	Implements: [Options, Events],

	options: {
		'select':			null,
		'id':				'select',
		'cssClass':			'select',
		'itemRenderer':		SelectBaseItemRenderer,
		'showDuration':		200,
		'showTransition':	Fx.Transitions.linear,
		'hideDuration':		100,
		'hideTransition':	Fx.Transitions.linear
	},

	initialize: function(options) {
		this.setOptions(options);

		this.options.select						= $(this.options.select);

		this.options.select.store('select', this);

		// private properties

		this.shown								= false;
		this.container							= null;
		this.handler							= null;
		this.list								= null;
		this.items								= [];
		this.onContainerMouseOutBound			= this.onContainerMouseOut.bind(this);
		this.onHandlerPressBound				= this.onHandlerPress.bind(this);
		this.onItemSelectInternalBound			= this.onItemSelectInternal.bind(this);
		this.onItemFocusBound					= this.onItemFocus.bind(this);
		this.onItemBlurBound					= this.onItemBlur.bind(this);
		this.onShowListEffectStartBound			= this.onShowListEffectStart.bind(this);
		this.onHideListEffectCompleteBound		= this.onHideListEffectComplete.bind(this);
		this.onHideHandlerEffectCompleteBound	= this.onHideHandlerEffectComplete.bind(this);

		// visual components

		this.createContainer();
		this.createHandler();
		this.createList();

		// private effects

		this.showListEffect	= new Fx.Morph(this.list, {
			'link':			'cancel',
			'duration':		this.options.showDuration,
			'transition':	this.options.showTransition,
			'onStart':		this.onShowListEffectStartBound
		});
		this.hideListEffect	= new Fx.Morph(this.list, {
			'link':			'cancel',
			'duration':		this.options.hideDuration,
			'transition':	this.options.hideTransition,
			'onComplete':	this.onHideListEffectCompleteBound
		});
		this.showHandlerEffect = new Fx.Morph(this.handler, {
			'duration':		this.options.showDuration,
			'transition':	this.options.showTransition
		});
		this.hideHandlerEffect = new Fx.Morph(this.handler, {
			'duration':		this.options.hideDuration,
			'transition':	this.options.hideTransition,
			'onComplete':	this.onHideHandlerEffectCompleteBound
		});
	},

	destroy: function() {
		this.items.each(function(el) {
			el.removeEvents();
			el.destroy();
		});
		this.items.empty();

		this.list.removeEvents();
		this.list.destroy();

		this.handler.removeEvents();
		this.handler.destroy();

		this.options.select.setStyle('display', 'inline');

		this.options.select.store('select', null);

		this.list							=
		this.items							=
		this.onItemSelectInternalBound		=
		this.onItemFocusBound				=
		this.onItemBlurBound				=
		this.onSelectFocusBound				=
		this.onSelectBlurBound				=
		this.onShowListEffectStartBound		=
		this.onHideListEffectCompleteBound	=
		this.showListEffect					=
		this.hideListEffect					= null;

		return this;
	},

	show: function() {
		if (!this.shown) {
			this.showListEffect.start({ 'opacity': 1 });
		}

		return this;
	},

	hide: function() {
		if (this.shown) {
			this.hideListEffect.start({ 'opacity': 0 });
		}

		return this;
	},

	getId: function() {
		return this.options.id;
	},

	setId: function(value) {
		this.list.set('id', value + '-list');
		this.items.each(function(el) {
			el			= el.getElement();

			var id		= el.get('id').split('-');
			id[0]		= value;

			el.set('id', id.join('-'));

			el			= null;
			id			= null;
		});

		this.options.id	= value;

		return this;
	},

	getCSSClass: function() {
		return this.options.cssClass;
	},

	setCSSClass: function(value) {
		this.list.set('class', value + '_list');
		this.items.each(function(el) {
			el					= el.getElement();

			var clss			= el.get('class').split('_');
			clss[0]				= value;

			el.set('class', clss.join('_'));

			el					= null;
			clss				= null;
		});

		this.options.cssClass	= value;

		return this;
	},

	getItemRenderer: function() {
		return this.options.itemRenderer;
	},

	setItemRenderer: function(value) {
		this.options.itemRenderer = value;

		if (this.shown) {
			this.onShowListEffectStartBound();
		}

		return this;
	},

	getShowDuration: function() {
		return this.options.showDuration;
	},

	setShowDuration: function(value) {
		this.options.showDuration = value;

		this.showListEffect.set('duration', value);

		return this;
	},

	getShowTransition: function() {
		return this.options.showTransition;
	},

	setShowTransition: function(value) {
		this.options.showTransition = value;

		this.showListEffect.set('transition', value);

		return this;
	},

	getHideDuration: function() {
		return this.options.hideDuration;
	},

	setHideDuration: function(value) {
		this.options.hideDuration = value;

		this.hideListEffect.set('duration', value);

		return this;
	},

	getHideTransition: function() {
		return this.options.hideTransition;
	},

	setHideTransition: function(value) {
		this.options.hideTransition = value;

		this.hideListEffect.set('transition', value);

		return this;
	},

	/**
	 * Private function! Create list (ul element);
	 */
	createContainer: function() {
		var selectPos	= this.options.select.getPosition();

		this.container	= new Element('div', {
			'id':			this.options.id + '-container',
			'class':		this.options.cssClass + '_container',
			'styles': {
				'position':	'absolute',
				'width':	this.options.select.getSize().x + 'px',
				'left':		selectPos.x + 'px',
				'top':		selectPos.y + 'px'
			},
			'events': {
				'mouseleave': this.onContainerMouseOutBound
			}
		});

		this.options.select.setStyle('visibility', 'hidden');

		document.body.grab(this.container);

		selectPos		= null;
	},

	/**
	 * Private function! Create list (ul element);
	 */
	createHandler: function() {
		var selectedOpt	= this.options.select.getSelected();

		this.handler	= new Element('div', {
			'id':					this.options.id + '-handler',
			'class':				this.options.cssClass + '_handler',
			'styles': {
				'background-image':	'url(images/icons/' + selectedOpt.get('value') + '.gif)'
			},
			'events': {
				'mousedown': this.onHandlerPressBound
			}
		}).set('html', selectedOpt.get('html'));

		this.container.grab(this.handler);

		selectedOpt		= null;
	},

	/**
	 * Private function! Create list (ul element);
	 */
	createList: function() {
		this.list	= new Element('ul', {
			'id':				this.options.id + '-list',
			'class':			this.options.cssClass + '_list',
			'styles': {
				'width':		this.options.select.getSize().x + 'px',
				'overflow':		'hidden',
				'visibility':	'hidden'
			}
		});

		this.container.grab(this.list);
	},

	/**
	 * Private function! Adds new item to list
	 */
	addItem: function(options) {
		options.__id__			= this.options.id + '-item-' + this.items.length;
		options.__cssClass__	= this.options.cssClass + '_item';

		var newItem				= new this.options.itemRenderer(options);
		newItem.addEvents({
			'itemSelectInternal':	this.onItemSelectInternalBound,
			'itemFocus':			this.onItemFocusBound,
			'itemBlur':				this.onItemBlurBound
		});

		this.list.grab(newItem.getElement());

		this.items.push(newItem);

		newItem					= null;

		return this;
	},

	/**
	 * Private function! Replace current items with new set
	 */
	replaceItems: function(items) {
		if ($type(items) == 'array') {
			this.items.each(function(el) {
				el.removeEvents();
				el.destroy();
			});
			this.items.empty();

			for (var i=0; i<items.length; ++i) {
				this.addItem(items[i]);
			}
		}

		return this;
	},

	/**
	 * Private function! Selects (highlights) previous item. If no item selected then selects last item
	 */
	selectPrevious: function() {
		if (this.shown) {
			var i	= 0;
			while ((!this.items[i].isSelected()) && (++i < this.items.length));

			if (i < this.items.length) {
				this.items[i].deselect();
			}

			i		= (i == 0) ? this.items.length - 1 : i - 1;

			this.items[i].select();
		}
	},

	/**
	 * Private function! Selects (highlights) next item. If no item selected then selects first item
	 */
	selectNext: function() {
		if (this.shown) {
			var i	= 0;
			while ((!this.items[i].isSelected()) && (++i < this.items.length));

			if (i < this.items.length) {
				this.items[i].deselect();
			}

			i		= (i >= this.items.length - 1) ? 0 : i + 1;

			this.items[i].select();
		}
	},

	/**
	 * Private function!
	 */
	onContainerMouseOut: function() {
		var selectedOpt	= this.options.select.getSelected();

		this.handler.set('html', selectedOpt.get('html'));
		this.handler.setStyle('background-image', 'url(images/icons/' + selectedOpt.get('value') + '.gif)');

		this.hide();
	},

	/**
	 * Private function!
	 */
	onHandlerPress: function() {
		this.show();
	},

	/**
	 * Private function! Reacts on clicking on some item
	 */
	onItemSelectInternal: function(item) {
		this.fireEvent('itemSelectInternal', [this.options.select, item.getPassedParams()]);
		this.options.select.fireEvent('itemSelect', item.getPassedParams());

		this.options.select.set('value', item.getValue());

		this.hide();
	},

	/**
	 * Private function! Reacts on selecting (highlighting) some item
	 */
	onItemFocus: function(item) {
		this.items.each(function(el) {
			if (el != item) {
				el.deselect();
			}
		});

		this.hideHandlerEffect.start({ 'opacity': 0 });
	},

	/**
	 * Private function! Reacts on loosing select (highlight) of some item
	 */
	onItemBlur: function(item) {
	},

	/**
	 * Private function! Reacts on starting showListEffect
	 */
	onShowListEffectStart: function() {
		this.shown			= true;

		var selected		= this.options.select.getSelected()[0];
		var options			= this.options.select.getElements('option');
		var optionsCount	= options.length;
		var items			= [];

		for (var i = 0; i < optionsCount; ++i) {
			if (options[i] != selected) {
				items.push({
					'label':			options[i].get('text'),
					'value':			options[i].get('value')
				});
			}
		}

		this.replaceItems(items);

		var windowBottom	= window.getScroll().y + window.getSize().y;
		var selectCoords	= this.options.select.getCoordinates();

		var lastVisible		= this.items.getLast().getElement();
		var listHeight		= (lastVisible.getPosition().y + lastVisible.getSize().y) - this.items[0].getElement().getPosition().y;
		var listTop			= (selectCoords.bottom + listHeight < windowBottom) ? selectCoords.bottom : selectCoords.top - listHeight;

		this.list.setStyles({
			'left':			this.options.select.getPosition().x,
			'top':			listTop
		});

		this.container.set('class', this.container.get('class') + '_expanded');

		selectCoords		= null;
		lastVisible			= null;
	},

	/**
	 * Private function! Reacts on completing hideListEffect
	 */
	onHideListEffectComplete: function() {
		this.items.each(function(el) {
			el.removeEvents();
			el.destroy();
		});
		this.items.empty();

		this.container.set('class', this.options.cssClass + '_container');

		this.shown			= false;
	},

	/**
	 * Private function! Reacts on completing hideHandlerEffect
	 */
	onHideHandlerEffectComplete: function() {
		var i	= 0;
		while ((!this.items[i].isSelected()) && (++i < this.items.length));

		if (i < this.items.length) {
			this.handler.set('html', this.items[i].getElement().get('html'));
			this.handler.setStyle('background-image', this.items[i].getElement().getStyle('background-image'));
		}

		this.showHandlerEffect.start({ 'opacity': 1 });
	}
});

window.addEvent('domready', function() {
	window.Select = new SelectsManager();
});

