/**
 *	Scrolling marquee
 */
var BluQuee = new Class({
	
	/**
	 *	Options.
	 */
	Implements: [Options, Events],
	
	/**
	 *	Default options.
	 */
	options: {
		step: 1,			// Pixels per step.
		interval: 10,		// Milliseconds per step
		direction: 'left',	// Direction for inner content to move in., Accepts 'up', 'right', 'down' and 'left'.
		start: true,		// Start scrolling on load.
		reset: true,		// Whether to centre the content on load
		onMouseEnterFxOptions: {
			duration: 'long',
			transition: 'elastic:out'
		}					// Fx options for when marquee hovered.
	},
	
	/**
	 *	Stuff to do before starting the marquee.
	 */
	onInitialize: $empty,
	
	/**
	 *	Customisable mouse over event.
	 *
	 *	Wobbles content
	 */
	onMouseEnter: function () {
		this.position += 15 * this.vector;
		this.onMouseEnterFx = this.inner.get('tween', this.options.onMouseEnterFxOptions);
		this.onMouseEnterFx.start(this.property, this.position);		
	},
	
	/**
	 *	Customisable mouse leave event
	 *
	 *	Unwobbles content.
	 */
	onMouseLeave: function () {
		if (this.onMouseEnterFx) {
			this.onMouseEnterFx.cancel();
		}
	},
	
	/**
	 *	Containers for marquee
	 */
	container: null,
	inner: null,
	
	/**
	 *	Timer for calling the method
	 */
	timer: null,
	
	/**
	 *	CSS property ranges
	 */
	property: null,
	range: [],
	position: null,
	vector: null,
	
	/**
	 *	Constructor.
	 */
	initialize: function (container, options) {
		
		// Standard procedure
		this.container = $(container).addClass('bluquee');
		this.inner = this.container.getElement('.bluquee-inner');
		this.addEvents({
			'initialize': this.onInitialize.bindWithEvent(this),
			'mouseenter': this.onMouseEnter.bindWithEvent(this),
			'mouseleave': this.onMouseLeave.bindWithEvent(this)			
		});
		this.setOptions(options);
		
		// Delegate event handlers
		this.inner.addEvents({
			'mouseenter': this._onMouseEnter.bindWithEvent(this),
			'mouseleave': this._onMouseLeave.bindWithEvent(this)
		});
		
		// Set object parameters.
		this._setVectors();
		
		// Set initial position
		if (this.options.reset) {
			this._reset();
		}
		this.fireEvent('initialize');
		
		// Make initial move.
		if (this.options.start) {
			this.start();
		}
		
	},
	
	/**
	 *	Set up the CSS coordinate (and its boundaries) to transition, based on the given options.
	 */
	_setVectors: function () {
		var innerCoordinates = this.inner.getCoordinates();
		var outerCoordinates = this.container.getCoordinates();
		switch (this.options.direction) {
			case 'up':
				this.property = 'top';
				this.range = [
					outerCoordinates.height.toInt(),
					-innerCoordinates.height.toInt()
				];
				this.vector = -this.options.step;
				break;
				
			case 'right':
				this.property = 'left';
				this.range = [
					-innerCoordinates.width.toInt(),
					outerCoordinates.width.toInt()
				];
				this.vector = this.options.step;
				break;
				
			case 'down':
				this.property = 'top';
				this.range = [
					-innerCoordinates.height.toInt(),
					outerCoordinates.height.toInt()
				];
				this.vector = this.options.step;
				break;
				
			case 'left':
				this.property = 'left';
				this.range = [
					outerCoordinates.width.toInt(),
					-innerCoordinates.width.toInt()
				];
				this.vector = -this.options.step;
				break;
		}
	},
	
	/**
	 *	Mouse over event
	 */
	_onMouseEnter: function () {
		this.stop();
		this.fireEvent('mouseenter');
	},
	
	/**
	 *	Default mouse leave event
	 */
	_onMouseLeave: function () {
		this.fireEvent('mouseleave');
		this.start();
	},
	
	/**
	 *	Complete the marquee.
	 */
	complete: function () {
		this._reset();
		this.fireEvent('complete');
	},
	
	/**
	 *	Reset marquee to initial position
	 */
	_reset: function () {
		this.position = this.range[0];
	},
	
	/**
	 *	Start the marquee moving.
	 */
	start: function () {
		this.timer = this._move.delay(this.options.interval, this);
	},
	
	/**
	 *	Pause the marquee.
	 */
	stop: function () {
		$clear(this.timer);
	},
	
	/**
	 *	Move the marquee one step in the specified direction.
	 */
	_move: function () {
		
		// Move
		this.position += this.vector;
		this.inner.setStyle(this.property, this.position+'px');
		
		// Reached boundaries?
		this.range.each(function(limit) {
			if (limit > 0 && this.position > limit) {
				return this.complete();
			}
			if (limit < 0 && this.position < limit) {
				return this.complete();
			}
		}, this);
		
		// Recurse
		this.start();
		
	}
	
});
