/*global $, Class, Element, Events, Fx, Options  */
// requires: core, element, event, options

/* rev 1.1 
 * 		menu element no longer passed in constructor.
 * 		autoMenu property now should be the menu ul/li to which events are assigned.
 * rev 1.2 - changed in this version
 * 		start and stop events added
 * 		added public menu()
 * 		conditional zoom to fix IE "first click" issue;
 */
var Rubik = new Class({
	Implements: [Options,Events],
	options: {
		mode: 'horizontal', // or vertical
		autoMenu: false, //  automatically assign events to this ul/li set.
		menuMap: false, // map how the events are assigned
		nextBtn: false, // assigns a next event with wraparound
		transition: Fx.Transitions.Sine.easeInOut, //  slide transition
		duration: 2000, // slide duration
		current: 0, //  default slide to start on
		scrollAct: true, // automatically assigns mouse-wheel events
		constVelo: true,  // maintain a constant time between multiple slides.
		//class names
		clsRoot: 'rubik_',
		clsCont: 'container',
		clsDraw: 'drawer',
		clsPage: 'page',
		clsFix: '',
		// events
		onScrollStart: function(){},
		onScrollStop: function(){}
	},
	moving: false,
	current: 0,
	initialize: function(container,options){
		this.setOptions(options);
		this.current = this.options.current;
		this.container = $(container);
		this.drawer = new Element('div',{'class':this.options.clsRoot+this.options.clsDraw+this.options.clsFix});//.set('html',this.container.get('html'));
		this.container.getChildren().each(function(el,idx,ar){
				el.addClass(this.options.clsRoot+this.options.clsPage+this.options.clsFix);
				this.drawer.wraps(el);
		},this);
		
		this.container.addClass(this.options.clsRoot+this.options.clsCont+this.options.clsFix);
		
		if(this.options.mode=='vertical'){
			this.drawer.setStyle('height',this.container.getCoordinates().height*this.container.getChildren('div').length);
		}else{
			this.drawer.setStyle('width',this.container.getCoordinates().width*this.container.getChildren('div').length);
		}
		var obj = this;
		// add menu events if specified
		
		if (this.options.autoMenu){
			this.menu = $(this.options.autoMenu);
			this.addMenu(this.menu,this.options.menuMap);
			
		}
		// add next button event if specified
		if (this.options.nextBtn){
			$(this.options.nextBtn).addEvent('click',function(ev){
					ev.preventDefault();
					obj.next();
			});
		}
		// add the fx object
		this.efx = new Fx.Morph(this.drawer,{
			transition: this.options.transition,
			duration: this.options.duration,
			link: 'cancel'
		});
		// add scroll events if enabled
		if (this.options.scrollAct){
			this.container.addEvent('mousewheel',function(mwe){
				mwe.stop();
				if(mwe.wheel < 0){
					if (obj.current < obj.drawer.getChildren('div').length-1){
						obj.jumpTo(obj.current+1);
					}
				}else{
					if (obj.current > 0){
						obj.jumpTo(obj.current-1);
					}
				}
			});
		}
		// fix for click bug?
		if (Browser.Engine.trident){
			this.drawer.setStyle('zoom','1');
		}
		
		this.skipTrans(this.options.current);
	},
	
	jumpTo: function(idx){
		if (!this.moving){
			this.moving = true;
			
			var time;
			if (this.options.constVelo){
				time = this.options.duration;
			}else{
				time = this.options.duration * Math.abs(this.current - idx);
			}
			

			var obj = this;
			this.efx.set('duration',time);
			this.efx.start(this.movement(idx)).chain(function(){obj.current = idx; obj.moving = false;});
		}
	},
	
	skipTrans: function(idx){
		this.drawer.setStyles(this.movement(idx));
	},
	
	movement: function(idx){
		var movement;
		if(this.options.mode == 'vertical'){
			movement = {top: -(this.drawer.getChildren('div')[idx].getPosition(this.drawer).y)+'px'};
		}else{
			movement = {left: -(this.drawer.getChildren('div')[idx].getPosition(this.drawer).x)+'px'};
		}
		return movement;
	},
	
	next: function(){
		var next = this.current + 1;
		if (next > this.drawer.getChildren().length-1){
			next = 0;
		}
		this.jumpTo(next);
	},
	
	reset: function(){
		this.skipTrans(this.options.current);
	},
	
	addMenu: function(menuid, map){
		var obj = this;
		if (map){
		// if there's a menuMap specified, add the events to the menu as specified
			$(menuid).getElements('a').each(function(el,idx,ar){
				if (map[idx] !== -1){
					el.addEvent('click',function(ev){
						ev.preventDefault();
						obj.jumpTo(map[idx]);
					});
				}
			});
		}else{
		// otherwise just assign them sequentially.
			$(menuid).getElements('a').each(function(el,idx,ar){
				el.addEvent('click',function(ev){
					ev.preventDefault();
					obj.jumpTo(idx);
				});
			});
		}
	}
});