/*
 * Launch User Interface Animation Library
 *
 */
var LAUNCH = {};
LAUNCH.Version = '1.0';
LAUNCH.CompatibleWithPrototype = '1.6';

if (Prototype.Version.indexOf(LAUNCH.CompatibleWithPrototype) !== 0 && console && console.warn)
  console.warn("This version of LAUNCH javascript library is tested with Prototype " + LAUNCH.CompatibleWithPrototype + 
                  " it may not work as expected with this version (" + Prototype.Version + ")");

LAUNCH.Config = {};
LAUNCH.Config.APIurl = "/api/ajax.php";
LAUNCH.Config.LoaderSrc = "/images/ajax_loader_grey.gif";
LAUNCH.Config.ActionFigure = {};
LAUNCH.Config.ActionFigure.RefreshInterval = 25;

// function because vars can be set later on (style.js) assigned later
LAUNCH.Config.behaviourRules = function(){
	output = new Array();
	output[0] = hyperlink_rules;
	output[1] = google_maps_rules;
	return output;
}

LAUNCH.Config.pages = {};

if(location.hostname == "launch.staging.mangrove.nl"){
	LAUNCH.Config.pages.business = 2;
	LAUNCH.Config.pages.sap = 3;
	LAUNCH.Config.pages.training = 29;
	LAUNCH.Config.pages.legal = 30;
} else {
	LAUNCH.Config.pages.business = 3;
	LAUNCH.Config.pages.sap = 9;
	LAUNCH.Config.pages.training = 31;
	LAUNCH.Config.pages.legal = 29;
}

/**
 * Effect.js extension
 * doing nothing, usefull when some logic needs to be done after an animation is finished
 * just queue a Nothing Effect and use its afterFinish function
 */

Effect.Nothing = Class.create(Effect.Base, {
  initialize: function() {
    this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
  },
  update: Prototype.emptyFunction
});


/*
 * Header image transitions
 * 1. background image fade in
 * 2. logo,introtext and menu fade in
 * 3. action figure walk in
 */
LAUNCH.Header = {};

LAUNCH.Header.HeaderImage = Class.create({
	/**
	 * Initializer
	 * sets pointers to each object used in animation
	 * quick hides everything and start animation
	 * @param Element element to apply header class on
	 * @param Object options
	 */
	initialize: function(element, options){
		this.element = $(element);
		this.options = {};
		
		// setting pointers
		this.headerIntro = $('header-intro');
		this.headerFigure = $('header-figure');
		this.headerImage = $('header-image');
		//this.headerImageQuote = $('header-image-quote');
		this.headerImageDetails = $('header-image-details');
		
		// if we should transform on page load, skip the header fade in
		if(History.hash.get('pageID')){
			// build actionfigure to do its continues refresh loop
			var actionFigure = new LAUNCH.Header.ActionFigure(this.headerImage);
		} else {
			// hide everything, showed by css in case javascript is disabled
			this.element.setOpacity(0);
			this.headerIntro.setOpacity(0);
			this.headerImage.setOpacity(0);
			//this.headerImageQuote.hide();
			this.headerImageDetails.setOpacity(0);
			
			// set initial position walking figure
			this.headerFigure.setStyle({
					'left': '50px',
					'top': '50px'
				});
			
			
			// build actionfigure to do its continues refresh loop
			var actionFigure = new LAUNCH.Header.ActionFigure(this.headerImage);
			
			// start animation to show header
			this.showHeader();
		}
		
	},
	/**
	 * Header animation
	 */
	showHeader: function(){
		// fade in background image
		new Effect.Appear(this.element, {
			duration: 1.2,
			to: 1.0,
			queue:{
				position: 'end',
				scope: 'initialHeader'
			}
		});
		// fade in logo, introtext and menu
		new Effect.Appear(this.headerIntro, {
			duration: 0.8,
			queue:{
				position: 'end',
				scope: 'initialHeader'
			}
		});
		// figure walk in
		new Effect.Parallel([
  			new Effect.Appear(this.headerImage, { 
				to: 1.0,
				sync: true
			}), 
  			new Effect.Morph(this.headerFigure, { 
				style: {
    				'left': '0px',
					'top': '0px'
  				},
				sync: true,
				scaleContent: true
			}) 
		], {
			duration: 1,
			queue:{
				position: 'end',
				scope: 'initialHeader'
			}
		});
		// roll open quote
//		new Effect.BlindDown(this.headerImageQuote, {
//			duration: 0.5,
//			scaleX: true,
//			scaleContent: true,
//			queue:{
//				position: 'end',
//				scope: 'initialHeader'
//			}
//		});
		// fade in name and function block
		new Effect.Appear(this.headerImageDetails, {
			duration: 0.5,
			queue:{
				position: 'end',
				scope: 'initialHeader'
			}
		});
	}
});

/**
 * ActionFigure
 * retrieves a new actionfigure from server and controls animation to replace the old one with the new one
 * - (public)initialize: initiates full process
 * - (private) getNewFigure: makes ajax call to get new figure
 * - (private) replaceFigure: animates the replacement
 */
LAUNCH.Header.ActionFigure = Class.create({
	
	/*
	 * Initialize
	 * starts continues refresh loop for actionfigure change
	 */
	initialize: function(element){
		LAUNCH.Header.ActionFigure.modDuration = 1;
		this.element = $$('.header-image')[0];
		new PeriodicalExecuter(function(){
			this.getNewFigure();
		}.bind(this), LAUNCH.Config.ActionFigure.RefreshInterval);
	},
	/*
	 * gets new actionfigure
	 */
	getNewFigure: function(){
		if(LAUNCH.Header.ActionFigure.modDuration == 1){
			var thisdate = new Date();
			new Ajax.Request(LAUNCH.Config.APIurl+'?action=getActionfigure&ran='+ thisdate.getTime(), {
				method: 'get',
				onSuccess: function(transport) {
					this.replaceFigure(transport);
				}.bind(this)
			});
		}
	},
	/*
	 * Animation for actionfigure change
	 * 1. fade out old figure
	 * 2. change
	 * 3. fade in new figure
	 */
	replaceFigure: function(transport){
		
		this.HeaderImage = $$('.header-image')[0];
		
		// fade out
		new Effect.Fade(this.HeaderImage, {
			duration: LAUNCH.Header.ActionFigure.modDuration * 1,
			queue:{
				position: 'end',
				scope: 'actionFigure'
			},
			afterFinish: function(newHeaderImage){
				// change figure
				$$('.header-image')[0].replace(transport.responseText);
				headerImage = $$('.header-image')[0];
				headerImage.setOpacity(0);
				// fade in
				new Effect.Appear(headerImage, {
					duration: LAUNCH.Header.ActionFigure.modDuration * 1,
					queue:{
						position: 'end',
						scope: 'actionFigure'
					},
					afterFinish: function(el){
						//LAUNCH.Header.ActionFigure.modDuration = 1;
					}
				});
			}	
		});
	}
});



/**
 * Parts
 * Class containing several minor parts involved with animation
 */
LAUNCH.Parts = {};

/**
 * Submenu class
 * retrieves and animates the sub- and subsubmenu
 */
LAUNCH.Parts.Submenu = Class.create({
	/**
	 * Initialize
	 * 
	 * @param Element element
	 * @param Array options
	 */
	initialize: function(element, namespace){
		// element where this class is applied to
		this.element = $(element);
		
		// hide the element
		this.element.hide();
		this.showAnimated();
		this.newHTML = '';
		
		//because we can have both submenu or subsubmenu (would not be needed if IE would fire events from javascript generated elements)
		this.namespace = namespace;
	},
	/**
	 * animate the submenu to show its contents
	 * @type void
	 */
	showAnimated: function(){
		if(!this.element.empty()){
			/*new Effect.BlindDown(this.element, {
				duration:0.2,
				queue:{
					position: 'end',
					scope: 'blockScope'
				}
			});
			*/
		}
	},
	/**
	 * ajax request to get the html for the menu
	 * @param {Integer} pageID
	 */
	 // ???
	getNewHTML: function(pageID){
		action = (this.namespace == 'submenu')?'getSubmenu':'getSubsubmenu';
		new Ajax.Request(LAUNCH.Config.APIurl+'?action='+action+'&pageID=' + pageID, {
			method: 'get',
			onSuccess: function(transport) {
				this.newHTML = transport.responseText;
				
				//element fired from the document, because IE is unable to fire events from javascript generated elements
				document.fire(this.namespace+':updated');
			}.bind(this)
		});
	},
	/**
	 * insert the new html into the element
	 */
	update: function(){
		this.element.update(this.newHTML);
		this.element.insert({'bottom': new Element('div', {'class' : 'clear'})});
	},
	/**
	 * Animate the submenu hide action
	 */
	hideAnimated: function(){
		new Effect.BlindUp(this.element, {
			duration:0.2,
			queue:{
				position: 'end',
				scope: 'blockScope'
			}
		});
	}
});


/**
 * LabelBox class
 * Animates the displayal of the department boxes on the left and right side on the page
 * - initialize: set initial state: builds LabelBox DOM, attach hover events
 * - applyLabelActions: attach hover events
 * - removeLabelActions: detach hover events
 * - buildPart: builds LabelBox DOM based on link hash containing the configuration
 * - showAnimated: animation to show the labelBox: makes a fold, sticks any label through it
 * - hideAnimated: animation to hide the LabelBox: pulls back the labels and clears the fold
 * - hide: hard hide function ??? used?
 */
LAUNCH.Parts.LabelBox = Class.create({
	/**
	 * Initialize
	 * set initial state: builds LabelBox DOM, attach hover events
	 */
	initialize: function(element, options){
		this.options = {};// options reset
		
		// if element applied to is not set
		if( element == null){
			this.buildPart([{'classn': 'business', 'page': LAUNCH.Config.pages.business}, {'classn': 'sap', 'page': LAUNCH.Config.pages.sap}]);
		}else{
			this.element = $(element);
		}
		this.applyLabelActions();
	},
	/**
	 * Add the hoverstates for the labels
	 */
	applyLabelActions: function(){
		this.element.select('a').each(function(e){
			Event.observe(e, 'mouseover', function(){
				new Effect.Morph(e, {
				style: 'width:189px;',
				duration:0.1
				});
			});
			Event.observe(e, 'mouseout', function(){
				new Effect.Morph(e, {
				style: 'width:180px;',
				duration:0.1
				});
			});
		});
	},
	/**
	 * stop observing hover states ( used during transitions)
	 */
	removeLabelActions: function(){
		this.element.select('a').each(function(e){
			Event.stopObserving(e, 'mouseover');
			Event.stopObserving(e, 'mouseout');
		});
	},
	/**
	 * build the labels, using a hash with link information
	 * @param {Object} links
	 */
	buildPart: function(links, template){
		this.element.remove();
		this.element = null;
		// root
		var box = new Element('div', {'class' : 'label-box'});
		// vertical line
		var fold = new Element('div', {'class' : 'label-box-fold', 'style': 'display:none'});
		box.insert(fold);
		
		// construct each department label
		links.each(function(e){
			classname = e.classn + ((e.classn === template)? ' active': '');
			var link = new Element('a', {'href': '?pageID=' + e.page, 'rel': e.classn,  'class': classname, 'style': 'width:0px'});
			box.insert(link);
		});
		
		// attach to DOM
		$$('.secondary')[0].insert(box);
		
		// set pointer
		this.element = $(box);
	},
	/**
	 * show the labelbox using animation
	 */
	showAnimated: function(){
		this.element.show();
		new Effect.BlindDown(this.element.down('div'), {
			duration:0.5,
			queue:{
				position: 'end',
				scope: 'blockScope'
			}
		});
		this.element.select('a').each(function(e){
			new Effect.Morph(e, {
				style: 'width:180px;',
				duration:0.3,
				queue:{
					position: 'end',
					scope: 'blockScope'
				},
				afterFinish:function(){
					this.applyLabelActions();
					this.element.fire('labelBox:shown');
					
				}.bind(this)
			});
		}.bind(this));
	},
	/**
	 * hide the labelbox with animation 
	 */
	hideAnimated: function(){
		this.removeLabelActions();
		this.element.select('a').each(function(e){
			new Effect.Morph(e, {
				style: 'width:0px;',
				duration:0.2,
				queue:{
					position: 'end',
					scope: 'blockScope'
				}
			});
		});
		new Effect.BlindUp(this.element.down('div'), {
			duration:0.5,
			queue:{
				position: 'end',
				scope: 'blockScope'
			},
			afterFinish:function(){
				this.element.fire('labelBox:hidden');
				this.element.hide();
			}.bind(this)
		});
	},
	/**
	 * instantly hide the labelbox
	 */
	hide: function(){
		this.removeLabelAction();
		this.element.select('a').each(function(e){
			e.setStyle({
				'width': '0px'
			});
		});
		this.element.down('div').hide();
	},
	activate: function(className){
		this.element.childElements().each(function(el){
			el.removeClassName('active');
		});
		this.element.down('.'+className).addClassName('active');
	}
});

/*
 * Layout class
 * contains transformation from one template to any other
 */
LAUNCH.Layout = {};

LAUNCH.Layout.Block = 0;

/**
 * Launch Transform class
 *
 * - initialize: constructor
 * - loadHandler: on page load transforms to the requested page
 * - postContentCallback: called when animation is finished and content is retrieved
 * - postAnimationCallback: called when animation is finished but before content is loaded
 * - applyClasses: sets LAUNCH.Parts on elements already on page
 * - clickHandler: catches the anchor's clicked containing a rel attribute which we support
 * - setHistory: updates window.location to enable 'previous','next','history' and bookmarking functionality of browser
 * - updateActiveLink: sets correct highlight on menu item
 * - clearActiveLink: removes highlight from menu item
 * - pageChange: performs all template transistions
 * - retrieveSub(sub)menu: fills sub(sub)menu
 *
 * Template Switch functions
 * - refreshDepartmentPage: animates refreshment of department template
 * - globalToDepartment: animates switch from global to department template
 * - switchWhiteBlockSideTpl: animates switch between two department templates
 * - buildGlobalPage: constructs DOM for global template
 *
 * Structure functions
 * - contentCall: makes ajax call to get new content for page, when retrieved it is put in this.contentObject and calls our sync function tryContinue()
 * - tryContinue: semaphore function to synchronize between animation and several ajax calls, calls postContentCallback() when in sync
 * - finishAnimation: inserts empty effect to call postAnimationCallback()
 * - insertContent: reads server response and puts information in right location in DOM
 *
 * Helper functions
 * - addStyleBehaviours: queues an effect to apply style.js rules after completion
 * - setSecondary: positions the secondary div, containing the department labels
 * - returnShadowBox: returns html for main shadow box, it's a couple of nested div's
 * - showLoader: shows the ajax loader image
 * - hideLoader: hides ajax loader image
 */
LAUNCH.Layout.Transform = Class.create();
LAUNCH.Layout.Transform.prototype = {
	/**
	 * Constructor
	 * @currentTemplate String the template wich we start in
	 * @param Array options
	 */
	initialize: function(options){
		this.options = {};
		this.currentTemplate = $$('body')[0].identify();
		this.contentObject = {};
		this.waitForSomething = 0;
		this.waitThreshold = 1;
		this.newTemplate = '';
		this.isHistory = true;	
		this.queryParams = $H();	
		
		this.applyClasses();

		Event.observe($$('body')[0], 'click', this.clickHandler.bindAsEventListener(this));

		History.Observer.start();	
		
		History.Registry.set({
			'id':'pageID',
			'onStateChange': function(value){
				this.loadHandler(value);
			}.bind(this)
		});
		
		if(History.hash.get('pageID')){
			this.currentTemplate = $$('body')[0].identify();
			this.loadHandler(History.hash.get('pageID'));
		}
		
	},
	/**
	 * handle page load and backbutton
	 */
	loadHandler: function(value){
		
		this.isHistory = true;
		this.queryParams.set('pageID', value);
		this.queryString = History.hash.toQueryString();
		this.pageID = value;
		this.newTemplate = History.get('template');
		this.pageChange();
		this.currentTemplate = this.newTemplate;
		
		this.updateActiveLink();	
	},
	// dynamic function, will be called by tryContinue(), when all hide animations are done and all content requested retrieved.
	postContentCallback: function() {
	},
	// dynamic function, will be called by finishAnimation(), when all animations are done, before content is inserted, to construct right DOM
	postAnimationCallback: function(){
	},
	/**
	 * create classes based on elements already on page, only used at page load
	 */
	applyClasses: function(){
		//check for existance before class is applied
		var box  = $$('.label-box');
		if($$('.label-box')[0]){ this.labelBox = new LAUNCH.Parts.LabelBox($$('.label-box')[0]); }
		if($$('.submenu')[0]){ this.submenu = new LAUNCH.Parts.Submenu($$('.submenu')[0], 'submenu')}
		if($$('.subsubmenu')[0]){ this.subsubmenu = new LAUNCH.Parts.Submenu($$('.subsubmenu')[0], 'subsubmenu')}
	},
	/**
	 * this function is called when the body is clicked
	 * every link lets the click event through, so body catches it in this function
	 * this function retrieves what is actually clicked and makes the proper response
	 * @param {Event} event
	 */
	clickHandler: function(event) {
		var link = event.findElement('a');
		if(Object.isElement(link)){
			if(['sap', 'business','home','global','legal','training'].indexOf(link.readAttribute('rel')) != -1){				
				// new clicks will be blocked for now
				if(LAUNCH.Layout.Block == 0){
					LAUNCH.Layout.Block = 1;
					
					// to interrupt the action figure animation
					var queue = Effect.Queues.get('actionFigure');
					var timePos = new Date().getTime();
					// forcing future effects to 0 duration
					LAUNCH.Header.ActionFigure.modDuration = 0;
					// ending registered effects
					var i = 0;
					for(len=queue.effects.length;i<len;++i){
						queue.effects[i].finishOn = timePos;
					}
					
					this.isHistory = false;
					this.newTemplate = link.readAttribute('rel');
					this.queryParams = $H(link.readAttribute('href').toQueryParams());
					this.queryString = this.queryParams.toQueryString();
					this.pageID = this.queryParams.get('pageID') || 1;
					this.pageChange();
					this.currentTemplate = this.newTemplate;
					this.updateActiveLink();
				}
				link.blur();
				event.preventDefault();
				event.stopPropagation();	
			}
		}
	},
	/**
	 * sets the hash in the History object equal to the querystring from the clicked link
	 */
	setHistory: function(){
		//custom function in history library
		History.__previousHash = History.hash.toQueryString();
		History.hash  = this.queryParams;
		History.hash.set('template', this.currentTemplate);
		History.apply();
	},
	/**
	 * adds the class 'active' to the parent li, removes it from other list items in the list
	 * @param {Element} link
	 */
	updateActiveLink: function(){
		$$('a[href$="pageID='+this.pageID+'"]').each(function(link){
			var link = $(link);
			this.clearActiveLink(link.up(1));
			link.up().addClassName('active');	
		}.bind(this));
		$$('.label-box a.'+this.currentTemplate).each(function(link){
			var link = $(link);
			this.clearActiveLink(link.up(1));
			link.addClassName('active');	
		}.bind(this));
	},
	/** 
	 * clear the current active item from a menu
	 * @param {Element} menu
	 */
	clearActiveLink: function(menu){
		menu.select('.active').each(function(li){
			li.removeClassName('active');
		});
	},
	
	/**
	 * @description decide which transition should be used
	 */
	pageChange: function(){
		switch (this.currentTemplate + this.newTemplate) {
			case 'homehome':
				// nothing to do, no refresh of content to prevent flickering
				this.waitThreshold = 0;
				this.postContentCallback = function(){
				}
				this.postAnimationCallback = function(){
				}
				this.finishAnimation();
				break;
			case 'homeglobal':
				this.removeBanner();
				this.waitThreshold=1;
				this.contentCall();
				// setting callback function to perform after animation and content retrieval from server.
				this.postContentCallback = function(){
					this.insertContent();
					new Effect.Appear($$('.primary-content')[0],{
						duration:0.5,
						queue:{
							position:'end',
							scope: 'blockScope'
						}
					});
					this.labelBox.showAnimated();
				}
				
				// start animation
				new Effect.Parallel([
						new Effect.BlindUp($$('.content-box-business .box-content')[0], { sync: true}), 
						new Effect.BlindUp($$('.content-box-sap .box-content')[0], { sync: true}),
						new Effect.BlindUp($$('.content-box-training .box-content')[0], { sync: true}), 
						new Effect.BlindUp($$('.content-box-legal .box-content')[0], { sync: true}) 
					], { 
					duration: 0.3,
					queue:{
						position: 'end',
						scope: 'blockScope'
					}
				});
				new Effect.Parallel([
						new Effect.BlindUp($$('.content-box-business')[0], { sync: true}), 
						new Effect.BlindUp($$('.content-box-sap')[0], { sync: true}),
						new Effect.BlindUp($$('.content-box-training')[0], { sync: true}), 
						new Effect.BlindUp($$('.content-box-legal')[0], { sync: true}) 
					], { 
					duration: 0.3,
					queue:{
						position: 'end',
						scope: 'blockScope'
					}
				});

				// custom code to do on completion of animation
				this.postAnimationCallback = function(){
					var contentDiv = $$('.content')[0];
					contentDiv.update();
					this.buildGlobalPage();
					$$('.primary-content')[0].hide();	
				}
				this.finishAnimation();
			break;
			case 'homebusiness':
				this.homeToContent('business');
			break;
			case 'homesap':
				this.homeToContent('sap');
			break;
			case 'hometraining':
				this.homeToContent('training');
			break;
			case 'homelegal':
				this.homeToContent('legal');
			break;
			
			case 'globalhome':
				this.waitThreshold=1;
				// start retrieving content
				this.contentCall();
				// setting callback function to perform after animation and content retrieval from server.
				this.postContentCallback = function(){
					this.insertContent();
					
					new Effect.Parallel([
						new Effect.BlindDown($$('.content-box-business')[0], { sync: true}), 
						new Effect.BlindDown($$('.content-box-sap')[0], { sync: true}),
						new Effect.BlindDown($$('.content-box-training')[0], { sync: true}), 
						new Effect.BlindDown($$('.content-box-legal')[0], { sync: true}) 
					], { 
						duration: 0.5,
						queue:{
							position: 'end',
							scope: 'blockScope'
						},
						afterFinish: function(){
							new Effect.Parallel([
								new Effect.BlindDown($$('.box-content')[0], { sync: true}),
								new Effect.BlindDown($$('.box-content')[1], { sync: true}),
								new Effect.BlindDown($$('.box-content')[2], { sync: true}),
								new Effect.BlindDown($$('.box-content')[3], { sync: true})
							], { 
								duration: 0.3,
								queue:{
									position: 'end',
									scope: 'blockScope'
								}
							});
						}
					});
				}
				
				// start animation
				this.labelBox.hideAnimated();
				
				new Effect.Fade($$('.primary')[0],{
					duration:0.5,
					queue:{
						position:'end',
						scope: 'blockScope'
					}
				});
				
				// custom code to do on completion of animation
				this.postAnimationCallback = function(){
					var contentDiv = $$('.content')[0];
					
					contentDiv.update();
															
					var businessDiv = new Element('div', {'class': 'content-box-business'})
					businessDiv.insert({'top': this.returnShadowBox()});
					businessDiv.down('.box-bl').insert({'top': '<h2><a rel="business" href="?pageID='+LAUNCH.Config.pages.business+'"><img src="/images/logo_launch_business.gif" alt="Launch! Business consultancy" /></a></h2>'});
					businessDiv.down('.box-bl').insert({'bottom': new Element('div', {'class': 'box-content','style':'width: 465px;'}).hide() });
					businessDiv.hide();
					
					var sapDiv = new Element('div', {'class': 'content-box-sap'})
					sapDiv.insert({'top': this.returnShadowBox()});
					sapDiv.down('.box-bl').insert({'top': '<h2><a rel="sap" href="?pageID='+LAUNCH.Config.pages.sap+'"><img src="/images/logo_launch_sap.gif" alt="Launch! Sap consultancy" /></a></h2>'});
					sapDiv.down('.box-bl').insert({'bottom': new Element('div', {'class': 'box-content','style':'width: 465px;'}).hide() });
					sapDiv.hide();
					
					var trainingDiv = new Element('div', {'class': 'content-box-training'})
					trainingDiv.insert({'top': this.returnShadowBox()});
					trainingDiv.down('.box-bl').insert({'top': '<h2><a rel="training" href="?pageID='+LAUNCH.Config.pages.training+'"><img src="/images/logo_launch_training.gif" alt="Launch! training" /></a></h2>'});
					trainingDiv.down('.box-bl').insert({'bottom': new Element('div', {'class': 'box-content','style':'width: 465px;'}).hide() });
					trainingDiv.hide();
					
					var legalDiv = new Element('div', {'class': 'content-box-legal'})
					legalDiv.insert({'top': this.returnShadowBox()});
					legalDiv.down('.box-bl').insert({'top': '<h2><a rel="legal" href="?pageID='+LAUNCH.Config.pages.legal+'"><img src="/images/logo_launch_legal.gif" alt="Launch! legal" /></a></h2>'});
					legalDiv.down('.box-bl').insert({'bottom': new Element('div', {'class': 'box-content','style':'width: 465px;'}).hide() });
					legalDiv.hide();
					
					contentDiv.insert({'top': sapDiv});
					contentDiv.insert({'bottom': businessDiv});
					contentDiv.insert({'bottom': trainingDiv});
					contentDiv.insert({'bottom': legalDiv});
				}
				this.finishAnimation();
			break;
			case 'globalglobal':
				this.waitThreshold=1;
				this.contentCall();
				// setting callback function to perform after animation and content retrieval from server.
				this.postContentCallback = function(){
					this.insertContent();					
					new Effect.Appear($$('.primary-content')[0],{
						duration:0.2,
						queue:{
							position:'end',
							scope: 'blockScope'
						}
						
					});
				}
				// start animation
				new Effect.Fade($$('.primary-content')[0],{
					duration:0.2,
					queue:{
						position:'end',
						scope: 'blockScope'
					}
				});
				// custom code to do on completion of animation
				this.postAnimationCallback = function(){
					this.showLoader($$('.primary')[0]);
				}
				this.finishAnimation();
				break;
			break;
			case 'globalbusiness':
				this.globalToContent();
			break;
			case 'globalsap':
				this.globalToContent();
			break;
			case 'globaltraining':
				this.globalToContent();
			break;
			case 'globallegal':
				this.globalToContent();
			break;
			
			case 'businesshome':
				this.contentToHome();
			break;
			case 'businessbusiness':
				this.refreshContentPage();
			break;
			case 'businesssap':
				this.contentToContent();
			break;
			case 'businesstraining':
				this.contentToContent();
			break;
			case 'businesslegal':
				this.contentToContent();
			break;
			case 'businessglobal':
				this.contentToGlobal();
			break;
			
			case 'saphome':
				this.contentToHome();
			break;
			case 'sapbusiness':
				this.contentToContent();
			break;
			case 'sapsap':
				this.refreshContentPage();
			break;
			case 'saptraining':
				this.contentToContent();
			break;
			case 'saplegal':
				this.contentToContent();
			break;
			case 'sapglobal':
				this.contentToGlobal();
			break;
			
			case 'traininghome':
				this.contentToHome();
			break;
			case 'trainingbusiness':
				this.contentToContent();
			break;
			case 'trainingsap':
				this.contentToContent();
			break;
			case 'trainingtraining':
				this.refreshContentPage();
			break;
			case 'traininglegal':
				this.contentToContent();
			break;
			case 'trainingglobal':
				this.contentToGlobal();
			break;
			
			case 'legalhome':
				this.contentToHome();
			break;
			case 'legalbusiness':
				this.contentToContent();
			break;
			case 'legalsap':
				this.contentToContent();
			break;
			case 'legaltraining':
				this.contentToContent();
			break;
			case 'legallegal':
				this.refreshContentPage();
			break;
			case 'legalglobal':
				this.contentToGlobal();
			break;
		}
	},
	
	homeToContent: function(departmentName){
		this.waitThreshold=3;
		this.contentCall();
		
		this.submenu = new LAUNCH.Parts.Submenu(new Element('div', {'class': 'submenu'}), 'submenu');
		this.subsubmenu = new LAUNCH.Parts.Submenu(new Element('div', {'class': 'subsubmenu'}), 'subsubmenu');
		
		this.retrieveSubmenu();
		this.retrieveSubsubmenu();

		
		// start animation
			new Effect.Parallel([
					new Effect.BlindUp($$('.content-box-sap .box-content')[0], { sync: true}),
					new Effect.BlindUp($$('.content-box-business .box-content')[0], { sync: true}), 
					new Effect.BlindUp($$('.content-box-training .box-content')[0], { sync: true}), 
					new Effect.BlindUp($$('.content-box-legal .box-content')[0], { sync: true})
				], { 
				duration: 0.3,
				queue:{
					position: 'end',
					scope: 'blockScope'
				}
			});
			new Effect.Parallel([
					new Effect.BlindUp($$('.content-box-sap')[0], { sync: true}),
					new Effect.BlindUp($$('.content-box-business')[0], { sync: true}), 
					new Effect.BlindUp($$('.content-box-training')[0], { sync: true}), 
					new Effect.BlindUp($$('.content-box-legal')[0], { sync: true}) 
				], { 
				duration: 0.3,
				queue:{
					position: 'end',
					scope: 'blockScope'
				}
			});
		
		// setting callback function to perform after animation and content retrieval from server.
		this.postContentCallback = function(){
			this.insertContent();
			this.submenu.update();
			this.subsubmenu.update();
			
			new Effect.BlindDown($$('.primary .box-tr')[0], {
				duration:0.3,
				queue: {
					position: 'end',
					scope: 'blockScope'
				}
			});
			
			this.submenu.showAnimated();
			this.subsubmenu.showAnimated();
			this.labelBox.showAnimated();
		}
		
		// custom code to do on completion of animation
		this.postAnimationCallback = function(){
			var contentDiv = $$('.content')[0];
			contentDiv.update();
			
			this.buildGlobalPage();
			
			var primary = $$('.primary')[0];
			
			primary.update();
			
			primary.insert({'top': this.returnShadowBox()});
			
			primary.down('.box-bl').insert({'top': '<h2><a rel="'+this.newTemplate+'" href="?pageID='+LAUNCH.Config.pages[this.newTemplate]+'"><img src="/images/logo_launch_'+this.newTemplate+'.gif" alt="Launch! '+this.newTemplate+'" /></a></h2>'});
			
			primary.down('.box-bl').insert({'bottom': this.submenu.element});
			primary.down('.box-bl').insert({'bottom': this.subsubmenu.element});
			
			var primaryContent = $(new Element('div'));
			primaryContent.addClassName('primary-content');
			primary.down('.box-bl').insert({'bottom':primaryContent});
			
			$$('.primary .box-tr')[0].hide();
			$$('.primary')[0].setStyle({'float':"left"});
			this.showLoader($$('.primary')[0]);
			
			this.clearActiveLink($$('.menu')[0]);
			this.updateActiveLink();
		}
		this.finishAnimation();
	},
	contentToHome: function(){
		this.waitThreshold=1;
				// start retrieving content
				this.contentCall();
				// setting callback function to perform after animation and content retrieval from server.
				this.postContentCallback = function(){
					this.insertContent();
					
					new Effect.Parallel([
						new Effect.BlindDown($$('.content-box-sap')[0], { sync: true}),
						new Effect.BlindDown($$('.content-box-business')[0], { sync: true}), 
						new Effect.BlindDown($$('.content-box-training')[0], { sync: true}), 
						new Effect.BlindDown($$('.content-box-legal')[0], { sync: true}) 
					], { 
						duration: 0.3,
						queue:{
							position: 'end',
							scope: 'blockScope'
						},
						afterFinish: function(){
							new Effect.Parallel([
								new Effect.BlindDown($$('.box-content')[0], { sync: true}),
								new Effect.BlindDown($$('.box-content')[1], { sync: true}),
								new Effect.BlindDown($$('.box-content')[2], { sync: true}),
								new Effect.BlindDown($$('.box-content')[3], { sync: true})
							], { 
								duration: 0.3,
								queue:{
									position: 'end',
									scope: 'blockScope'
								}
							});
						}
					});
				}
				
				// start animation
				this.labelBox.hideAnimated();
				
				new Effect.BlindUp($$('.primary')[0],{
					duration:0.5,
					queue:{
						position:'end',
						scope: 'blockScope'
					}
				});
				
				// custom code to do on completion of animation
				this.postAnimationCallback = function(){
					var contentDiv = $$('.content')[0];
					
					contentDiv.update();
															
					var sapDiv = new Element('div', {'class': 'content-box-sap'})
					sapDiv.insert({'top': this.returnShadowBox()});
					sapDiv.down('.box-bl').insert({'top': '<h2><a rel="sap" href="?pageID='+LAUNCH.Config.pages.sap+'"><img src="/images/logo_launch_sap.gif" alt="Launch! Sap consultancy" /></a></h2>'});
					sapDiv.down('.box-bl').insert({'bottom': new Element('div', {'class': 'box-content','style':'width: 465px;'}).hide() });
					sapDiv.hide();
					
					var businessDiv = new Element('div', {'class': 'content-box-business'})
					businessDiv.insert({'top': this.returnShadowBox()});
					businessDiv.down('.box-bl').insert({'top': '<h2><a rel="business" href="?pageID='+LAUNCH.Config.pages.business+'"><img src="/images/logo_launch_business.gif" alt="Launch! Business consultancy" /></a></h2>'});
					businessDiv.down('.box-bl').insert({'bottom': new Element('div', {'class': 'box-content','style':'width: 465px;'}).hide() });
					businessDiv.hide();
					
					var trainingDiv = new Element('div', {'class': 'content-box-training'})
					trainingDiv.insert({'top': this.returnShadowBox()});
					trainingDiv.down('.box-bl').insert({'top': '<h2><a rel="training" href="?pageID='+LAUNCH.Config.pages.training+'"><img src="/images/logo_launch_training.gif" alt="Launch! training" /></a></h2>'});
					trainingDiv.down('.box-bl').insert({'bottom': new Element('div', {'class': 'box-content','style':'width: 465px;'}).hide() });
					trainingDiv.hide();
					
					var legalDiv = new Element('div', {'class': 'content-box-legal'})
					legalDiv.insert({'top': this.returnShadowBox()});
					legalDiv.down('.box-bl').insert({'top': '<h2><a rel="legal" href="?pageID='+LAUNCH.Config.pages.legal+'"><img src="/images/logo_launch_legal.gif" alt="Launch! legal" /></a></h2>'});
					legalDiv.down('.box-bl').insert({'bottom': new Element('div', {'class': 'box-content','style':'width: 465px;'}).hide() });
					legalDiv.hide();
					
					contentDiv.insert({'top': sapDiv});
					contentDiv.insert({'bottom': businessDiv});
					contentDiv.insert({'bottom': trainingDiv});
					contentDiv.insert({'bottom': legalDiv});
				}
				this.finishAnimation();
	},
	
	contentToGlobal: function(){
		this.waitThreshold=1;
		this.contentCall();
		// setting callback function to perform after animation and content retrieval from server.
		this.postContentCallback = function(){
			this.insertContent();
			new Effect.Appear($$('.primary-content')[0],{
				duration:0.3,
				queue:{
					position:'end',
					scope: 'blockScope'
				}
			});
			//this.labelBox.showAnimated();
		}
		
		// start animation
		new Effect.BlindUp($$('.primary')[0],{
			duration:0.3,
			queue:{
				position: 'end',
				scope: 'blockScope'
			}
		});		
		
		// custom code to do on completion of animation
		this.postAnimationCallback = function(){
			var contentDiv = $$('.content')[0];
			//contentDiv.update();
			this.buildGlobalPage();
			this.clearActiveLink(this.labelBox.element);
			$$('.primary-content')[0].hide();
		}
		this.finishAnimation();
	},
	/**
	 * refresh the primary-content of department
	 */
	refreshContentPage: function(){
		this.waitThreshold=2;
		this.contentCall();
		this.retrieveSubsubmenu();
		// setting callback function to perform after animation and content retrieval from server.
		this.postContentCallback = function(){
			this.hideLoader();
			this.insertContent();
			this.subsubmenu.update();
			// content blind down
			this.subsubmenu.showAnimated();
			new Effect.BlindDown($$('.primary-content')[0],{
				duration:0.3,
				queue:{
					position: 'end',
					scope: 'blockScope'
				}
			});
		}
		
		// start animation
		new Effect.BlindUp($$('.primary-content')[0],{
			duration:0.3,
			queue:{
				position: 'end',
				scope: 'blockScope'
			}
		});
		this.subsubmenu.hideAnimated();
		
		// custom code to do on completion of animation
		this.postAnimationCallback = function(){	
			this.showLoader($$('.primary .box-bl')[0]);		
		}
		this.finishAnimation();
	},
	/**
	 * @description swap from globalPage to content
	 */
	globalToContent: function(){
		this.waitThreshold=3;
		// start retrieving content
		this.contentCall();
		this.submenu = new LAUNCH.Parts.Submenu(new Element('div', {'class': 'submenu'}), 'submenu');
		this.subsubmenu = new LAUNCH.Parts.Submenu(new Element('div', {'class': 'subsubmenu'}), 'subsubmenu');
		
		this.retrieveSubmenu();
		this.retrieveSubsubmenu();
		
		
		// start animation
		new Effect.Fade($$('.primary-content')[0],{
			duration:0.5,
			queue:{
				position:'end',
				scope: 'blockScope'
			}
		});
		
		// setting callback function to perform after animation and content retrieval from server.
		this.postContentCallback = function(){
			this.insertContent();
			this.submenu.update();
			this.subsubmenu.update();
			
			new Effect.BlindDown($$('.primary .box-tr')[0], {
				duration:0.3,
				queue: {
					position: 'end',
					scope: 'blockScope'
				}
			});
			
			this.submenu.showAnimated();
			this.subsubmenu.showAnimated();
		}
		
		// custom code to do on completion of animation
		this.postAnimationCallback = function(){
			var contentDiv = $$('.content')[0];
			
			var primary = $$('.primary')[0];
			
			primary.update();
			
			primary.insert({'top': this.returnShadowBox()});
			
			primary.down('.box-bl').insert({'top': '<h2><a rel="'+this.newTemplate+'" href="?pageID='+LAUNCH.Config.pages[this.newTemplate]+'"><img src="/images/logo_launch_'+this.newTemplate+'.gif" alt="Launch! '+this.newTemplate+'" /></a></h2>'});
			
			primary.down('.box-bl').insert({'bottom': this.submenu.element});
			primary.down('.box-bl').insert({'bottom': this.subsubmenu.element});
			
			var primaryContent = $(new Element('div'));
			primaryContent.addClassName('primary-content');
			primary.down('.box-bl').insert({'bottom':primaryContent});
			
			$$('.primary .box-tr')[0].hide();
			$$('.primary')[0].setStyle({'float':"left"});
			this.showLoader($$('.primary')[0]);
			
			this.clearActiveLink($$('.menu')[0]);
		}
		this.finishAnimation();
	},
	contentToContent: function(){
		this.waitThreshold=3;
		// start retrieving content
		this.contentCall();
		this.submenu = new LAUNCH.Parts.Submenu(new Element('div', {'class': 'submenu'}), 'submenu');
		this.subsubmenu = new LAUNCH.Parts.Submenu(new Element('div', {'class': 'subsubmenu'}), 'subsubmenu');
		
		this.retrieveSubmenu();
		this.retrieveSubsubmenu();
		
		
		// start animation
		new Effect.BlindUp($$('.primary .box-tr')[0],{
			duration:0.5,
			queue:{
				position:'end',
				scope: 'blockScope'
			}
		});
		new Effect.BlindUp($$('.primary')[0],{
			duration:0.5,
			queue:{
				position:'end',
				scope: 'blockScope'
			}
		});
		
		// setting callback function to perform after animation and content retrieval from server.
		this.postContentCallback = function(){
			this.insertContent();
			this.submenu.update();
			this.subsubmenu.update();
			
			new Effect.BlindDown($$('.primary')[0], {
				duration:0.3,
				queue: {
					position: 'end',
					scope: 'blockScope'
				}
			});

			
			this.submenu.showAnimated();
			this.subsubmenu.showAnimated();
			//this.labelBox.showAnimated();
		}
		
		// custom code to do on completion of animation
		this.postAnimationCallback = function(){
			var contentDiv = $$('.content')[0];
			
			var primary = $$('.primary')[0];
			
			primary.update();
			
			primary.insert({'top': this.returnShadowBox()});
			
			primary.down('.box-bl').insert({'top': '<h2><a rel="'+this.newTemplate+'" href="?pageID='+LAUNCH.Config.pages[this.newTemplate]+'"><img src="/images/logo_launch_'+this.newTemplate+'.gif" alt="Launch! '+this.newTemplate+'" /></a></h2>'});
			
			primary.down('.box-bl').insert({'bottom': this.submenu.element});
			primary.down('.box-bl').insert({'bottom': this.subsubmenu.element});
			
			var primaryContent = $(new Element('div'));
			primaryContent.addClassName('primary-content');
			primary.down('.box-bl').insert({'bottom':primaryContent});
			
			$$('.primary .box-tr')[0];
			$$('.primary')[0].setStyle({'float':"left"});
			this.showLoader($$('.primary')[0]);
			
			//this.clearActiveLink($$('.menu')[0]);
		}
		this.finishAnimation();
	},
	
	retrieveSubmenu : function(){
		Event.observe(document, 'submenu:updated', function(){
			this.tryContinue();
			Event.stopObserving(document, 'submenu:updated');
		}.bind(this));
		this.submenu.getNewHTML(this.pageID);
	},
	retrieveSubsubmenu : function(){
		Event.observe(document, 'subsubmenu:updated', function(){
			this.tryContinue();
			Event.stopObserving(document, 'subsubmenu:updated');
		}.bind(this));
		this.subsubmenu.getNewHTML(this.pageID);
	},
	
	/**
	 * insert all elements used in the global template
	 */
	buildGlobalPage: function(){
		var contentDiv = $$('.content')[0];

		if(!contentDiv.down('.primary')){
			this.labelBox = new LAUNCH.Parts.LabelBox(new Element('div'));
			var secondary = $(new Element('div'));
			secondary.addClassName('secondary');
			secondary.addClassName('right');
			
			var primary = $(new Element('div'));
			primary.addClassName('primary');
			primary.addClassName('left');
			
			contentDiv.insert({'top':primary});
			contentDiv.insert({'bottom':secondary});
			$$('.secondary')[0].insert({'top': this.labelBox.element});
			this.labelBox.buildPart([{'classn': 'business', 'page': LAUNCH.Config.pages.business}, {'classn': 'sap', 'page': LAUNCH.Config.pages.sap}, {'classn': 'training', 'page': LAUNCH.Config.pages.training}, {'classn': 'legal', 'page': LAUNCH.Config.pages.legal}]);
		}else{
			primary = contentDiv.down('.primary').show();
			primary.update();
		}
		var primaryContent = $(new Element('div'));
		primaryContent.addClassName('primary-content');
		primary.insert({'top':primaryContent});
		
		var primaryTitle = $(new Element('h2'));
		primaryTitle.addClassName('primary-title');
		primaryContent.insert({'top':primaryTitle});
	},
	/**
	 * make ajax call and bind onSucces function (places content in global var 'contentObject')
	 * @param {Integer} page to get content from
	 */
	contentCall: function(){
		new Ajax.Request(LAUNCH.Config.APIurl+'?action=getPage&' + this.queryString, {
			method: 'get',
			onSuccess: function(transport) {
				this.contentObject = $H(transport.responseText.evalJSON());
				this.tryContinue();
			}.bind(this)
		});
	},
	/**
	 * this function is called at the end of every thread that has to finish before the animation can continue
	 */
	tryContinue: function(){
		if(this.waitForSomething == this.waitThreshold){
			this.waitForSomething = 0;
			this.hideLoader();
			if(!this.isHistory){
				this.setHistory();
			}
			if(this.contentObject){
				document.title = $H(this.contentObject).get('title') || document.title;
				pageTracker._trackPageview("/page/"+document.title);
			}
			this.postContentCallback();
			this.addStyleBehaviours();
			// action figure may animate again
			LAUNCH.Header.ActionFigure.modDuration = 1;
			// clicks may be processed from now on
			LAUNCH.Layout.Block = 0;
		}else{
			this.waitForSomething++;
		}
	},
	/**
	 * tryContinue has to be called after the first batch of animations
	 */
	finishAnimation: function(){
		new Effect.Nothing({
			queue:{
				position: 'end',
				scope: 'blockScope'
			},
			afterFinish: function(){
				this.postAnimationCallback();
				// waiting for semaphore
				this.tryContinue();
			}.bind(this)
		});
	},
	/**
	 * read content returned from server, and fill in page 
	 */
	insertContent: function(){
		if(this.newTemplate != 'home'){
			var content = $$('.primary-content')[0];
			var title = content.down('.primary-title');
			var contentString = "";
			var titleString = "";
			
			this.contentObject.each(function(pair){
				if(pair.key == 'head_kop1'){
					// read head_kop1 to place within <Hx> tag
					titleString = pair.value;	
				}else if(pair.key == 'title'){	
					//this.pageTitle = pair.value;
				}else{
					if (pair.value != '') {
						contentString += pair.value;
					}
				}
					
			}.bind(this));
			content.update(contentString);
			
			if(this.newTemplate == 'global'){
				title.update(titleString);
				content.insert({'top': title});
			}
		}
		else{
			$$('.content-box-sap .box-content')[0].update(this.contentObject.get('text_sap'));
			$$('.content-box-business .box-content')[0].update( this.contentObject.get('text_business'));
			$$('.content-box-training .box-content')[0].update(this.contentObject.get('text_training'));
			$$('.content-box-legal .box-content')[0].update( this.contentObject.get('text_legal'));
			
			$$('.content-box-sap .box-content')[0].insert({'bottom': '<p class="text-right"><a class="arrow-right" rel="sap" href="?pageID='+LAUNCH.Config.pages.sap+'">'+((Cookie.get('language')=="en")?"More information":"Meer info")+'</a></p>'});
			$$('.content-box-business .box-content')[0].insert({'bottom': '<p class="text-right"><a class="arrow-right" rel="business" href="?pageID='+LAUNCH.Config.pages.business+'">'+((Cookie.get('language')=="en")?"More information":"Meer info")+'</a></p>'});
			$$('.content-box-training .box-content')[0].insert({'bottom': '<p class="text-right"><a class="arrow-right" rel="training" href="?pageID='+LAUNCH.Config.pages.training+'">'+((Cookie.get('language')=="en")?"More information":"Meer info")+'</a></p>'});
			$$('.content-box-legal .box-content')[0].insert({'bottom': '<p class="text-right"><a class="arrow-right" rel="legal" href="?pageID='+LAUNCH.Config.pages.legal+'">'+((Cookie.get('language')=="en")?"More information":"Meer info")+'</a></p>'});
		}
	},
	/*
	 * applies style.js behaviours
	 */
	addStyleBehaviours: function(){
		new Effect.Nothing({
			queue:{
				position: 'end',
				scope: 'blockScope'
			},
			afterFinish: function(){
				rules = LAUNCH.Config.behaviourRules();
				for(var index = 0, len = rules.length; index < len; ++index){
					Event.addBehavior(rules[index]);
				}
			}.bind(this)
		});
	},
	/**
	 * set the location of the secondary content div depending on template
	 */
	setSecondary: function(template){
		var secondary = $$('.secondary')[0];
		// clean from other classes
		secondary.writeAttribute({'class': 'secondary'})
		
		secondary.addClassName('right');
		$$('.content')[0].insert({'bottom':secondary.remove()});
		this.labelBox.buildPart([{'classn': 'business', 'page': LAUNCH.Config.pages.business}, {'classn': 'sap', 'page': LAUNCH.Config.pages.sap}, {'classn': 'training', 'page': LAUNCH.Config.pages.training}, {'classn': 'legal', 'page': LAUNCH.Config.pages.legal}], template);
	},
	/**
	 * returns nested div structure used for the box with shadow
	 */
	returnShadowBox: function(){
		var boxHTML = '\
		<div class="box-tr">\n\
			<div class="box-tl">\n\
				<div class="box-br">\n\
					<div class="box-bl">\n\
					</div>\n\
				</div>\n\
			</div>\n\
		</div>';
		return boxHTML;
	},
	/**
	 * @description remove the banner on the homePage
	 */
	removeBanner: function(){
		if($$('.banner_home')[0]){
			new Effect.Fade($$('.banner_home')[0],{
				duration:0.3,
				queue: {
					position: 'end',
					scope: 'blockScope'
				},
				afterFinish:function(){
					$$('.banner_home')[0].remove();
				}
			});
		}
	},
	/**
	 * show the loader 
	 * @param {Element} element to insert the loader
	 */
	showLoader: function(element){
//		element.insert('<img src="'+LAUNCH.Config.LoaderSrc+'" class="ajax-loader" style="display:none;" alt="" />');
//		new Effect.BlindDown($$('.ajax-loader')[0],{
//			duration:0.1
//		});
	},
	/**
	 * hide the ajax-loader
	 */
	hideLoader: function(){
//		$$('.ajax-loader').each(function(loader){
//			loader.remove();
//		});
	}
};
