/**
 * THE ALMIGHTY PHOTOBROWSER!
 * ALL GLORY TO THE HYPNO-ARON
 * 
 * Versie 1.0
 */
var Photobrowser = Class.create({
	
	initialize: function() {
	
		this.reset();
	
		this.options = Object.extend({
			beforeRender: function() {},
			afterRender: function() {},
			hasOverlay: true,
			getTitle: undefined
		}, arguments[0]|| {});
		
		this.templateOptions = Object.extend({
			photoBrowserId: 'photobrowser-container',
			classNameThumb: 'photobrowser-thumb',
			classNameThumbSlider: 'photobrowser-slider',
			classNameContainer: 'photobrowser-container',
			classNameContainerInner: 'photobrowser-container-inner',
			classNamePhotoContainer: 'photobrowser-container-photos',
			classNameTextContainer: 'photobrowser-container-text',
			idSliderPrev: 'photobrowser-button-prev',
			idSliderNext: 'photobrowser-button-next',
			idPhotoContentList: 'photobrowser-photocontent',
			classNameClose: 'photobrowser-button-close',
			thumbnailWidth: 180,
			thumbsPerPage: 3,
			thumbPadding: 5
		}, arguments[0] || {});

		// Event handlers initialiseren
		this._initDefaultEvents();
	},
	
	reset: function() {
		this._rendered = false;
		this._element = '';
		this._overlay = '';
		this._photos = [];
		this._index = 0;
		this._thumbPage = 1;
		this._thumbnails = [];
		this._inTransition = false;
		this._dimensions = {};	
	},
	
	/**
	 * Link hrefs verkrijgen
	 * 
	 */
	getPhotos: function() {
		if (this._photos.length <= 0) {
			var photos = [];
			$$('.' + this.templateOptions.classNameThumb).each(function(element) { 
				photos.push(element.href);
			});
			this._photos = photos;
		}
		return this._photos;
	},
	
	/**
	 * Thumbnail srcs ophalen
	 * 
	 */
	getThumbnails: function() {
		if (this._thumbnails.length <= 0) {
			var photos = [];
			$$('.' + this.templateOptions.classNameThumb).each(function(element) { 
				var images = element.getElementsByTagName('img');
				if (images.length > 0) {
					photos.push(images[0].src);
				}
			});
			this._thumbnails = photos;
		}
		return this._thumbnails;
	},
	
	getDimensions: function() {
		if (typeof(this._dimensions.width) == 'undefined') {
			this._dimensions = $$('div.' + this.templateOptions.classNamePhotoContainer).first().getDimensions();
		}
		return this._dimensions;
	},
	
	/**
	 * Element renderen
	 * 
	 */
	render: function() {
		if (this._rendered) return false;
		
		// before render hook
		this._beforeRenderInternal();
		this.options.beforeRender();
		
		///////////////////////////////
		// START DOM TEMPLATING MADNESS
		///////////////////////////////
		
		var outerTemplate = new Template(
			'<div id="#{photoBrowserId}" class="#{classNameContainer}">' +
				'<div class="#{classNameContainerInner}">' +
					'<div class="#{classNameTextContainer}" style="display:#{textDisplay};">#{text}</div>' +
					'<div class="#{classNamePhotoContainer}">#{photos}</div>' +
					'<a href="prev" id="#{idSliderPrev}"></a>' +					
					'<div class="#{classNameThumbSlider}" style="width:#{viewportSize}px;">#{thumbs}</div>' +
					'<a href="next" id="#{idSliderNext}"></a>' +
				'</div>' +
				'<div class="#{classNameClose}"><a href="#">Sluiten</a></div>' +
			'</div>'
		);
		
		// fotos genereren
		var photos = this.getPhotos();
		var photoContent = '<ul id="' + this.templateOptions.idPhotoContentList + '">';
		for (var i = 0; i < photos.length; i++) {
			photoContent += '<li><img src="' + photos[i] + '" alt="" /></li>';
		}
		photoContent += '</ul>';
		
		// thumbs genereren
		// totale breedte berekenen
		var totalWidth = photos.length * this.templateOptions.thumbnailWidth;
		var thumbContent = '<ul style="width:' + totalWidth + 'px;">';
		var thumbs = this.getThumbnails();
		for (var i = 0; i < thumbs.length; i++) {
			thumbContent += '<li style="width:' + this.templateOptions.thumbnailWidth + 'px;padding:' + this.templateOptions.thumbPadding + 'px;"><a href="#"><img src="' + thumbs[i] + '" alt="" /></a></li>';
		}
		thumbContent += '</ul>';
		
		var title = (typeof(this.options.getTitle) == 'function') ? this.options.getTitle() : this._getTitleDefault();
		
		var renderedTemplate = outerTemplate.evaluate(Object.extend({
			viewportSize: this.getViewPortWidth(),
			photos: photoContent,
			thumbs: thumbContent,
			text: title,
			textDisplay: (title == '') ? 'none' : 'block'
		}, this.templateOptions));
		
		///////////////////////////////
		// END DOM TEMPLATING MADNESS
		///////////////////////////////
		
		if (this.options.hasOverlay) {
			this._overlay = new Overlay();
		}
		
		var body = document.getElementsByTagName("body").item(0);
		$(body).insert(renderedTemplate);
		
		$(this.templateOptions.idPhotoContentList).setStyle({
			width: photos.length * this.getDimensions().width + 'px'
		});
		
		// aan de hand van de index de juiste foto + pagina weergeven
		if (this._index > 0) {
			var ul = $(this.templateOptions.idPhotoContentList);
			$(ul).setStyle({
				left: '-' + this._index * this.getDimensions().width + 'px'
			});
			var page = Math.ceil( (this._index+1) / this.templateOptions.thumbsPerPage);
			if (page > 1) {
				var ul = $$('div.' + this.templateOptions.classNameThumbSlider + ' ul').first();
				$(ul).setStyle({
					left: '-' + (this.getViewPortWidth() * (page - 1) ) + 'px'
				});
			}
		}
		
		Position.center(this.templateOptions.photoBrowserId);
		
		// after render hooks
		this._afterRenderInternal();
		this.options.afterRender();
		
		return true;
	},
	
	/**
	 * Breedte van de viewport berekenen
	 */
	getViewPortWidth: function() {
		return ( (this.templateOptions.thumbnailWidth + (this.templateOptions.thumbPadding * 2)) * this.templateOptions.thumbsPerPage);		
	},
	
	/**
	 * Totale aantal thumb pagina's berekenen
	 */
	getTotalPages: function() {
		return Math.ceil(this.getPhotos().length / this.templateOptions.thumbsPerPage);
	},
	
	destroy: function() {
		// remove overlay
		if (this.options.hasOverlay) {
			this._overlay.remove();
		}
		// remove browser
		$(this.templateOptions.photoBrowserId).remove();
		// reset variables
		this.reset();
	},
	
	/**
	 * Index van een specifieke thumbnail vaststellen
	 */
	getIndex: function(element) {
		var photos = this.getThumbnails();
		for (var i = 0; i < photos.length; i++) {
			if (element.src == photos[i]) {
				return i;
			}
		}
	},
	
	/**
	 * Pagina-element ophalen aan de hand van index
	 */
	getPageElementByIndex: function(index) {
		var result = false;
		$$('.' + this.templateOptions.classNameThumb).each(function(element, key) {
			if (key == index) {
				result = element;
				throw $break;
			}
		}.bind(this));
		return result; 
	},
	
	_updateTitle: function() {
		var title = (typeof(this.options.getTitle) == 'function') ? this.options.getTitle() : this._getTitleDefault();
		console.log(title);
		var element = $$('.' + this.templateOptions.classNameTextContainer).first();
		console.log(element);
		if (title && title != '') {
			element.update(title);
			element.show();
		} else {
			element.update();
			element.hide();
		}
	},
	
	/**
	 * Standaard events instellen
	 * 
	 */
	_initDefaultEvents: function() {
		// thumbnails
		$$('.' + this.templateOptions.classNameThumb).each(function(element) {
			element.observe('click', this._eventThumbClick.bind(this));
		}.bind(this));
	},
	
	/**
	 * Standaard thumbnail klik (op pagina)
	 */
	_eventThumbClick: function(event) {
		event.preventDefault();
		var anchor = Event.findElement(event, 'a');
		var element = $(anchor.getElementsByTagName('img')[0]); 
		var index = this.getIndex(element);
		this._index = index;
		this._thumbPage = Math.ceil(index / this.templateOptions.thumbsPerPage);
		if (this._thumbPage == 0) this._thumbPage = 1;
		this.render();
	},
	
	/**
	 * Browser thumb event
	 */
	_eventBrowserThumbClick: function(event) {
		event.preventDefault();
		if (this._inTransition) return false;		
		// vaststellen wat de index van het aangeklikte element is
		var index = this.getIndex(Event.element(event));
		var ul = $(this.templateOptions.idPhotoContentList);
		var offset = (this._index - index) * this.getDimensions().width;
		new Effect.Move(ul, {
			x: offset,
			duration: 0.3,
			afterFinish: function() {
				this._inTransition = false;
				this._index = index;
				this._afterThumbClickInternal();
			}.bind(this)
		});		
	},
	
	/**
	 * Vorige thumbnail event
	 */
	_eventBrowserThumbPrev: function(event) {
		event.preventDefault();
		if (this._inTransition) return false;
		if (this._thumbPage == 1) return false;
		this._inTransition = true;
		var ul = $$('div.' + this.templateOptions.classNameThumbSlider + ' ul').first();
		new Effect.Move(ul, {
			x: (this.getViewPortWidth()),
			duration: 0.3,
			afterFinish: function() {
				this._inTransition = false;
				this._thumbPage--;
				this._afterSlideInternal();
			}.bind(this)
		});
	},
	
	/**
	 * Volgende thumbnail event
	 */
	_eventBrowserThumbNext: function(event) {
		event.preventDefault();
		if (this._inTransition) return false;
		if (this._thumbPage == this.getTotalPages()) return false;
		this._inTransition = true;
		var ul = $$('div.' + this.templateOptions.classNameThumbSlider + ' ul').first();
		var offset = ul.style.left;
		new Effect.Move(ul, {
			x: -(this.getViewPortWidth()),
			duration: 0.3,
			afterFinish: function() {
				this._inTransition = false;
				this._thumbPage++;
				this._afterSlideInternal();
			}.bind(this)			
		});
	},
	
	/**
	 * Photobrowser sluit event
	 * 
	 */
	_eventBrowserClose: function(event) {
		event.preventDefault();
		this.destroy();
	},
	
	_updateNavElements: function() {
		if (this._thumbPage == 1) {
			$(this.templateOptions.idSliderPrev).setStyle({ visibility: 'hidden' });
		} else {
			$(this.templateOptions.idSliderPrev).setStyle({ visibility: 'visible' });
		}
		if (this._thumbPage == this.getTotalPages()) {
			$(this.templateOptions.idSliderNext).setStyle({ visibility: 'hidden' });
		} else {
			$(this.templateOptions.idSliderNext).setStyle({ visibility: 'visible' });
		}		
	},
	
	/**
	 * Interne before render hook
	 * 
	 */
	_beforeRenderInternal: function() {},
	
	/**
	 * Interne after render hook
	 */
	_afterRenderInternal: function() {
		// event handlers in de gerenderde code initialiseren
		$(this.templateOptions.idSliderPrev).observe('click', this._eventBrowserThumbPrev.bindAsEventListener(this));
		$(this.templateOptions.idSliderNext).observe('click', this._eventBrowserThumbNext.bindAsEventListener(this));
		$$('.' + this.templateOptions.classNameClose + ' a').first().observe('click', this._eventBrowserClose.bindAsEventListener(this));
		$$('.' + this.templateOptions.classNameThumbSlider + ' ul li a').each(function(element) {
			$(element).observe('click', this._eventBrowserThumbClick.bindAsEventListener(this));
		}.bind(this));
		this._updateNavElements();
	},
	
	_afterSlideInternal: function() {
		this._updateNavElements();
	},
	
	_afterThumbClickInternal: function() {
		this._updateTitle();
	},
	
	_getTitleDefault: function() {
		var element = this.getPageElementByIndex(this._index);
		if ($(element) && $(element).title) {
			return $(element).title;
		}
		return '';
	}
});


/////////////////////////////////////////////////////////////////////////////////////////////////
// COMPATIBILITY FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////////

if (typeof(console) == 'undefined') {
    var console = {
        log: function(){}
    };
}

if (typeof(getPageSize) == 'undefined') {
	function getPageSize() {
	
		var xScroll, yScroll;
	
		if (window.innerHeight && window.scrollMaxY) {
			xScroll = document.body.scrollWidth;
			yScroll = window.innerHeight + window.scrollMaxY;
		} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}
	
		var windowWidth, windowHeight;
		if (self.innerHeight) {	// all except Explorer
			windowWidth = self.innerWidth;
			windowHeight = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if (document.body) { // other Explorers
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}
	
		// for small pages with total height less then height of the viewport
		if(yScroll < windowHeight){
			pageHeight = windowHeight;
		} else {
			pageHeight = yScroll;
		}
	
		// for small pages with total width less then width of the viewport
		if(xScroll < windowWidth){
			pageWidth = windowWidth;
		} else {
			pageWidth = xScroll;
		}
	
	
		arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight);
		return arrayPageSize;
	}
}

function showSelectBoxes(){
	var selects = document.getElementsByTagName("select");
	for (i = 0; i != selects.length; i++) {
		selects[i].style.visibility = "visible";
	}
}

function hideSelectBoxes(){
	var selects = document.getElementsByTagName("select");
	for (i = 0; i != selects.length; i++) {
		selects[i].style.visibility = "hidden";
	}
}

var Overlay = Class.create();

Overlay.prototype = {
	
	overlay: undefined,
	
	initialize: function() {
		
		this.options = Object.extend({
			afterCreation: false
		}, arguments[0] || {});
		
		var b = document.getElementsByTagName("body").item(0);
		this.overlay = document.createElement("div");
		this.overlay.setAttribute('id','overlay');
		this.overlay.style.display = 'none';
		this.overlay.style.position = 'absolute';
		this.overlay.style.top = '0';
		this.overlay.style.left = '0';
		this.overlay.style.zIndex = '90';
	 	this.overlay.style.width = '100%';
		b.insertBefore(this.overlay, b.firstChild);
		
		hideSelectBoxes();
	
		var arrayPageSize = getPageSize();
		this.overlay.style.height = (arrayPageSize[1] + 'px');
		$(this.overlay).setOpacity(0.8);
		
		Effect.BlindDown(this.overlay, {
			duration: 0.3,
			afterFinish: (function() {
				if (this.options.afterCreation) {
					this.options.afterCreation.bind(this)();
				}
			}).bind(this)
		});
	},
	
	remove: function() {
		new Effect.BlindUp(this.overlay, { 
			duration: 0.3,
			afterFinish: (function() { 
			    try {
    				this.overlay.remove();
			    } catch (e) { }
				showSelectBoxes();
			}).bind(this)
		});
		
	}	

};

Position.center = function(element) {
	element = $(element);
    if (element.hasClassName('centered')) return;
    var options = Object.extend({
        zIndex: 999,
        update: false
    }, arguments[1] || {});
    element = $(element)
    if(!element._centered) {
        Element.setStyle(element, {position: 'absolute', zIndex:options.zIndex });
        element._centered = true;
    }
    var dims = Element.getDimensions(element);
    Position.prepare();
    var winWidth = self.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0;
    var winHeight = self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0;
    var offLeft = (Position.deltaX + Math.floor((winWidth-dims.width)/2));
    var offTop = (Position.deltaY + Math.floor((winHeight-dims.height)/2));
    element.style.top = ((offTop != null && offTop > 0) ? offTop : '0')+ 'px';
    element.style.left = ((offLeft != null && offLeft > 0) ? offLeft :'0') + 'px';
    element.addClassName('centered');
    if(options.update) {
        Event.observe(window, 'resize', function(evt) {
            Position.center(element);
        }, false);
        Event.observe(window, 'scroll', function(evt) {
            Position.center(element);
        }, false);
    }
}

Element.addMethods();

