if (typeof MOTO === 'undefined') { var MOTO = {}; MOTO.modulesLoaded = []; }
if (typeof MOTO.StyledForm === 'undefined') { MOTO.StyledForm = {}; }

MOTO.StyledForm.Slider = new Class(function() {
	function stopEvent(e) {
		var evt;
		if (e) {
			evt = new Event(e);
			evt.stop();
		}
	}
	return {
		Implements: [Events, Options],
		options: {
			animate: true,
			duration: 250,
			transition: 'circ:out',
			itemSize: 120,
			horizontal: true,
			forwardButtonClass: 'forward',
			backButtonClass: 'back',
			scrubberClass: 'scrubber',
			snapTo: true,
			trackClass: 'track',
			buttonHoldDelay: 150
		},
		el: null,
		track: null,
		trackSize: null,
		scrubber: null,
		scrubberSize: null,
		scrubberPosition: null,
		itemTrackSize: null,
		forwardButton: null,
		backButton: null,
		drag: false,
		dragOffset: null,
		buttonHoldInterval: null,
		events: {},
		scrubberLimits: { 'top': null, 'bottom': null, 'left': null, 'right': null },
		initialize: function(el, scrubberRatio, options) {
			this.setOptions(options);
			this.el = $(el);
			options = this.options;
			this.track = el.getElement('.' + this.options.trackClass);
			var sliderSize;
			if (options.horizontal) {
				sliderSize = el.getSize().x;
				this.trackSize = this.track.getSize().x;
				this.scrubberTween = 'left';
			} else {
				sliderSize = el.getSize().y;
				this.trackSize = this.track.getSize().y;
				this.scrubberTween = 'top';
			}

			this.events = {
				'mousedown': this.mouseDown.bind(this),
				'mousemove': this.mouseMove.bind(this),
				'mouseup': this.mouseUp.bind(this)
			};
			this.track.addEvent('mousedown', this.events.mousedown);
			document.addEvent('mousemove', this.events.mousemove);
			document.addEvent('mouseup', this.events.mouseup);

			this.scrubber = el.getElement('.' + this.options.scrubberClass);
			this.scrubberSize = Math.floor(scrubberRatio * sliderSize);
			
			this.scrubberPosition = 0;
			this.scrubber.set('tween', {
				duration: this.options.duration,
				transition: this.options.transition
			});
			this.scrubber.setStyle(this.options.horizontal ? 'width' : 'height', this.scrubberSize);

			this.itemTrackSize = this.options.itemSize * scrubberRatio;

			this.forwardButton = el.getElement('.' + this.options.forwardButtonClass);
			var forwardButton = this.forwardButton;
			forwardButton.addEvent('mousedown', this.forwardButtonClick.bind(this));
			forwardButton.addEvent('click', stopEvent);

			this.backButton = el.getElement('.' + this.options.backButtonClass);
			var backButton = this.backButton;
			backButton.addEvent('mousedown', this.backButtonClick.bind(this));
			backButton.addEvent('click', stopEvent);

			if (this.options.horizontal) {
				this.scrubberLimits.left = 0;
				this.scrubberLimits.right = this.trackSize - this.scrubberSize;
			} else {
				this.scrubberLimits.top = 0;
				this.scrubberLimits.bottom = this.trackSize - this.scrubberSize;
			}
		},
		load: function() {
			this.el.fade('in');
		},
		mouseDown: function(e) {
			this.drag = true;
			this.isMouseDown = true;
			stopEvent(e);
			var mousePosition = this.options.horizontal ? e.page.x : e.page.y;
			if (this.isPositionAboveScrubber(mousePosition)) {
				this.setScrubberOffset(mousePosition);
			} else {
				this.centerScrubberToPosition(mousePosition);
			}
		},
		mouseMove: function(e) {
			stopEvent(e);
			var mousePosition;
			if (this.drag) {
				mousePosition = this.options.horizontal ? e.page.x : e.page.y;
				this.dragScrubberTo(mousePosition);
			}
		},
		mouseUp: function() {
			$clear(this.buttonHoldInterval);
			if (!this.isMouseDown) { return; } 
			this.isMouseDown = false;
			if (this.drag) {
				this.drag = false;
			}
			var modGrid = this.scrubberPosition % this.itemTrackSize;
			var newPosition = this.scrubberPosition;
			var positionRatio;
			if (this.options.snapTo) {
				if (modGrid > 0) {
					newPosition = this.scrubberPosition - modGrid;
				}
				if (newPosition !== this.scrubberPosition &&
							this.scrubberPosition !== (this.trackSize - this.scrubberSize)) {
					this.setScrubberPosition(newPosition);
				} else if (newPosition !== this.scrubberPosition &&
							this.scrubberPosition === (this.trackSize - this.scrubberSize)) {
					positionRatio = newPosition/this.trackSize;
					this.options.animate ? this.fireEvent('onSlideTo', positionRatio) : this.fireEvent('onMoveTo', positionRatio);
				}
			}
			if (this.scrubberPosition === (this.trackSize - this.scrubberSize)) {
				this.fireEvent('onReachedEnd',this);
			}
		},
		mouseWheel: function(e) {
			var evt = new Event(e);
			if (evt.wheel > 0 && this.scrubberPosition != this.scrubberLimits[this.options.horizontal ? 'left' : 'top']) {
				// wheel up
				this.backButtonClick(e);
			} else if (evt.wheel < 0 && this.scrubberPosition != this.scrubberLimits[this.options.horizontal ? 'right' : 'bottom']) {
				// wheel down
				this.forwardButtonClick(e);
			}
			this.isMouseDown = true;
			this.mouseUp();
		},
		forwardButtonClick: function(e) {
			stopEvent(e);
			this.isMouseDown = true;
			this.slideScrubberTo(this.scrubberPosition + this.scrubberSize);
			this.buttonHoldInterval = this.forwardButtonClick.delay(this.options.buttonHoldDelay,this);
		},
		backButtonClick: function(e) {
			stopEvent(e);
			this.isMouseDown = true;
			this.slideScrubberTo(this.scrubberPosition - this.scrubberSize);
			this.buttonHoldInterval = this.backButtonClick.delay(this.options.buttonHoldDelay,this);
		},
		slideScrubberTo: function(trackPosition) {
			this.setScrubberPosition(trackPosition);
		},
		setScrubberOffset: function(position) {
			var trackPosition = this.getTrackPosition(position);
			this.dragOffset = trackPosition - this.scrubberPosition;
		},
		dragScrubberTo: function(position) {
			var trackPosition = this.getTrackPosition(position);
			this.setScrubberPosition(trackPosition - this.dragOffset);
		},
		isPositionAboveScrubber: function(position) {
			var trackPosition = this.getTrackPosition(position);
			return (trackPosition > this.scrubberPosition && trackPosition < (this.scrubberPosition + this.scrubberSize)) ? true : false;
		},
		getTrackPosition: function(position) {
			var trackPos = this.options.horizontal ? this.track.getPosition().x : this.track.getPosition().y;
			return position - trackPos;
		},
		centerScrubberToPosition: function(position) {
			var trackPosition = this.getTrackPosition(position);
			var halfScrubberSize = this.scrubberSize/2;
			this.setScrubberPosition(trackPosition - halfScrubberSize);
			this.dragOffset = halfScrubberSize;
		},
		setScrubberPosition: function(position, animate) {
			animate = animate || this.options.animate;
			this.scrubberPosition = position;
			if (this.scrubberPosition < 0) {
				this.scrubberPosition = 0;
			} else if ((this.scrubberPosition + this.scrubberSize) > this.trackSize) {
				this.scrubberPosition = this.trackSize - this.scrubberSize;
			}
			var positionRatio = this.scrubberPosition/this.trackSize;
			if (animate) {
				this.scrubber.tween(this.scrubberTween, this.scrubberPosition);
				this.fireEvent('onSlideTo', positionRatio);
			} else {
				this.scrubber.setStyle(this.scrubberTween, this.scrubberPosition);
				this.fireEvent('onMoveTo', positionRatio);
			}
		},
		destroy: function() {
			this.track.removeEvent('mousedown', this.events.mousedown);
			document.removeEvent('mousemove', this.events.mousemove);
			document.removeEvent('mouseup', this.events.mouseup);
			this.el.destroy();
			this.el = null;
			this.track = null;
			this.scrubber = null;
			this.forwardButton = null;
			this.backButton = null;
		}
	};
}());
