/**
 * mLoad
 * An ajax page loader (proof of conecpt)
 * by Moquan Chen <mc@newzoo.no>
 *
 * License:
 * http://creativecommons.org/licenses/by/3.0/
 *
 * Tested in:
 * - Firefox 2
 * - Firefox 3
 * - Safari 3
 * - Opera 9.5
 */
var mLoad = new Class({

	Implements : [Options],

	options : {
		keyClass :		'mLoad',
		base :			'/labs/mLoad/',
		query :			{},
		fetchURI :		'/labs/mLoad/fetch.php?page=',
		fragmentPrefix :	'/',
		markedClass :		'marked',
		refreshInterval :	1000,
		failureMessage :	'Request failed. Redirecting...',
		loadingMessage :	'<p>Loading ... <br /><a href={href}>Manual load</a></p>',
		scrollToTop :		true
	},
	currentFragment : '',
	defaultFragment : '',
	fragmentChangeActive : true,
	
	// constructor
	initialize : function(currentPage,options) {
	
		this.setOptions(options);
		
		this.currentFragment = this.options.fragmentPrefix + currentPage;
		this.defaultFragment = this.currentFragment;
		
		if(this.isDirectFragmentRequest()) {
			this.autoLoad(this.findFragment());
		}
		
		this.registerFragmentChangeAutoLoad();
		
		this.registerEvents();
		
	},
	
	// find fragment
	findFragment : function() {
		var frag = window.location.hash.substring(1+this.options.fragmentPrefix.length);
		if(this.defaultFragment.length > 0 && frag.length == 0) {
			return this.defaultFragment.substring(this.options.fragmentPrefix.length);
		}
		else {
			return frag;
		}
	},
	
	// remove base from uri
	removeBase : function(uri) {
		return uri.substring(this.options.base.length);
	},
	
	// is it a direct request
	isDirectFragmentRequest : function() {
		var frag = this.findFragment();
		return frag.length > 0 && frag != this.defaultFragment.substring(
			this.options.fragmentPrefix.length);
	},
	
	// if the user manually changed the fragment
	registerFragmentChangeAutoLoad : function() {
		var temp = this;
		var fragmentChange = window.setInterval(function() {
			var fragment = temp.options.fragmentPrefix + temp.findFragment();
// 			if(temp.currentFragment != fragment) {
			if(temp.fragmentChanged() && temp.fragmentChangeActive) {
				temp.autoLoad(fragment.substring(temp.options.fragmentPrefix.length));
			}
		},this.options.refreshInterval);
	},
	
	// has the fragement changed?
	fragmentChanged : function() {
		var fragment = this.options.fragmentPrefix + this.findFragment();
		return (this.currentFragment != fragment);
	},
	
	
	// register events for all mload elements
	registerEvents : function() {
		var temp = this;
		$$('.'+this.options.keyClass).each(function(item,index) {
			item.addEvent('click',function(e) {
				if(temp.scrollToTop) {
					window.scroll(0,0);
				}
				e = new Event(e).stop();
				var destination = item.get('rel');
				if($(destination) != null) {
					$(destination).set('text','');
					// load the page
					temp.loadPage(item.get('href'),item.get('rel'));
					// remvoe the marked class from the rest
					$$('.'+temp.options.keyClass).each(function(otherItem,otherIndex) {
						otherItem.removeClass(temp.options.markedClass);
					});
					item.addClass(temp.options.markedClass);
				}
				else {
					window.location = item.href;
				}
			});
		});
	},
	
	// autoload a fragment
	autoLoad : function(fragment) {
		this.fragmentChangeActive = false;
		var href = this.options.base + fragment;
		var dest = '';
		// find all elements with an href attribute matching this and contains class mload
		// remove the marked class
		var markedClass = this.options.markedClass;
		$$('.'+this.options.keyClass).each(function(item,index) {
			item.removeClass(markedClass);
		});
		// add the marked class
		$$('.'+this.options.keyClass).each(function(item,index) {
			if(item.get('href') == href) {
				item.addClass(markedClass);
				dest = item.get('rel');
			}
		});
		this.loadPage(href,dest);
		
		this.fragmentChangeActive = true;
	},
	
	// load a page
	loadPage : function(href,destination) {
	
		if(destination == null || destination.length == 0 || $(destination) == null) {
			// no destination
			return;
		}
		
		// modification for fintan's site
// 		$(destination).set('tween',{duration : 500});
		
		var temp = this;
		
		var req = new Request.HTML({
			url : this.options.fetchURI + this.removeBase(href),
			method : 'get',
			onRequest : function() {
				/*$(destination).adopt(temp.options.loadingMessage.replace(
							'/{href}/g',href));*/
				$(destination).set('text','');
				$(destination).set('html',temp.options.loadingMessage.replace(
							'{href}',href));
			},
			onSuccess : function(html) {
				
				// modification for fintant's site
// 				$(destination).setStyle('opacity',0);
				
				$(destination).set('text','');
				$(destination).adopt(html);
				temp.currentFragment = temp.options.fragmentPrefix + temp.removeBase(href);
				window.location = '#' + temp.currentFragment;
				
				// modification for fintan's site
// 				$(destination).tween('opacity',1);
			},
			onFailure : function() {
				$(destination).set('text',this.options.failureMessage);
				window.location = href;
			}
		}).get(this.options.query);
		req.send();
		
		
	}
});


var fintan = new Class({
	
	Implements : [Options],
	
	options : new Hash({
		imageMenuId : 'imageMenu',
		hiddenClass : 'hidden',
		menuId : 'menu',
		markedClass : 'marked',
// 		loadingMessage :'<p>Requesting image...<br />'+
// 					'<a href="{href}">View image manually</a></p>',
		loadingMessage : '',
		imageMenuKeyClass : 'imageLoad',
		mainImageId : 'mainImage',
		disableAjax : false
	}),
	firstImage : null,
	base : null,
	imageLoader : null,
	imageMenuItems : new Array(),
	
	initialize : function(base,firstImage,options) {
		this.base = base;
		this.firstImage = (firstImage != null) ? firstImage : this.findFirstImage();
		this.setOptions(options);
		if(!this.options.disableAjax) {
			this.loadImageLoader();
			this.loadImageMenuAnimation();
			this.imageMenuMarker().periodical(this.imageLoader.options.refreshInterval);
		}
// 		this.preloadImages(); // not working since p2 integration
		this.loadMainMenuCatSlide();
		this.loadMainMenuSlide();
// 		this.imageTransition();
	},
	
	
	/**
	 * Find the image with both markedClass and imageMenuKeyClass
	 * that is the first image.
	 *
	 * @return string	The first image's href after it has been trimmed.
	 */
	findFirstImage : function() {
		var out = '';
		var point = this;
		$$('.'+this.options.markedClass).each(function(item,index) {
			if(item.hasClass(point.options.imageMenuKeyClass)) {
				out = item.get('href').substring(point.base.length);
			}
		});
		return out;
	},
	
	/**
	* Image menu ajax.
	*/
	loadImageLoader : function() {
		/*var base = window.location.pathname.split('/');
		delete base[base.length-1];
		base = base.join('/');
		*/
		var base = this.base;
		
		this.imageLoader = new mLoad(this.firstImage,{
			base : base,
			fetchURI : base,
			query : {'ajax' : ''},
			loadingMessage : this.options.loadingMessage,
			markedClass : this.options.markedClass,
			scrollToTop : false,
			keyClass : this.options.imageMenuKeyClass
		});
/*
		if(window.location.hostname == 'localhost') {
			this.imageLoader = new mLoad('Vilnius_Lithuania_01.jpg',{
				base : '/projects/fintan/v1/',
				fetchURI : '/projects/fintan/v1/fetch.php?image=',
				loadingMessage : this.options.loadingMessage,
				markedClass : this.options.markedClass,
				scrollToTop : false,
				keyClass : this.options.imageMenuKeyClass
			});
		}
		else {
			this.imageLoader = new mLoad('Vilnius_Lithuania_01.jpg',{
				base : '/',
				fetchURI : '/fetch.php?image=',
				loadingMessage : this.options.loadingMessage,
				markedClass : this.options.markedClass,
				scrollToTop : false,
				keyClass : this.options.imageMenuKeyClass
			});
		}*/
	},
	
	/**
	 * Transition animation.
	 * Make it slide out and in when clicking a new image.
	 */
	imageTransition : function() {
		var point = this;
		$(this.options.mainImageId).set('tween',{duration : 700});
// 		var orgWidth = $(this.options.mainImageId).getElement('img').getSize().x;

// 		var width = Math.floor((document.body.offsetWidth - 76) * 0.7);

		$$('.'+this.options.imageMenuKeyClass).each(function(item,index) {
			item.addEvent('click',function(e) {
				$(point.options.mainImageId).setStyle('opacity',0);
				$(point.options.mainImageId).tween('opacity',1);
			});
		});
	},
	
	/**
	 * Image menu highlighter.
	 * Highlight the image in image menu that is active.
	 */
	imageMenuMarker : function() {
		var temp = this;
		var t = function() {
			if(temp.imageLoader.fragmentChanged()) {
				// go through the image menu and remove marked from the others
				temp.imageMenuItems.each(function(item,index) {
					var anchor = item.getElement('a');
// 					if(temp.imageLoader.removeBase(anchor.href)
// 					var b = 'http://'+window.location.hostname+temp.imageLoader.options.base;
					var b = temp.imageLoader.options.base;
					var a = temp.imageLoader.options.fragmentPrefix+
						anchor.get('href').substring(b.length);
					if(a == temp.imageLoader.currentFragment) {
						anchor.tween('opacity',0.5);
// 						alert(temp.imageLoader.removeBase(anchor.href));
					}
					else if(a == temp.imageLoader.options.fragmentPrefix+
					temp.imageLoader.findFragment()) {
						anchor.tween('opacity',1);
					}
				});
			}
		}
		return t;
	},
	
	
	/**
	 * Animation on the image menu.
	 */
	loadImageMenuAnimation : function() {
		var imageMenu = $(this.options.imageMenuId);
		if(imageMenu == null) {
			return;
		}
		this.imageMenuItems = imageMenu.getElement('ul').getElements('li');
		var temp = this;
		this.imageMenuItems.each(function(item,index) {
			var anchor = item.getElement('a');
			if(!item.hasClass(temp.options.hiddenClass)) {
				anchor.set('tween',{duration: 500});
				anchor.addEvents({
					mouseenter : function(e) {
						e.stop();
						anchor.tween('opacity',1);
					},
					mouseleave : function(e) {
						e.stop();
						if(!anchor.hasClass(temp.options.markedClass)) {
							anchor.tween('opacity',0.5);
						}
					},
					click : function(e) {
						e.stop();
						// remove marked class from the others
// 						temp.imageMenuItems.each(function(oItem.oIndex) {
// 						[',',1,2].each(function(oItem,oIndex) {
						(temp.imageMenuItems).each(function(oItem,oIndex) {
							var oAnchor = oItem.getElement('a');
							if(oAnchor.href != anchor.href) {
								oAnchor.removeClass(temp.options.markedClass);
								oAnchor.tween('opacity',0.5);
							}
						});
						anchor.addClass(temp.options.markedClass);
					}
				});
			}
		});
	},
	
	
	/**
	 * Preload the images.
	 */
	preloadImages : function() {
		var images = new Array();
		var i = 0;
		var temp = this;
		$(this.options.imageMenuId).getElement('ul').getElements('li').each(function(item,index) {
			var anchor = item.getElement('a');
			if(!item.hasClass(temp.options.hiddenClass)) {
				images[i++] = anchor.href;
			}
		});
		new Asset.images(images);
	},
	
	
	
	/**
	 * Slides the menu's submenus in and out.
	 */
	loadMainMenuCatSlide : function() {
		
		var sliders = new Array();
		var anchors = new Array();
		var i = 0;
		
		$$('li.column').each(function(item,index) {
			if(item.getElement('ul') != null) {
				sliders[i] = new Fx.Slide(item.getElement('ul'),{
						duration : 700,
						transition : Fx.Transitions.Quad.easeOut
						});
				if(!item.getElement('ul').hasClass('open')) {
					sliders[i].hide();
				}
				anchors[i] = item.getElement('strong').getElement('a');
				i++;
			}
		});
		
		sliders.each(function(slider,index) {
			anchors[index].addEvent('click',function(e) {
				e.preventDefault();
				slider.toggle();
				
				// close the others
				sliders.each(function(oSlider,oIndex) {
					if(oSlider.open && oIndex != index) {
						oSlider.slideOut();
					}
				});
			});
		});
		
	},
	
	/**
	 * Main menu slide.
	 */
	loadMainMenuSlide : function() {
		var sliders = new Array();
		var anchors = new Array();
		var containers = new Array();
		var i = 0;
		$(this.options.menuId).getElement('ul').getElements('li').each(function(item,index) {
			var secondLevel = item.getElement('ul');
			if(secondLevel != null) {
				secondLevel.getElements('li').each(function(secondItem,secondIndex) {
					// if this item contains another ul
					if(secondItem.getElement('ul') != null) {
						sliders[i] = new Fx.Slide(secondItem.getElement('ul'),{
							duration : 500,
							transition : Fx.Transitions.Quad.easeOut
						});
						anchors[i] = secondItem.getElement('a');
						containers[i] = secondItem.getElement('ul');
						
						++i;
					}
				});
			}
		});
		
		sliders.each(function(slider,index) {
			
			// do not hide if the 'ul' has class 'open'
			if(!containers[index].hasClass('open')) {
				slider.hide();
			}
			
			anchors[index].addEvent('click',function(e) {
				e.preventDefault();
				e.stop();
				slider.toggle();
				
				// close the others
				sliders.each(function(oSlider,oIndex) {
					if(oSlider.open && oIndex != index) {
						oSlider.slideOut();
					}
				});
			});
		});
	}
});



/**
	* Image menu, no ajax.
	*
	* Slow, it load the image before it shows the image in mainImage.
	*/
/*$('imageMenu').getElement('ul').getElements('li').each(function(item,index) {
	var anchor = item.getElement('a');
	var mainImage = $('mainImage').getElement('img');
	if(!item.hasClass('hidden')) {
		anchor.addEvent('click',function(e) {
			e = new Event(e).preventDefault();
			mainImage.setStyle('visibility','hidden');
			mainImage.set('src',anchor.href);
			mainImage.setStyle('visibility','visible');
		});
	}
});*/
