function projector(){

	var className = "projector";
	var version = "1.0";
	var author = "Marcin Kita";
    
	var mainElement = null;
	var currentImageIndex = null;
	var currentImageSizeIndex = 0;
	var previousImageIndex = null;

	var allImages = new imagesCollection();
    
	var currentImg = null;
	var previousImg = null;
	var displayMode = null;
	var fadingSpeed = 1000;
    
	var width = 0;
	var height = 0;
	
	this.busy = false;
	
	var cssClassForImages='';
	
	this.setCssClassForImages = function(c){
		cssClassForImages=c;
	}
	
	this.getCurrentImageIndex = function(){
		return currentImageIndex;
	}

	this.setMainElement = function(el){
		mainElement = el;
		width = $(mainElement).width();
		height = $(mainElement).height();
	}
    
	this.setDisplayMode = function( dm ){
		displayMode = dm;
	}

	this.setFadingSpeed = function( speed ){
		fadingSpeed = parseInt(speed);
	}
    
	this.setSize = function( sizeIndex ){
		currentImageSizeIndex = sizeIndex;
	}
    
	this.add = function( names ){
		allImages.add(names)
		return allImages.length-1;
	}
	
	this.addImagesFromElement = function( el ){
		
		var imgs = $('img',el);
		
		for (var n=0; n<imgs.length; n++){
			allImages.add([imgs[n].src]);
		
			var images = allImages.get( n );
		
			images.setImg( currentImageSizeIndex, imgs[n] );
			$(imgs[n]).data('projector',this);

		}
		
	}

	this.showNext = function(){
		this.show( currentImageIndex<allImages.length-1?currentImageIndex+1:0  );
		return currentImageIndex;
	}
	this.showPrev = function(){
		this.show( currentImageIndex==0?allImages.length-1:currentImageIndex-1 );
		return currentImageIndex;
	}
	this.showLast = function(){
		this.show( allImages.length-1 );
		return currentImageIndex;	
	}
	this.showFirst = function(){
		this.show( 0 );
		return currentImageIndex;		
	}
	
	this.preloadNext = function(){
		if (currentImageIndex<allImages.length-1) this.preload(currentImageIndex+1);
	}

	this.preload = function( imageIndex, force ){
		
		//console.log('preload: index '+imageIndex+' '+force);
		
		var images = allImages.get( imageIndex );
		
		var img = images.getImg( currentImageSizeIndex )

		if (!img) {
        
			var img = document.createElement('img');
			
			$(mainElement).append(img);
	
			images.setImg( currentImageSizeIndex, img );

			if (force) {
				currentImg = img;
				$(img)
				.data('afterLoad',this.display)
				.load( function(){
					
					//alert('wykonano onload');
					
					$(this).data('afterLoad')()
				} )
			}
			$(img)
			.data('projector',this)
			.attr( 'src', images.getName( currentImageSizeIndex ) )
			.css({/*position:'absolute',left:0,right:0,*/
				visibility:'hidden',
				opacity:0,
				display:'none'
			})
			.addClass(cssClassForImages);
		}
		if (force) currentImg = img;
	}
    
	this.show = function( imageIndex ){
		
		if (this.busy) return;
		if( currentImageIndex==imageIndex ) return;

		this.busy = true;

		previousImageIndex = currentImageIndex;
        
		if ( typeof imageIndex == 'number' ) {

			currentImageIndex = imageIndex;
		}else {
			alert('ERROR:1a');
			return
		}
        
		var i = allImages.get( imageIndex ).getImg( currentImageSizeIndex );
		if (!i) {

			this.preload( imageIndex, true);
		} else {
			
			currentImg = i;
			this.display( );
		}
	}
    
	this.display = function(  ){

		var i = $(currentImg);
		
		i.css({
			opacity:0,
			visibility:'visible',
			display:'block'
		})
		
		if ( i.get(0).complete===false)		{
			// jeżeli ładowanie obrazka nie zostało ukończone jego wyświetlenie nalezy opóźnić
			// w przeciwnym razie obrazek będzie wyświetlany w nieprawidłowym miejscu,
			// gdyż jego wymiary nie będą prawidłowe do momentu całkowitego załadowania
			var a = i.data('projector').display;
			if (a) {
				setTimeout( a,300 );
				return false;
			} 
		}
		
		switch ( displayMode ){


			case 'fitBest' :
				var new_width = i.width() * Math.max( width / i.width(), height / i.height() );
				$(mainElement).css({
					position:'relative'
				});
				i.width( new_width )
				.css( {
					position:'absolute',
					left:(width - i.width())/2 + 'px',
					top:(height - i.height())/2 + 'px'
				} );
							 
				break
            
			case 'fitWidth' :
				i.width( width ).css('top',(height - i.height())/2 + 'px');
				break;
            
			case 'fitHeight' :
				i.height( height ).css('left',(width - i.width())/2 + 'px');
				break;
					 
			case 'fitParentHeightWidth' :
				$(mainElement).css({
					position:'relative'
				});
				i.parent().height( i.height() );
				i.parent().width( i.width() );
				i.parent().parent().attr('height', i.height());
				i.css( {
					position:'absolute'
				} );
				break;

			case 'center' :
			default :
				$(mainElement).css({
					position:'relative'
				});
				i.css( {
					position:'absolute',
					left:(width - i.width())/2 + 'px',
					top:(height - i.height())/2 + 'px'
				} );
		}
		
		if ( previousImageIndex!=null ) {
			$( allImages.get( previousImageIndex ).getImg( currentImageSizeIndex )).fadeTo( fadingSpeed, 0, function(){

				//console.log('d:none on ' + previousImageIndex );
				//console.log( $(allImages.get( previousImageIndex ).getImg( currentImageSizeIndex )).attr('src'));
				

				$(this).css('display','none')
				} );
		}
		i.css('display','block').fadeTo(fadingSpeed ,1,
			function(){
				var p = $(this).data('projector');
				if (p) p.busy = false;
			} );
	}
    
	function imageSet( names ) {
		this.imagesData = []
		for (var n in names){
			this.imagesData.push( {
				name:names[n],
				img:null
			} )
		}
		this.getName = function( sizeIndex ){
			return this.imagesData[sizeIndex].name
		}
		this.getImg = function( sizeIndex ){
			return this.imagesData[sizeIndex].img
		}
		this.setImg = function( sizeIndex, i ){
			this.imagesData[sizeIndex].img = i;
		}
	}

	function imagesCollection(){
		this.images=[];
		this.length=0;
        
		this.add = function ( names ){
			this.images.push( new imageSet(names) );
			this.length = this.images.length;
		}
    
		this.get = function (index){
			if (this.images[index]) return this.images[index]; else return null;
			this.length = this.images.length;
		}
	}
}

