in360Viewer = new Class({
	Implements: [Chain, Events, Options],
	
	options: {
		classes: [],
		controller: false,
		duration: 750,
		frequency: 20,
		paused: false,
		transition: function(p){return -(Math.cos(Math.PI * p) - 1) / 2;}
		
	},
	initialize: function(el, tourImage, options){
		this.setOptions(options);
		this.virtualTour = $(el);
		if (!this.virtualTour) {
			return;
		}
		// Classes
		var keys = ['virtualTour', 'first', 'prev', 'play', 'pause', 'next', 'last', 'images', 'captions', 'controller', 'thumbnails', 'hidden', 'visible', 'inactive', 'active', 'loader'];
		var values = keys.map(function(key, i) {
			return this.options.classes[i] || key;
		}, this);
		this.classes = values.associate(keys);
		this.classes.get = function(){
			var str = '.' + this.virtualTour;
			for (var i = 0, l = arguments.length; i < l; i++) {
				str += ('-' + this[arguments[i]]);
			}
			return str;
		}.bind(this.classes);
		
		this.events = $H({'keydown': [], 'keyup': [], 'mousemove': []});
		var keyup = function(e){
			switch(e.key){
				case 'left': 
					this.prev(e.shift); break;
				case 'right': 
					this.next(e.shift); break;
				case 'p': 
					this.pause(); break;
			}
		}.bind(this);
		this.events.keyup.push(keyup);
		document.addEvent('keyup', keyup);
		
		this.tourImage = this.virtualTour.getElement(this.classes.get('virtualTour'));
		this.actionPause = false;
		this.paused = true;
		this.currX = false;
		this.timer = false;
		this.setTour(tourImage);
		
		var myDragScroller = new Drag(this.tourImage, {
			onBeforeStart: function (el) {
				if (this.paused == false) {
					this.actionPause = true;
					this.pause();
				}
			}.bind(this),
			onComplete: function (el) {
				bX = this.tourImage.style.backgroundPosition.split(" ")[0];
				this.currX = bX.substring(0,(bX.length-2));
				if (this.actionPause == true) {
					this.actionPause = false;
					this.start();
				}
			}.bind(this),
			style: true,
			invert: true,
			modifiers: {x: 'backgroundPosition', y: 'top'}
		});
		
		if (this.options.controller) {
			this._controller();
		}
		
		this.start();
	},
	setTour: function (url) {
		/*if (!this.tourImage.retrieve('morph')){
			var options = (this.options.overlap) ? {'duration': this.options.duration, 'link': 'cancel'} : {'duration': this.options.duration / 2, 'link': 'chain'};
			$$(this.a, this.b).set('morph', $merge(options, {'onStart': this._start.bind(this), 'onComplete': this._complete.bind(this), 'transition': this.options.transition}));
		}
		var hidden = this.classes.get('images', ((this.direction == 'left') ? 'next' : 'prev'));
		var visible = this.classes.get('images', 'visible');
		var img = (this.counter % 2) ? this.a : this.b;
		
		if (this.options.overlap){
			img.get('morph').set(visible);
			this.tourImage.get('morph').set(hidden).start(visible);
		} else {
			var fn = function(hidden, visible) {
				this.image.get('morph').set(hidden).start(visible);
			}.pass([hidden, visible], this);
			hidden = this.classes.get('images', ((this.direction == 'left') ? 'prev' : 'next'));
			img.get('morph').set(visible).start(hidden).chain(fn);
		}
		*/
		
		this.setBGPosition(0);
		this.tourImage.style.backgroundImage = "url(" + url + ")";
	},
	setBGPosition: function (x) {
		this.currX = x;
		this.tourImage.style.backgroundPosition = +x+'px 0px';
		//alert(paw_vt_el.style.backgroundPositionX);
	},
	start: function () {
		this.paused = false;
		this.setBG(this.currX);
	},
	pause: function () {
		if (this.paused == false) {
			this.paused = true;
			clearTimeout(this.timer);
		} else {
			this.start();
		}
	},
	setBG: function (x) {
		this.setBGPosition(x);
		/*if (x) {
			alert("Revolutions: " + );
		}*/
		this.timer = setTimeout(function () {this.setBG(x-1)}.bind(this),this.options.frequency);
	},
	_controller: function(){
		if (this.options.controller === true) {
			this.options.controller = {};
		}
		var el = this.virtualTour.getElement(this.classes.get('controller'));
		var controller = (el) ? el.empty() : new Element('div', {'class': this.classes.get('controller').substr(1)}).inject(this.virtualTour);
		var ul = new Element('ul').inject(controller);
		$H({/*'first': 'Shift + Leftwards Arrow', 'prev': 'Leftwards Arrow', */'pause': 'P'/*, 'next': 'Rightwards Arrow', 'last': 'Shift + Rightwards Arrow'*/}).each(function(accesskey, action){
			var li = new Element('li', {
				'class': (action == 'pause' && this.options.paused) ? this.classes.play + ' ' + this.classes[action] : this.classes[action]
			}).inject(ul);
			var a = this.virtualTour.retrieve(action, new Element('a', {
				'title': ((action == 'pause') ? this.classes.play.capitalize() + ' / ' : '') + this.classes[action].capitalize() + ' [' + accesskey + ']'
			}).inject(li));
			a.set('events', {
				'click': function(action){this[action]();}.pass(action, this),
				'mouseenter': function(active){this.addClass(active);}.pass(this.classes.active, a),
				'mouseleave': function(active){this.removeClass(active);}.pass(this.classes.active, a)
			});
		}, this);
		controller.set({
			'events': {
				'hide': function(hidden){
					if (!this.retrieve('hidden')) {
						this.store('hidden', true).morph(hidden);
					}
				}.pass(this.classes.get('controller', 'hidden'), controller),
				'show': function(visible){  
					if (this.retrieve('hidden')) {
						this.store('hidden', false).morph(visible);
					}
				}.pass(this.classes.get('controller', 'visible'), controller)
			},
			'morph': $merge(this.options.controller, {'link': 'cancel'})
		}).store('hidden', false);
		var keydown = function(e){
			if (['left', 'right', 'p'].contains(e.key)){
				var controller = this.virtualTour.retrieve('controller');
				if (controller.retrieve('hidden')) {
					controller.get('morph').set(this.classes.get('controller', 'visible'));
				}
				switch(e.key){
					case 'left': 
						this.virtualTour.retrieve((e.shift) ? 'first' : 'prev').fireEvent('mouseenter'); break;
					case 'right':
						this.virtualTour.retrieve((e.shift) ? 'last' : 'next').fireEvent('mouseenter'); break;
					default:
						this.virtualTour.retrieve('pause').fireEvent('mouseenter'); break;
				}
			}
		}.bind(this);
		this.events.keydown.push(keydown);
		var keyup = function(e){
			if (['left', 'right', 'p'].contains(e.key)){
				var controller = this.virtualTour.retrieve('controller');
				if (controller.retrieve('hidden'))
					controller.store('hidden', false).fireEvent('hide');
				switch(e.key){
					case 'left': 
						this.virtualTour.retrieve((e.shift) ? 'first' : 'prev').fireEvent('mouseleave'); break;
					case 'right': 
						this.virtualTour.retrieve((e.shift) ? 'last' : 'next').fireEvent('mouseleave'); break;
					default:
						this.virtualTour.retrieve('pause').fireEvent('mouseleave'); break;
				}
			}
		}.bind(this);
		this.events.keyup.push(keyup);
		var mousemove = function(e){
			var images = this.tourImage.getCoordinates();
			if (e.page.x > images.left && e.page.x < images.right && e.page.y > images.top && e.page.y < images.bottom) {
				this.virtualTour.retrieve('controller').fireEvent('show');
			} else {
				this.virtualTour.retrieve('controller').fireEvent('hide');
			}
		}.bind(this);
		this.events.mousemove.push(mousemove);
		document.addEvents({'keydown': keydown, 'keyup': keyup, 'mousemove': mousemove});
		this.virtualTour.retrieve('controller', controller).fireEvent('hide');
	}
});
