function helper_ScreenCenterElement_GetMarginTop(idElem) {
	// must use id
	// else if e.g. idElem is a $(elem) Object in a chained call (as in cIntro.initIntro)
	// it would result in an "OwnerDocument is undefined" error
	var mrgTop = parseInt( ($(window).height() / 2) - ($('#' + idElem).height() / 2) );
	return (mrgTop >= 0) ? mrgTop : 0;
}

var cBaseIntro = {
	useScreenCentering: false,
	replayIntroStr: 'Replay Intro',
	loaderImg: null,
	bgColorPreloadingForMSIE: '#eaeaea',
	useTimeSlider: false,
	afterAnimUrl: null,
	afterAnimFunction: null,
	timeSliderStartIndex: 0,
	timeSliderTransition: gl_introTransition['fade'],
	timeSliderImg: null,
	timeSliderWrapperImg: null,
	timeSliderStyle: null,
	timeSliderWrapperStyle: null,
	wrapperStyle: null,
	idTimeSlider: 'timeSlider',
    idTimeSliderWrapper: 'timeSliderWrapper',
    idWrapper: 'wrapper',
    idLoader: 'loader',
    idStatus: 'status',
	timeFrame: 500,
    timeTransition: 250,
    images: null,
    imgLoaded: 0,
    imgToLoad: 0
}

var cIntro = function() {
    // closure var
    var selfRef = this;
	var stopAnim = false;
	var preloader = null;
	var args = null;
    
    this.initIntro = function(){
		this.stopAnim = false;
		
        this.imgToLoad = this.images.length;       
		
        $('#' + this.idWrapper)
			.empty()
			.width( (selfRef.wrapperStyle['width'] != null) ? parseInt(selfRef.wrapperStyle['width']) : 200 )
			.height( (selfRef.wrapperStyle['height'] != null) ? parseInt(selfRef.wrapperStyle['height']) : 200 )
			.queue(function(next) {
				for (var cssProp in selfRef.wrapperStyle) {
					$(this)
						.css(cssProp, selfRef.wrapperStyle[cssProp]);
				}
				next();
			})	
			.css('position', 'relative')
			.css('overflow', 'hidden')
			.queue(function(next) {
				if (selfRef.useScreenCentering) {
					$(this)
						.css('margin-top', helper_ScreenCenterElement_GetMarginTop(selfRef.idWrapper) + 'px');	
				}	
				next();			
			})
			.show(0);
        
        this.showLoader();
		this.preloader = new cPreloader( {
			images: this.images,
			callbackImgLoaded: this.imgPreloaded,
			callbackAllLoaded: this.preloadingDone
		});
    }
	
	// this is a callback use selfRef instead of this to get this object and not the caller object
	// or use an anonymous fnct
	this.imgPreloaded = function(index, img) {
		$('#' + selfRef.idStatus).html('loading ' + (index + 1) + '/' + selfRef.preloader.imgToLoad);
		selfRef.imgLoaded++;
        $(img)
			.css('position', 'absolute')
			.css('top', '0px')
			.css('left', '0px');
	}
	
	// this is a callback use selfRef instead of this to get this object and not the caller object
	// or use an anonymous fnct
	this.preloadingDone = function() {
		$('#' + selfRef.idLoader)
			.fadeOut(250)
			.queue(
				function(next) {
					$('#' + selfRef.idWrapper).empty();
					var maxWidth = 0, maxHeight = 0;
					for (var i in selfRef.images)
					{
						// get max size for x and y
						maxWidth = (maxWidth < selfRef.images[i]['img'].width) ? selfRef.images[i]['img'].width : maxWidth;
						maxHeight = (maxHeight < selfRef.images[i]['img'].height) ? selfRef.images[i]['img'].height : maxHeight;
						// append
						$('#' + selfRef.idWrapper)
							.append(
								$(selfRef.images[i]['img'])
									.hide()
							);
					}
					$('#' + selfRef.idWrapper)
						.width(maxWidth)
						.height(maxHeight)
						.queue(function(next) {
							if (selfRef.useScreenCentering) {
								$(this)
									.css('margin-top', helper_ScreenCenterElement_GetMarginTop(selfRef.idWrapper) + 'px');	
							}	
							next();			
						});
					
					selfRef.startAnim();
					next();	
				}				
			);	
	}
    
    this.showLoader = function(){
        $('#' + this.idWrapper)
			.html(
				$(document.createElement('div'))
				.attr('id', selfRef.idLoader)			
				.css('margin-left', 'auto')
				.css('margin-right', 'auto')
				.css('text-align', 'center')
				.append(
					$(selfRef.loaderImg)
						.css('margin-left', 'auto')
						.css('margin-right', 'auto')
						//.css('display', 'block')
				).append(
					$(document.createElement('p'))
					.attr('id', selfRef.idStatus)
					.css('font-family', 'Verdana,Arial,sans-serif,"Lucida Sans","Franklin Gothic Medium"')
					.css('font-size', '8pt')
					.css('color', '#777777')
					.queue(function(next) {
                        // if is ie add bg color to prevent pixelated text while fading 
                        if ($.browser.msie) {
                            $(this)
                                .css('background-color', selfRef.bgColorPreloadingForMSIE);
                        }
                        next();
                    })				
					.html('loading 0/' + selfRef.imgToLoad)
				)
			)
			.queue(function(next) {
				$('#' + selfRef.idLoader)
					.css('margin-top', 
						parseInt(
							($('#' + selfRef.idWrapper).height() / 2) - ($('#' + selfRef.idLoader).height() / 2)
						)  + 'px');					
				next();
			});
    }
    
    this.startAnim = function(){
		// set click handler
		if (this.afterAnimUrl != null) {
			$('#' + selfRef.idWrapper)
				.css('cursor', 'pointer')
				.click(function() {
					selfRef.stopAnim = true;
					selfRef.endAnim();					
				});	
		}
		
		// set timeslider
		if (this.useTimeSlider)
		{
			// create timeslider elements
			$(document.createElement('div'))
				.attr('id', selfRef.idTimeSliderWrapper)
				.queue(function(next) {
					for (var cssProp in selfRef.timeSliderWrapperStyle) {
						$(this)
							.css(cssProp, selfRef.timeSliderWrapperStyle[cssProp]);
					}
					next();
				})		
				.css('position', 'absolute')
				.css('overflow', 'hidden')		
				.html( $(document.createElement('div'))
							.attr('id', selfRef.idTimeSlider)
							.queue(function(next) {
								for (var cssProp in selfRef.timeSliderStyle) {
									$(this)
										.css(cssProp, selfRef.timeSliderStyle[cssProp]);
								}
								next();
							})
				)
				.appendTo($('#' + this.idWrapper))
				.hide();						
		}
		
    	this.animate(0);
    }
	
	this.endAnim = function() {		
		$('#' + selfRef.idWrapper)
			.unbind('click')
			.css('cursor', 'default')
			.find('img:not(img:last)')
			.remove()
			.end()
			.children()
			.fadeOut(250, function() {
				if ( $(this).is(':last-child') ) {
					$('#' + selfRef.idWrapper)
						.empty()					
						.html(
							$(document.createElement('div'))
								.attr('id', selfRef.idLoader)			
								.css('margin-left', 'auto')
								.css('margin-right', 'auto')
								.css('text-align', 'center')
								.css('cursor', 'pointer')
								.append(
									$(document.createElement('p'))
									.attr('id', selfRef.idStatus)
									.css('font-family', 'Verdana,Arial,sans-serif,"Lucida Sans","Franklin Gothic Medium"')
									.css('font-size', '8pt')
									.css('color', '#777777')
									.html(selfRef.replayIntroStr)							
								)
								.click(function() {
									/*
									if (selfRef['gl_ctlPage'] != null
										&& typeof selfRef['gl_ctlPage']['init'] == 'function'
										&& selfRef['gl_ctlPage']['init'].length == 1) 
									{
										selfRef['gl_ctlPage']['init']( selfRef['gl_ctlPage'] );		
									}
									*/
									window.location.reload();								
								})
						)
						.queue(function(next) {
							$('#' + selfRef.idLoader)
								.css('margin-top', 
									parseInt(
										($('#' + selfRef.idWrapper).height() / 2) - ($('#' + selfRef.idLoader).height() / 2)
									)  + 'px');					
							next();
						});
				}
			});
		
		if (this.afterAnimUrl != null) {
			$('#' + selfRef.idWrapper)
				.queue(function(next) {
					next();
					if (selfRef.afterAnimFunction != null) {
						// do stuff
						// should pass here selfRef.afterAnimUrl
						// and 'this' as arguments
						selfRef.afterAnimFunction(selfRef, selfRef.afterAnimUrl);
					} else {
						window.location = selfRef.afterAnimUrl;	
					}
				});								
		}							
	}
	
	this.animate = function(index) {
		if (index >= 0 
		 	&& index < this.images.length 
			&& $('#' + this.idWrapper).find('img').length == this.images.length) 
		{		 
		 	var domObj = $('#' + this.idWrapper + ' img').get(index);
			// check if domObj and indexed img in this.images[index]['img'] re the same obj  
			if ( domObj === this.images[index]['img'] )
			{
				var timeFrame = (this.images[index]['timeFrame'] != null) ? this.images[index]['timeFrame'] : this.timeFrame;		
				var timeTransition = (this.images[index]['timeTransition'] != null) ? this.images[index]['timeTransition'] : this.timeTransition;
								
				$(domObj).queue(function(next) {
						switch(selfRef.images[index]['transition']) {
							case gl_introTransition['none']:
									$(this).show(0).delay(timeTransition);
								break; 								
							case gl_introTransition['slideDown']:
									$(this)
										.css('top', '-' + $('#' + selfRef.idWrapper).height() + 'px')
										.show(0)
										.animate({top: 0}, timeTransition);	
								break; 							
							case gl_introTransition['slideUp']:
									$(this)
										.css('top', $('#' + selfRef.idWrapper).height() + 'px')
										.show(0)
										.animate({top: 0}, timeTransition);								
								break;
							case gl_introTransition['slideLeft']:
									$(this)
										.css('left', $('#' + selfRef.idWrapper).width() + 'px')
										.show(0)
										.animate({left: 0}, timeTransition);
								break; 
							case gl_introTransition['slideRight']:
									$(this)
										.css('left', '-' + $('#' + selfRef.idWrapper).width() + 'px')
										.show(0)
										.animate({left: 0}, timeTransition);
								break; 							
							case gl_introTransition['fade']:
									$(this).fadeIn(timeTransition);
								break; 							
							default:
								$(this).fadeIn(timeTransition);
						}
						next();
					}
				)
				.queue(function(next) {
					setTimeout(function(){
						selfRef.animate(++index);
					}, timeFrame);
					next();
				});	
				
				// init timeSlider
				if (this.useTimeSlider && index == this.timeSliderStartIndex)
				{
					// temp save animation variables
					var obj = $('#' + selfRef.idTimeSliderWrapper).get();					
					var tSWTop = $('#' + selfRef.idTimeSliderWrapper).css('top');
					var tSWLeft = $('#' + selfRef.idTimeSliderWrapper).css('left');
					var tSWidth = $('#' + selfRef.idTimeSlider).css('width');
					// set timeSlider width to zero 
					$('#' + selfRef.idTimeSlider).css('width', '0px');
					// animate sliderWrapper				
					$('#' + selfRef.idTimeSliderWrapper).queue(function(next) {
							switch(selfRef.timeSliderTransition) {
								case gl_introTransition['none']:
										$(this).show(0).delay(selfRef.timeTransition);
									break; 								
								case gl_introTransition['slideDown']:
										$(this)
											.css('top', '-' + $(this).height() + 'px')
											.show(0)
											.animate({top: tSWTop}, selfRef.timeTransition);	
									break; 							
								case gl_introTransition['slideUp']:
										$(this)
											.css('top', $('#' + selfRef.idWrapper).height() + 'px')
											.show(0)
											.animate({top: tSWTop}, selfRef.timeTransition);								
									break;
								case gl_introTransition['slideLeft']:
										$(this)
											.css('left', $('#' + selfRef.idWrapper).width() + 'px')
											.show(0)
											.animate({left: tSWLeft}, selfRef.timeTransition);
									break; 
								case gl_introTransition['slideRight']:
										$(this)
											.css('left', '-' + $(this).width() + 'px')
											.show(0)
											.animate({left: tSWLeft}, selfRef.timeTransition);
									break; 							
								case gl_introTransition['fade']:
										$(this).fadeIn(selfRef.timeTransition);
									break; 							
								default:
									$(this).fadeIn(selfRef.timeTransition);
							}
							next();
						}
					);
					// animate Slider								
					$('#' + selfRef.idTimeSlider).queue(function(next) {
						// compute timeslider animation time
						// with dynamic timing
						var animTimeSlider = 0;
						var aTimeFrame = 0;
						var aTimeTransition = 0;
						
						for (iImage in selfRef.images)
						{	
							if (iImage >= selfRef.timeSliderStartIndex)
							{
								aTimeFrame = (selfRef.images[iImage]['timeFrame'] != null) ? selfRef.images[iImage]['timeFrame'] : selfRef.timeFrame;		
								aTimeTransition = (selfRef.images[iImage]['timeTransition'] != null) ? selfRef.images[iImage]['timeTransition'] : selfRef.timeTransition;								
								animTimeSlider += aTimeFrame + aTimeTransition;
							}												
						}						
						// old version with fixed timing:
						// var animTimeSlider = (selfRef.images.length - index) * (selfRef.timeFrame + selfRef.timeTransition);
						
						$(this).animate({
								width: tSWidth
							}, {
								duration: animTimeSlider, 
							    specialEasing: {
							      width: 'linear'							      
							    }
							});
						next();
					});			
				}						
			}	
					
			return;
		 }
		 // finally
		 if (!this.stopAnim) {
		 	this.endAnim();
		 }			 		 
	}
	
	// add args as copy
	this.args = arguments[0];
	
    // bind arguments
    for (var n in arguments[0]) {
        this[n] = arguments[0][n];
    };
    // bind event handler
	if (selfRef.useScreenCentering) {
		$(window).resize(function(){
			// realign wrapper margin
			$('#' + selfRef.idWrapper)
				.css('margin-top', helper_ScreenCenterElement_GetMarginTop(selfRef.idWrapper) + 'px');
		});
	}
    // preload loader and timeslider imgs first, then init this object
	var prePreloadArgs = {
		loaderImg: {
			path: this.loaderImg
		},
		timeSliderWrapperImg: {
			path: this.timeSliderWrapperImg
		},
		timeSliderImg: {
			path: this.timeSliderImg
		}
	}
	
	this.preloader = new cPreloader( {
		images: [ 
			prePreloadArgs.loaderImg, 
			prePreloadArgs.timeSliderWrapperImg, 
			prePreloadArgs.timeSliderImg
		],			
		callbackImgLoaded: null,
		callbackAllLoaded: function() {
			for (member in prePreloadArgs) {
				if (prePreloadArgs[member].img != null) {
					selfRef[member] = prePreloadArgs[member].img;
				}
			}
			selfRef.initIntro();
		}
	});
}
cIntro.prototype = cBaseIntro;

