
// init all found galleries
document.observe("dom:loaded", function() {
	  var galleries = $$('.image-gallery').each(function (gallery) {BS_GalleryManager(gallery.id).init();});
	});

function BS_GalleryManager(galleryId) {
	var manager = new Object();
	manager.id = galleryId;
	manager.galleryRoot = $(galleryId);
	if ( !manager.galleryRoot ) return null;	// no such element
	if ( manager.galleryRoot.galleryManager ) return manager.galleryRoot.galleryManager;
	manager.galleryRoot.galleryManager = manager;
	
	manager.bigView = manager.galleryRoot.select(".bigView").first();
	manager.moverTop = manager.galleryRoot.select('.mover_top').first();
	
	// init function
	manager.init = function () {
		manager.bigView.hide(); // hide initial image - so we can scale it before it's displayed (disabled: on Opera this mostly occurs after load-event)
		
		Element.observe(manager.bigView, 'load', function(event) {
				// fit into bounding-box (div) 
				var imgNew = new Image();	// this "workaround" to get the real size of the image doesn't cost any time (2-5ms)
				imgNew.onload = function () {
					var imgDim = {width: imgNew.width, height: imgNew.height};	// Opera doesn't hand out real dimensions otherwise
					//alert(manager.bigView.naturalWidth + "/" + manager.bigView.naturalHeight);
					var divDim = manager.bigView.up('.ig_image').getDimensions();
					var wFactor = divDim['width']  / imgDim['width']; 
					var hFactor = divDim['height'] / imgDim['height'];
					var factor = Math.min(wFactor, hFactor);
					if ( factor > 1 ) factor=1; // don't do upscaling
					// always setting image size fixes a bug in chrome
					//alert((imgDim['width']  * factor) + "/" + (imgDim['height'] * factor) + "/fac:" + factor);
					manager.bigView.width = imgDim['width']  * factor;
					manager.bigView.height= imgDim['height'] * factor;
					
					var imgDim = manager.bigView.getDimensions();
					
					new Effect.Appear(manager.bigView, { duration: 0.2 });
				};
				imgNew.src = manager.bigView.src;
				
			});

		manager.galleryRoot.select('.mover_prev', '.mover_next', '.big_prev', '.big_magnify', '.big_next').each(function (elem, context) {
				var fadeOutLimit = 0.1;
				if ( elem.hasClassName('mover_prev') || elem.hasClassName('mover_next') ) fadeOutLimit = 0.5;
				new Effect.Fade(elem, {to: fadeOutLimit, duration: 3.0});
				var eventScopeName = 'actionItem'+context;
				var eventScopeSettings = {position: 'end', scope: eventScopeName}
				elem.observe('mouseover', function() {
						Effect.Queues.get(eventScopeName).invoke('cancel');
						new Effect.Appear(elem, {to: 0.7, duration: 0.2, queue: eventScopeSettings});
					});
				elem.observe('mouseout' , function() {
						Effect.Queues.get(eventScopeName).invoke('cancel');
						new Effect.Fade  (elem, {to: fadeOutLimit, duration: 0.5, queue: eventScopeSettings});
					});
			});

		var links = this.moverTop.select('a[rel=lightbox]').each(function (linkItem) {
				manager._previewLinkInitClickEvents(linkItem);
			});
		// initially apply preview-selection-fade-out and mouseover/mouseout
		var previewEventGroupIdx = 0;
		manager.galleryRoot.select('a[rel=lightbox] img').each(function (elem) {
				var eventScopeName = 'prevScope'+(previewEventGroupIdx++);
				manager._previewImgInitFadeEvents(elem, eventScopeName);
			});
		
		manager.currentElemClick();
	}
	
	manager.empty = function () {
		manager.bigView.hide();
		manager.moverTop.select('a').each(function (elem) {elem.remove()});
	}

	manager.initPicasa = function (userId, albumId) {
		manager.empty();
		
		var picasaJsonUrl = 'picasa_ajax_proxy.php?userId='+userId+'&albumId='+albumId;
		//var picasaJsonUrl = 'http://localhost/image-gallery/index.php';
		var statusDiv = $(manager.id+'_status');
		statusDiv.update('Fetching data from picasa-web-feed ... Please Wait.');
		statusDiv.removeClassName('failure');
		statusDiv.removeClassName('success');
		statusDiv.addClassName('working');
		$(manager.id+'_galleryHeadline').update('&nbsp;');
		new Ajax.Request(picasaJsonUrl, {
			  method: 'get',
			  onSuccess: function(response) {
					statusDiv.removeClassName('working');
					if ( !response.responseText || response.responseText.startsWith('error') ) {
						statusDiv.addClassName('failure');
						statusDiv.update('Error fetching data from picasa-web-feed!');
					} else {
						statusDiv.addClassName('success');
						statusDiv.update('Successfully fetched data from picasa-web-feed.');
					}
					//alert"onSuccess "+response.status + " Server: "+response.getHeader('Server'));
					var jsonResponse = response.responseJSON;
					manager._initPicasaProcessResult(jsonResponse);
				  },
			  onFailure: function(response) {
					statusDiv.removeClassName('working');
					statusDiv.addClassName('failure');
					statusDiv.update('Error fetching data from picasa-web-feed: ' + response.status + "/" + response.statusText);
				  },
			});
	}

	manager._initPicasaProcessResult = function (jsonResponse) {
		//$('debug').update('<pre>' + dump(jsonResponse) + '</pre>');
		var title = jsonResponse.feed.title.$t;
		var entries = jsonResponse.feed.entry;
		
		$(manager.id+'_galleryHeadline').update('<b>Gallery:</b> ' + title + ' ('+entries.length+' images)');
		
		var itemOptionsList = [];
		var index = 0;
		entries.each(function (item) {
				var selected = (index++) == 0; 
				var options = {	
						preview: item.media$group.media$thumbnail[0].url,
						big: item.media$group.media$thumbnail[2].url,
						full: item.media$group.media$content[0].url,
						title: item.title.$t,
						'selected': selected};
				
				itemOptionsList.push(options);
			});
		
		manager.addItemsArray(itemOptionsList);		
	}
	
	manager.addItemsArray = function (itemOptionsList) {
		manager.bringMoverToPosition(0);
		var selectedLink;
		
		for(var i=0; i<itemOptionsList.length; i++) {
			var options = itemOptionsList[i];
			var a=manager.addItem(options);
			if ( options.selected ) selectedLink = a;
		}
		
		if ( selectedLink ) {
			manager._clickAndScrollToLinkItem(selectedLink, 'left');
		}
	}

	manager.addItem = function (options) {
		var a = new Element('a', { href: options.big, target: '_blank', rel: 'lightbox', onclick: 'return false;'});
		var img = new Element('img', { src: options.preview, title: options.title});
		if ( options.full ) a.fullUrl = options.full;
		manager.moverTop.appendChild(a);
		if ( options.selected ) img.addClassName('selected');
		a.appendChild(img);
		manager._previewImgInitFadeEvents(img, a.href);
		manager._previewLinkInitClickEvents(a);
		
		return a;
	}
	
	manager._clickAndScrollToLinkItem = function (linkItem, scrollFromDirection) {
		linkItem.fire('custom:click');
		manager.makeLinkItemVisibleInScrollBox(linkItem, manager._getDefaultIfUndefined(scrollFromDirection, 'left'));
	}

	manager._previewImgInitFadeEvents = function (imgItem, eventScopeName) {
		var eventScopeSettings = {position: 'end', scope: eventScopeName};
		imgItem.observe('mouseover', function() {if( !imgItem.hasClassName('selected') ) manager._previewSelectionAppear(imgItem, eventScopeSettings);})
		imgItem.observe('mouseout' , function() {if( !imgItem.hasClassName('selected') ) manager._previewSelectionFade  (imgItem, eventScopeSettings);})
		if( !imgItem.hasClassName('selected') ) manager._previewSelectionFade(imgItem);
	}

	manager._previewLinkInitClickEvents = function (linkItem) {
		linkItem.observe('click', function (event) {
				manager._previewLinkClickEvent(linkItem);
			});
		linkItem.observe('custom:click', function (event) {	// this is sick - can't fire "normal" click-event
				manager._previewLinkClickEvent(linkItem);
			});
	}

	manager._previewLinkClickEvent = function (linkItem) {
		var linkItemImage = linkItem.select('img').first();
		manager.bigView.hide();
		manager.bigView.src=linkItem.href;
		manager.bigView.title=linkItemImage.title;
		
		// set only current item selected
		linkItem.siblings().each(function(siblingLinkItem) {
				//alert(siblingLinkItem.up().id + "/" + siblingLinkItem.down());
				var imgItem = siblingLinkItem.select('img').first();
				if ( imgItem.hasClassName('selected') ) {
					manager._previewSelectionFade(imgItem);
					imgItem.removeClassName('selected');
				}
			});
		manager._previewSelectionAppear(linkItemImage);
		linkItemImage.addClassName('selected');
	}
	

	manager._previewSelectionFade = function (imgItem, queueSettings) {
		var settings = {to: 0.7, duration: 0.5};
		if ( typeof(queueSettings) != 'undefined' ) {
			settings = $H(settings).merge({queue: queueSettings}).toObject();
			Effect.Queues.get($H(queueSettings).get('scope')).invoke('cancel');
		}
		new Effect.Fade(imgItem, settings);
	}

	manager._previewSelectionAppear = function (imgItem, queueSettings) {
		var settings = {to: 1.0, duration: 0.2};
		if ( typeof(queueSettings) != 'undefined' ) {
			settings = $H(settings).merge({queue: queueSettings}).toObject();
			Effect.Queues.get($H(queueSettings).get('scope')).invoke('cancel');
		}
		new Effect.Appear(imgItem, settings);
	}

	manager._moverDoSeeking = function () {
		var curPos = manager.moverTop.scrollLeft;
		var seekPos = manager.moverTop.seekPosition;
		var posDiff = seekPos - curPos;
		var posCorrection = posDiff;
		if ( Math.abs(posDiff) > 2 ) posCorrection = Math.floor( posCorrection / 2 );
		var nextPos = curPos + posCorrection;

		manager.moverTop.scrollLeft = nextPos;
		if ( nextPos != seekPos) setTimeout(function () {manager._moverDoSeeking();}, 100);
		else manager.moverTop.seeking=false;
	}

	manager.moveRight = function () {
		manager.bringMoverToPosition(manager.moverTop.scrollLeft+manager.moverTop.getWidth());
	}

	manager.moveLeft = function (clickElem) {
		manager.bringMoverToPosition(manager.moverTop.scrollLeft-manager.moverTop.getWidth());
	}

	manager.bringMoverToPosition = function (position) {
		if ( position < 0 ) position = 0;
		manager.moverTop.seekPosition = position;
		if ( !manager.moverTop.seeking ) {
			manager.moverTop.seeking=true;
			manager._moverDoSeeking();
		}
	}

	manager.makeLinkItemVisibleInScrollBox = function (linkItem, direction) {
		var imgItem = linkItem.select('img').first();
		var imgOffsetLeft = imgItem.offsetLeft;
		var imgOffsetRight = imgOffsetLeft + imgItem.getWidth();
		var viewLeft = manager.moverTop.scrollLeft;
		var viewRight = viewLeft + manager.moverTop.getWidth();

		var leftBorderVisible = imgOffsetLeft > viewLeft && imgOffsetLeft < viewRight;
		var rightBorderVisible = imgOffsetRight > viewLeft && imgOffsetRight < viewRight;
		if ( !leftBorderVisible || !rightBorderVisible) {
			if ( direction == 'left' ) {
				manager.bringMoverToPosition(imgOffsetLeft);
			} else {
				manager.bringMoverToPosition(viewLeft + imgOffsetRight - viewRight);
			}
		}
	}

	manager._findActivePreviewLink = function () {
		var selectedPreviewImg = manager.galleryRoot.select('img.selected').first();
		if ( selectedPreviewImg ) return selectedPreviewImg.up();
	}

	manager.bigMagnify = function () {
		var previewLinkOfCurImage = manager._findActivePreviewLink();
		if ( previewLinkOfCurImage ) {
			var url;
			if ( previewLinkOfCurImage.fullUrl ) {
				url=previewLinkOfCurImage.fullUrl;
			} else {
				url=previewLinkOfCurImage.href;
			}
			window.open(url, "bs_fullView");
		}
	}

	manager.bigRight = function () {
		var previewLinkOfCurrentImage = manager._findActivePreviewLink();
		if ( previewLinkOfCurrentImage ) {
			var previewLinkOfNewImage = previewLinkOfCurrentImage.next();
			if ( previewLinkOfNewImage ) {
				manager._clickAndScrollToLinkItem(previewLinkOfNewImage, 'right');
			}
		}
	}

	manager.bigLeft = function () {
		var previewLinkOfCurrentImage = manager._findActivePreviewLink();
		if ( previewLinkOfCurrentImage ) {
			var previewLinkOfNewImage = previewLinkOfCurrentImage.previous();
			if ( previewLinkOfNewImage ) {
				manager._clickAndScrollToLinkItem(previewLinkOfNewImage, 'left');
			}
		}
	}

	manager.currentElemClick = function () {
		var previewLinkOfCurrentImage = manager._findActivePreviewLink();
		if ( previewLinkOfCurrentImage ) {
			manager._clickAndScrollToLinkItem(previewLinkOfCurrentImage, 'left');
		}
	}
	
	manager._getDefaultIfUndefined = function (value, defaultValue) {
		return typeof(value) != 'undefined' ? value : defaultValue;
	}

	return manager;
}


// helper-functions directly called from event-handlers outside class

function findManager(containedElem) {
	return containedElem.up('.image-gallery').galleryManager;
}

function dump(arr,level) {
	var dumped_text = "";
	if(!level) level = 0;
	
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) level_padding += "    ";
	
	if(typeof(arr) == 'object') { //Array/Hashes/Objects 
		for(var item in arr) {
			var value = arr[item];
			
			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "' ...\n";
				dumped_text += dump(value,level+1);
			} else if(typeof(value) != 'function') {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}
