var f = null;

window.addEvent('domready', function() {
	init();
});

window.addEvent('unload', function() {
	f = null;
});

function init()
{
	f = new Engine();
	f.construct();
	
	f.addEvent('content', f.init.bind(f) );
}

var Engine = new Class({
	
	Implements: Events,
	
	construct: function( )
	{
		this.history = new HistoryManager();
		this.init( document );
		this.history.start();
	},
	
	init: function( obj )
	{
		this.addThis( obj.getElements('.addthis') );
		
		this.tabs( obj.getElements('.tabs') );
		this.multiloads( obj.getElements('.multiload') );
		this.scrolls( obj.getElements('.scroll'), obj.getElement('.scroll-here') );
		this.menus( obj.getElements('.menu') );
		this.expands( obj.getElements('.expand') );
		this.slideshows( obj.getElements('.slideshow') );
		this.sends( obj.getElements('.send') )
		
		Slimbox.scanPage( obj );
	},
	
	expands: function( objs )
	{
		objs.each( this.expand.bind(this) );
	},
	
	expand: function( obj )
	{
		obj.importOptions();
		
		obj.setStyle('overflow', 'hidden');
		obj.fx = new Fx.Tween( obj, {'property': 'height'} ).set( obj.options.from );
		obj.togglers = obj.getElements( obj.options.toggler );
		obj.togglers.addEvent('click', this.expandToggle.pass(obj, this) );
		obj.togglers.addEvent('click', function(e) { new Event(e).stop(); } );
		obj.status = 0;
	},
	
	expandToggle: function( obj )
	{
		obj.status = obj.status ? 0 : 1;
		obj.fx.start( obj.status ? obj.options.to : obj.options.from );
		obj.fireEvent('expanded');
	},
	
	sends: function( objs )
	{
		objs.each( this.send.bind(this) );
	},
	
	send: function( obj, i )
	{
		obj.importOptions();
		
		obj.addEvent('submit', function(obj) {
			var submit = obj.getElement('input[type=submit]');
			submit.set('value', submit.get('rel'));
			obj.set('send', {url: obj.options.url, method: 'post', 'onComplete': this.sendFill.pass(obj, this)} );
			obj.send(  );
		}.pass(obj, this) );
		obj.addEvent('submit', function(e) { e.stop(); } );
	},
	
	sendFill: function( obj )
	{
		var trg = $(obj.options.trg);
		trg.set('html', obj.get('send').response.text);
		this.fireEvent('content', trg);
	},
	
	slideshows: function( objs )
	{
		objs.each( this.slideshow.bind(this) );
	},
	
	slideshow: function( obj )
	{
		obj.importOptions();
		
		//obj.index = 0;
		obj.duration = 500;
		obj.delay = 5000;
		
		obj.nav = new Element('div', {'class': 'slideshow-btns'} ).inject( obj, 'before' );
		obj.buttons = []
		obj.blocks = obj.getElements(obj.options.blocks);
		for (var i=0; i<obj.blocks.length; i++)
		{
			obj.blocks[i].fx = new Fx.Tween( obj.blocks[i], { 'property': 'opacity', 'duration': obj.duration, 'link': 'cancel' } ).set(0);
			obj.buttons[i] = new Element('a', {'href': 'javascript:;', 'html': '<span>&nbsp;</span>'} ).addEvent('click', function(obj, i) { this.slideshowStep(obj, i); this.slideshowStop(obj); }.pass([obj, i], this) ).inject( obj.nav );
		}
		
		this.slideshowStep( obj, null );
		obj.addEvent('expanded', this.slideshowStop.pass(obj, this) );
	},
	
	slideshowStep: function( obj, n )
	{
		if (obj.slidetimer)
			$clear( obj.slidetimer );
		
		var i = obj.index;
		if (n == null)
		{
			// get next
			var n = ( (i != null) ? i+1 : 0 );
			if (n > obj.blocks.length-1)
				n = 0;
		}
		if ( (i != n) && obj.blocks[i])
			obj.blocks[i].fx.start(0);
		
		if (obj.blocks[n])
			obj.blocks[n].fx.start(1);
		
		obj.index = n;
		obj.slidetimer = this.slideshowStep.delay( obj.delay, this, obj );
		

		for (var j=0; j<obj.buttons.length; j++)
		{
			obj.buttons[j].removeClass('slideshow-btn-selected');
		}
		obj.buttons[n].addClass('slideshow-btn-selected');
	},
	
	slideshowStop: function( obj )
	{
		if (obj.slidetimer)
			$clear( obj.slidetimer );
	},
	
	menus: function( objs )
	{
		objs.each( this.menu.bind(this) );
	},
	
	menu: function( obj, i )
	{
		//obj.index = 0; // first element
		obj.menu = obj.getElement('ul');
		obj.items = obj.menu.getChildren();
		obj.submenu = new Element('div', {'class': 'submenu-box'} ).inject( obj, 'after');
		obj.submenus = []
		
		obj.tail = new Element('div', {'class': 'menu-tail'} ).inject( obj, 'after' );//.inject( $$('body')[0], 'top');
		obj.tail.fx = new Fx.Morph( obj.tail, {'link': 'cancel'} ).set( {'opacity': 0/*, 'left': obj.menu.getPosition().x, 'top': obj.menu.getPosition().y*/} );
		
		/*obj.getParent().addEvents( {
			'mouseleave': this.menuOver.pass([obj, null], this)
		} );*/
		
		for (var k=0; k<obj.items.length; k++)
		{
			var item = obj.items[k];
			var link = item.getElement('a');
			var submenu = item.getElement('ul');
			
			obj.submenus[k] = new Element('div', {'class': 'submenu'} ).inject( obj.submenu );
			obj.submenus[k].fx = new Fx.Tween( obj.submenus[k], {'property': 'opacity', 'link': 'cancel'} ).set(0);
			if (submenu)
			{
				var subitems = submenu.getElements('li');
				var sublinks = submenu.getElements('li a');
				var subtotal = subitems.length;
				if (submenu.getElement('.menu-maserati'))
					subtotal++;
				submenu.inject( obj.submenus[k] );
				subitems.setStyle('width', parseInt(100/subtotal) + '%');
				if (submenu.getElement('.menu-maserati'))
					submenu.getElement('.menu-maserati').getParent('li').setStyle('width', (parseInt(100/subtotal)*2) + '%');
				
				for (var j=0; j<sublinks.length; j++)
				{
					sublinks[j].addEvent('loaded', function(obj, k, j) {
						this.menuSubSelected( obj, k, j );
						this.menuSelected( obj, k );
					}.pass([obj,k,j], this) );
				}
				
				obj.submenus[k].subitems = subitems;
				obj.submenus[k].sublinks = sublinks;
			}
			link.addEvent('loaded', function(obj, k) {
				this.menuSelected( obj, k );
				if (obj.items[k].hasClass('menu-select-first'))
				{
					this.menuSubSelected( obj, k, 0 );
				}
			}.pass([obj, k], this) );
			
			item.addEvents( {
				'click': this.menuOver.pass([obj, k], this)
				//'mouseenter': this.menuOver.pass([obj, k], this)
			} );
			
			if (obj.items[k].hasClass('menu-selected'))
				obj.index = k;
		}
		if (obj.index != null)
		{
			this.menuOver( obj, obj.index );
		}
		
		window.addEvent('resize', this.menuOver.pass( [obj, null], this ) );
	},
	
	menuOver: function( obj, k )
	{
		if (k == null)
			k = obj.index;
		for (var j=0; j<obj.items.length; j++)
		{
			obj.submenus[j].fx.start( (j == k) ? 1 : 0 );
		}
		var menu = obj.menu.getCoordinates();
		if (obj.items[k])
		{
			var coord = obj.items[k].getElement('a').getCoordinates();
			obj.tail.fx.start( {
				'opacity': 1,
				'width': coord.width,
				'left': coord.left - menu.left
			} );
		}
	},
	
	menuSelected: function( obj, k )
	{
		obj.index = k;
		this.menuOver( obj, k );
		
		obj.items.removeClass('menu-selected');
		obj.items[k].addClass('menu-selected');
	},
	
	menuSubSelected: function( obj, k, j )
	{
		for (var f=0; f<obj.submenus.length; f++)
			if (obj.submenus[f].subitems)
				obj.submenus[f].subitems.removeClass('submenu-selected');
		obj.submenus[k].subitems[j].addClass('submenu-selected');
	},
	
	multiloads: function( objs )
	{
		objs.each( this.multiload.bind(this) );
	},
	
	multiload: function( obj, i )
	{
		obj.importOptions();
		
		obj.target = $(obj.options.trg);
		obj.target.fx = new Fx.Morph( obj.target, {'link': 'chain'} );
		obj.tmp = new Element('div').setStyles( { 'position': 'absolute', 'left': -99999 } ).inject( $$('body')[0], 'top' ); // temp div for calculate new content size
		obj.spinner = new Element('div', {'class': 'loading', 'html': '<span></span>'} ).inject( $$('body')[0], 'top' ); // placeholder for loading
		obj.spinner.fx = new Fx.Morph( obj.spinner, {'link': 'cancel'} ).set( {'opacity': 0} );
		
		obj.links = obj.getElements( obj.options.elements );
		
		for (var k=0; k<obj.links.length; k++)
		{
			obj.links[k].key = obj.links[k].get('name');
			
			obj.links[k].addEvent('click', function( obj, k ) {
				
				this.loadContent( obj, k );
				
				return false;
			}.pass([obj,k], this));
			
			// attach history
			obj.hkey = obj.options.key; // 'go';
			obj.history = this.history.register(
				obj.hkey,
				[null],
				function(args) {
					//console.log(args, obj);
					if (args[0] == null) return;
					if (obj.current != args[0])
					{
						//console.log( 'current: ' + obj.current + ', to load: '+args[0] );
						for (var k=0; k<obj.links.length; k++)
						{
							if (obj.links[k].key == args[0]) args[0] = k;
						}
						this.loadContent( obj, args[0] );
					}
				}.bind(this),
				function(args) { return obj.hkey + ':' + args[0]; }.bind(this),
				obj.hkey + ':(\\w+)' // + ':([\\w_-]*)' //
			);
		}
	},
	
	loadContent: function( obj, k )
	{
		var coord = obj.target.getCoordinates();
		
		obj.xhr = new Request( { 'url': obj.links[k].getAjaxUrl() } );
		obj.xhr.addEvent('onComplete', this.putContent.pass([obj, k], this) );
		
		// init spinner
		obj.spinner.setStyles( { 'width': coord.width, 'left': coord.left, 'top': coord.top } );
		obj.spinner.setStyle( 'height', document.getSize().y ); // hack for force scrolling
		
		// take off old text
		obj.target.fx.start( {'opacity': 0} ).chain( function() {
			// put loading spinner
			obj.spinner.fx.start( {'opacity': 1, 'margin-top': 50 } );
			
			obj.xhr.send();
			
		}.bind(this) );
		
		if (obj.history)
			obj.history.setValue( 0, obj.links[k].key );
	},
	
	putContent: function( obj, k )
	{
		obj.tmp.set('html', obj.xhr.response.text);
		this.fireEvent('content', obj.tmp); // parse it now for calculation
		var h = obj.tmp.getSize().y;
		
		if (obj.tmp.get('html').length == 0)
		{
			// home: change background
			$$('body')[0].addClass('page-home');
		}
		else
		{
			$$('body')[0].removeClass('page-home');
		}
		if (obj.tmp.getElements('.type-maserati').length > 0)
		{
			// maserati!
			$$('body')[0].addClass('page-cycles maserati');
		}
		else
		{
			$$('body')[0].removeClass('page-cycles maserati');
		}
		document.title = 'Milani Cycles Factory - ' + obj.links[k].get('text');
		
		obj.target.setStyles( {'overflow': 'hidden'} );
		
		// fill with loaded (and parsed) data
		obj.target.empty();
		obj.tmp.getChildren().inject( obj.target, 'bottom' );
		obj.target.fx.start( {'opacity': 1, 'height': h} ).chain( function() {
			// re-hide loading
			obj.spinner.fx.start( {'opacity': 0, 'margin-top': 0 } );
			
			obj.target.setStyles( {'height': 'auto'} );
		} );
		
		obj.current = obj.links[k].key;
		obj.links[k].fireEvent('loaded');
		
		try {
			_gaq.push( ['_trackPageview', _trackPageview( obj.links[k].getAjaxUrl() ) ] );
		} catch (err) {
		}
	},
	
	tabs: function( objs )
	{
		objs.each( this.tab.bind(this) );
	},
	
	tab: function( obj, i )
	{
		obj.importOptions();
		obj.tabbox = obj.getElement(obj.options.tabbox);
		obj.titles = obj.getElements( obj.options.titles );
		obj.blocks = obj.getElements( obj.options.blocks );
		
		var screen_width = obj.blocks[0].getSize().x;
		var width = 0;
		obj.pos = []
		for (var k=0; k<obj.blocks.length; k++)
		{
			obj.pos[k] = width;
			width += obj.blocks[k].getSize().x
		}
		
		obj.tabs = []
		obj.tabcont = new Element('ul').inject( obj.tabbox );
		obj.blockbox = new Element('div').setStyles( {'overflow': 'hidden', 'width': screen_width} ).inject( obj.blocks[0], 'before');
		obj.blockcont = new Element('div').setStyles( {'width': width } ).inject( obj.blockbox );
		obj.fx = new Fx.Tween( obj.blockcont, {'property': 'margin-left', 'link': 'cancel', 'duration': 500, 'fps': 50} ); // , 'transition': Fx.Transitions.Back.easeOut
		for (var k=0; k<obj.titles.length; k++)
		{
			obj.tabs[k] = new Element('li', {'html': '<a href="javascript:;">' + obj.titles[k].get('html') + '</a>'} ).inject( obj.tabcont );
			
			obj.titles[k].dispose();
			obj.tabs[k].addEvent('click', function(obj, k) {
				this.tabOpen( obj, k );
			}.pass([obj,k], this) );
			
			obj.blocks[k].setStyles( { 'float': 'left', 'width': screen_width } ).inject( obj.blockcont );
			obj.blocks[k].fx = new Fx.Tween( obj.blocks[k], {'property': 'opacity', 'link': 'cancel', 'duration': 200 } ).set(0);
		}
		this.tabOpen(obj, 0);
	},
	
	tabOpen: function( obj, k )
	{
		for (var j=0; j<obj.tabs.length; j++)
			obj.tabs[j].removeClass('tab-selected');
		obj.tabs[k].addClass('tab-selected');
		
		//obj.fx.start( -obj.pos[k] );
		
		obj.blocks[ obj.index || 0 ].fx.start(0).chain( function() {
			obj.fx.set( -obj.pos[k] );
			obj.blocks[k].fx.start(1);
		} );	
		
		obj.index = k;
	},
	
	scrolls: function( objs, here )
	{
		if (!this.scroller)
		{
			this.scroller = new Fx.Scroll( document, {
			    wheelStops: false
			} );
		}
		if (here)
			this.scroller.toElement( here );
		
		objs.each( this.scroll.bind(this) );
	},
	
	scroll: function( obj, i )
	{
		obj.importOptions();
		obj.links = obj.getElements( obj.options.elements );
		for (var i=0; i<obj.links.length; i++)
		{
			obj.links[i].addEvent('click', this.scrollTo.bindWithEvent(this, [obj, i]) );
		}
	},
	
	scrollTo: function( event, obj, i )
	{
		var el = obj.links[i];
		if (obj.options.trg)
			f = obj.options.trg;
		else
		{
			var h = el.get('href');
			var x = h.indexOf(h, '#');
			var f = h.substr( x+1, h.length - x );
			event.preventDefault();
		}
		this.scroller.toElement( $(f) );
	},
	
	addThis: function( objs )
	{
		if (objs.length > 0)
		{
			objs.each( function(el) {
				if (typeof addthis != 'undefined')
					addthis.button(el, {}, {url: el.get('href'), title: el.get('text') } );
			});
		}
	}
});

/**** NATIVE IMPLEMENTATIONs ***/
Element.implement( {
	importOptions: function()
	{
		this.saveOptions( this, this );
	},
	
	copyOptions: function( obj )
	{
		this.saveOptions( obj, this );
	},
	
	saveOptions: function( source, target )
	{
		var trigger = "logics@";
		if (!target.options)
			target.options = {}
		if (source.className.indexOf(trigger) !== -1)
		{
			// import rel settings
			var logics = source.className.substring( source.className.indexOf(trigger) + trigger.length );
			var parts = logics.split('|');
			for (var j=0; j<parts.length; j++)
			{
				kv = parts[j].split(':');
				if (kv.length == 2)
				{
					eval("target.options."+kv[0]+" = '"+kv[1]+"'");
				}
			}
		}
	},
	
	getAjaxUrl: function( )
	{
		if (this.get('rel'))
			return this.get('rel');
		var href = this.href;
		if (href.indexOf('?') !== -1)
			href += '&';
		else
			href += '?';
		href += 'client=xhr';
		return href;
	}
} );
