(function($) {

this.PioLightbox = new Class({
	
	Implements: [Events, Options, Chain],
	
	ie6: Browser.Engine.trident4,
	
	options: {
		startDimensions: {x: 100, y: 100},
		containerPadding: 10,
		containerMargin: 10,
		captionHeight: 40,
		overlayDuration: 200,
		resizeDuration: 500,
		showDuration: 250,
		captionDuration: 250,
		counter: "Zdjęcie {NUM} z {TOTAL}"
	},

	initialize: function(anchors, options) {
		this.setOptions(options);
		this.items = [];
		
		anchors.each(function(anchor, i) {
			this.items.push({
				src: anchor.href,
				caption: anchor.title
			});
			anchor.addEvent('click', function(e) {
				e.stop();
				this.open(i);
			}.bind(this));
		}, this);
		
		this.animations = [
			// rozszerzenie
			function() {
				var imgSize = {
						x: this.actual.img.width,
						y: this.actual.img.height
					},
					opt = this.options,
					newContSize = this.getSize(imgSize),
					newImgSize = this.changeSize(
							newContSize, -opt.containerPadding * 2, -opt.containerPadding * 2),
					newContPosition = this.getCenterPosition(
							this.changeSize(newContSize, null, opt.captionHeight));				
				
				this.actual.img.setStyles({
					width: newImgSize.x,
					height: newImgSize.y
				});
				
				this.navnext.setStyle('height', newImgSize.y);
				this.navprev.setStyle('height', newImgSize.y);
				
				this.fx.resize.start({
					width: newContSize.x,
					height: newContSize.y,
					left: newContPosition.x,
					top: newContPosition.y
				});
			},
			
			// pokazanie obrazka
			function() {	
				this.inner.removeClass('loading');
				this.inner.setStyle('opacity', 0);
				this.inner.grab(this.actual.img);
				this.fx.show.start(1);	
			},
			
			// pokazanie caption
			function() {
				var countertext;
				
				this.navprev.setStyle('visibility', 'visible');
				this.navnext.setStyle('visibility', 'visible');
				
				if (this.options.counter) {
					countertext = this.options.counter;
					countertext = countertext.replace(/\{NUM\}/, this.actualindex + 1);
					countertext = countertext.replace(/\{TOTAL\}/, this.items.length);
					this.counter.set('text', countertext);
				}
				
				this.desc.set('text', (this.actual.caption ? this.actual.caption : ''));
				
				this.caption.setStyle('display', 'block');
				this.fx.caption.start(0);
			},
			
			// preload kolenjego
			function() {
				return;
				var next = this.items[this.actualindex + 1];
				
				if (next) {
					this.loadImage(next, true);
				}
			}
		];
		
		this.resizeFn = this.reconstructOverlay.bindWithEvent(this);
		this.keyFn = this.keyboardListener.bindWithEvent(this);
	},
	
/*
	Public methods
*/	
	
	open: function(index) {
		index = index || 0;
		
		this.actual = this.items[index];
		this.actualindex = index;
		
		this.windowSize = window.getSize();
		this.windowScroll = window.getScroll();
		
		if (!$chk(this.container)) {
			this.createContainer();
			this.fireEvent('containerCreated');
			this.createFxs();
			window.addEvent('resize', this.resizeFn);
			document.addEvent('keypress', this.keyFn);
			this.fx.overlay.start(0.8);
		} else {
			this.clearChain();
			for (var x in this.fx) {
				this.fx[x].cancel();
			}
			this.inner.empty().addClass('loading');
			this.navnext.setStyle('visibility', 'hidden');
			this.navprev.setStyle('visibility', 'hidden');
			this.caption.setStyles({
				'display': 'none',
				'top': -this.options.captionHeight
			});
		}
		
		if (this.actual.img) {
			this.startAnimations();
		} else {
			this.loadImage(this.items[index]);
		}
	},

	next: function(e) {
		if (e) {
			e.stop();
		}
		
		var next = this.actualindex + 1;
		
		if (next > this.items.length - 1) {
			 next = 0;
		}
		if (next < 0) {
			next = (this.items.length - 1);
		}
		this.open(next);
	},
	
	previous: function(e) {
		if (e) {
			e.stop();
		}
		
		var prev = this.actualindex - 1;
		
		if (prev > this.items.length - 1) {
			prev = 0;
		}
		if (prev < 0) {
			prev = (this.items.length - 1);
		}
		this.open(prev);	
	},
	
	close: function() {
		this.container.destroy();
		new Fx.Tween(this.overlay, {
			duration: this.options.overlayDuration,
			property: "opacity",
			onComplete: function() {
				this.overlay.destroy();
				this.overlay = null;
				this.container = null;
				this.actual = null;
				this.actualIndex = null;
				this.fireEvent('close');
			}.bind(this)
		}).start(0);
		window.removeEvent('resize', this.resizeFn);
		document.removeEvent('keypress', this.keyFn);
	},

	add: function(mix) {
		if ($type(mix) == 'array' && mix.length > 0 && mix[0].src) {
			this.items.combine(mix);
		} else if ($type(mix) == 'object' && mix.src)  {
			this.items.push(mix);
		}
		return this;
	},
/*
	Private methods
*/
	
	startAnimations: function() {
		this.chain(this.animations);
		this.callChain();
	},
	
	loadImage: function(item, isOnlyPreload) {
		if (item.img) {
			return;
		}
		
		item.img = new Asset.image(item.src, {
			'onload': function(img) {
				if (item == this.actual && !isOnlyPreload) {
					this.startAnimations();
				}
			}.bind(this)
		});
	},
	
	getSize: function(obj) {
		var res = {},
			conMar = this.options.containerMargin * 2,
			conPad = this.options.containerPadding * 2,
        	ws = {
				x: this.windowSize.x - conMar,
				y: this.windowSize.y - conMar - this.options.captionHeight
			},
			con = {
				x: obj.x + conPad,
				y: obj.y + conPad
			};
		
		if (con.x <= ws.x && con.y <= ws.y) {
			return con;
        }

        if (con.x - ws.x > con.y - ws.y) {
            res.x = ws.x;
            res.y = Math.ceil((res.x / con.x) * con.y);
        } else {
        	res.y = ws.y;
            res.x = Math.ceil((res.y / con.y) * con.x);
        }

        return res;
	},	
	
	reconstructOverlay: function() {
		var scrollSize = window.getScrollSize();
		this.overlay.setStyles({
			width: scrollSize.x,
			height: scrollSize.y
		});
		this.fireEvent('overlayReconstructed');
	},
	
	keyboardListener: function(e) {
		if (e.key == "esc") {
			this.close();
		}
	},
	
	getCenterPosition: function(dim) {
		return {
			x: Math.ceil(this.windowSize.x / 2 - (dim.x / 2)) + this.windowScroll.x,
			y: Math.ceil(this.windowSize.y / 2 - (dim.y / 2)) + this.windowScroll.y
		}
	},
	
	changeSize: function(obj, x, y) {
		x = x || 0;
		y = y || 0;
		return {
			x: obj.x + x,
			y: obj.y + y
		}
	},
	
	createContainer: function() {
		var scrollSize = window.getScrollSize(),
			dim = this.options.startDimensions,
			position = this.getCenterPosition(dim);
						
		this.overlay = new Element('div', {
			'events': {
				'click': function(e) {
					this.close();
				}.bind(this)
			},
			'class': 'piolightbox-overlay',
			'styles': {
				'opacity': 0, 
				'width': scrollSize.x, 
				'height': scrollSize.y
			}
		}).inject(document.body);
		
		this.container = new Element('div', {
			'class': 'piolightbox',
			'styles': {
				'width': dim.x,
				'height': dim.y,
				'left': position.x,
				'top': position.y
			}
		}).adopt(
			this.inner = new Element('div', {
				'class': 'inner loading'
			}),
			this.caption = new Element('div', {
				'class': 'caption',
				'styles': {'display': 'none', 'top': -this.options.captionHeight}
			}).adopt(
				new Element('div', {
					'class': 'close',
					'events': {
						'click': this.close.bindWithEvent(this)
					}
				}),
				this.counter = new Element('div', {
					'class': 'counter'
				}),
				this.desc = new Element('div', {
					'class': 'desc'
				})
			),
			this.navprev = new Element('a', {
				'class': 'nav nav-prev', 
				'href': '#', 
				'events': {
					'click': function(e) {
						this.previous(e);
					}.bind(this)
				},
				'styles': {'visibility': 'hidden'}
			}),
			this.navnext = new Element('a', {
				'class': 'nav nav-next', 
				'href': '#',
				'events': {
					'click': function(e) {
						this.next(e);
					}.bind(this)
				},
				'styles': {'visibility': 'hidden'}
			})
		).inject(document.body);		
	},
	
	createFxs: function() {
		this.fx = {
			overlay: new Fx.Tween(this.overlay, {
				duration: this.options.overlayDuration,
				property: "opacity"
			}),
			
			resize: new Fx.Morph(this.container, {
				duration: this.options.resizeDuration,
				onComplete: this.callChain.bind(this)
			}),
			
			show: new Fx.Tween(this.inner, {
				duration: this.options.showDuration,
				property: "opacity",
				onComplete: this.callChain.bind(this)
			}),
			
			caption: new Fx.Tween(this.caption, {
				property: "top",
				duration: this.options.captionDuration,
				onComplete: this.callChain.bind(this)
			})
		};		
	}
});

})(document.id || $);
