/*
---

name: HoverGroup

description: Manages mousing in and out of multiple objects (think drop-down menus).

authors: Aaron Newton (this slightly changed version for MooTools 1.3 by Rolf Langenhuijzen)

license: MIT-style license.

requires: [Core, PowerTools!/Class.Binds]

provides: HoverGroup

...
*/

var HoverGroup = new Class({

	Implements: [Class.Binds, Options, Events],

	options: {
		/*
		onEnter: function(){},
		onLeave: function(){},
		*/
		elements: [],
		delay: 300,
		start: ['mouseenter'],
		remain: [],
		end: ['mouseleave']
	},

	initialize: function(options){
		this.setOptions(options);
		this.attachTo(this.options.elements);
		this.addEvents({
			leave: function(){
				this.active = false;
			},
			enter: function(){
				this.active = true;
			}
		});
	},

	elements: [],

	attachTo: function(elements, detach){
		var starters = {},
			remainers = {},
			enders = {};

		elements = Array.from(document.id(elements) || $$(elements));

		this.options.start.each(function(start){
			starters[start] = this.bound('enter');
		}, this);

		this.options.end.each(function(end){
			enders[end] = this.bound('leave');
		}, this);

		this.options.remain.each(function(remain){
			remainers[remain] = this.bound('remain');
		}, this);

		if (detach) {
			elements.each(function(el){
				el.removeEvents(starters).removeEvents(enders).removeEvents(remainers);
				this.elements.erase(el);
			}, this);
		} else {
			elements.each(function(el){
				el.addEvents(starters).addEvents(enders).addEvents(remainers);
			});
			this.elements.combine(elements);
		}
		return this;
	},

	detachFrom: function(elements){
		this.attachTo(elements, true);
	},

	enter: function(event){
		this.isMoused = true;
		this.assert(event);
	},

	leave: function(event){
		this.isMoused = false;
		this.assert(event);
	},

	remain: function(event){
		if (this.active) this.enter(event);
	},

	assert: function(event){
		clearTimeout(this.assertion);
		this.assertion = (function(){
			if (!this.isMoused && this.active) this.fireEvent('leave', event);
			else if (this.isMoused && !this.active) this.fireEvent('enter', event);
		}).delay(this.options.delay, this);
	}

});
