if (('undefined' == typeof(WF)) || ('undefined' == typeof(WF.Imagegallery)) || ('undefined' == typeof(WF.Imagegallery.GalleryPanel))) {
	// Define gallery panel for webfront (if it is not defined already

	Ext.namespace('WF.Imagegallery');

	WF.Imagegallery.GalleryPanel = Ext.extend(Ext.Panel, {
		galleryInfo: {
			currentView: null,
			enableSlideshow: null,
			autostartSlideshow: null,
			autostartSlideshowDelay: null,
			thumbRowNumber: 3,
			maxPreviewImageWidth: 400
		},
		header: false,
		border: false,
		iconImageSize: 20,
		thumbImageSize: 100,
		previewImageSize: 400,
		imageResizeServiceUrl: 'http://i.flexiweb.no/',
		showTopNavSetChangeButtons: null,
		detailViewTpl:
			'<div class="detail-view">' +
				'<h3>{title} <a href="#{[this.scope.createHashString()]}" class="back-link">(Vis oversikt)</a></h3>' +
				'<div class="top-nav">' +
					'<tpl if="this.scope.showTopNavSetChangeButtons">' +
						'<p class="prev-set">' + '<a class="{[this.scope.prevPossible() ? "" : "disabled"]}" href="" onclick="return false" title="Forrige sett">Forrige sett</a></p>' +
					'</tpl>' +
					'<p class="prev">' + '<a class="{[this.scope.changeCurrentImagePossible(false) ? "" : "disabled"]}" href="" onclick="return false" title="Forrige">Forrige</a></p>' +
					'<ul class="thumb-nav">' +
					'<tpl for="images">' +
						'<li><img src="{values.icon_url}" width="{this.scope.iconImageSize}" height="{this.scope.iconImageSize}" alt="" /></li>' +
					'</tpl>' +
					'</ul>' +
					'<tpl if="this.scope.showTopNavSetChangeButtons">' +
						'<p class="next-set">' + '<a class="{[this.scope.nextPossible() ? "" : "disabled"]}" href="" onclick="return false" title="Neste sett">Neste sett</a></p>' +
					'</tpl>' +
					'<p class="next">' + '<a class="{[this.scope.changeCurrentImagePossible(true) ? "" : "disabled"]}" href="" onclick="return false" title="Neste">Neste</a></p>' +
				'</div>' +
				'<tpl for="current">' +
				'<div class="fig-wrap">' +
				'<div class="figure">' +
					'<div><img src="{values.preview_url}" alt="" /></div>' +
						'<ul class="arrow-nav">' +
							'<li class="prev">' +
								'<tpl if="this.scope.changeCurrentImagePossible(false)">' +
									'<a href="" onclick="return false" title="Forrige">Forrige</a>' +
								'</tpl>' +
							'</li>' +
							'<li class="next">' +
								'<tpl if="this.scope.changeCurrentImagePossible(true)">' +
									'<a href="" onclick="return false" title="Neste">Neste</a>' +
								'</tpl>' +
							'</li>' +
						'</ul>' +
					'</div>' +
				'</div>' +
				'<h3>{name}</h3>' +
				'<div class="desc"><p>{[values.description ? values.description : ""]}</p></div>' +
				'</tpl>' +
			'</div>',
		thumbViewTpl:
			'<h3>{title}</h3>' +
			'<div class="thumbs-view">' +
				'<div class="images">' +
					'<tpl for="images">' +
						'<div class="figure thumb">' +
							'<img src="{values.thumbnail_url}" alt="" width="{this.scope.thumbImageSize}" height="{this.scope.thumbImageSize}" />' +
						'</div>' +
					'</tpl>' +
				'</div>' +
				'<tpl if="(this.scope.prevPossible() || this.scope.nextPossible())">' +
					'<div class="bottom-nav">' +
						'<p class="prev">' +
							'<tpl if="this.scope.prevPossible()"><a href="" onclick="return false"></tpl>' +
								'&laquo; forrige' +
							'<tpl if="this.scope.prevPossible()"></a></tpl>' +
						'</p>' +
						'<p class="desc">Side {page} av {pages}</p>' +
						'<p class="next{[values.page == values.pages ? " disabled" : ""]}">' +
							'<tpl if="this.scope.nextPossible()"><a href="" onclick="return false"></tpl>' +
								'neste &raquo;' +
							'<tpl if="this.scope.nextPossible()"></a></tpl>' +
						'</p>' +
					'</div>' +
				'</tpl>' +
			'</div>',
		tpl: null,

		// Stores HTML node for images in gallery
		galleryImages: null,
		galleryImageSelector: null,
		galleryData: {
			id: this.id,
			title: this.title,
			page: 1,
			pages: 1,
			imagesPerPage: 15,
			navigationImagesStartIndex: 0,
			navigationImagesNumber: 15,
			galleryImages: [],
			images: [],
			current: {
				name: '',
				url: '#',
				description: '',
				galleryIndex: null
			}
		},

		initComponent: function() {
			// Called during component initialization
			this.galleryImages = new Ext.CompositeElementLite();
			if (null == this.showTopNavSetChangeButtons) {
				this.showTopNavSetChangeButtons = true;
			}

			Ext.applyIf(this.galleryInfo, {
				currentView: null,
				enableSlideshow: null,
				autostartSlideshow: null,
				autostartSlideshowDelay: null,
				thumbRowNumber: 3,
				maxPreviewImageWidth: 400
			});
			// Get width of a main content div and set that as a preview image width
			//value stated in XML config file is corrected by 2 pixels
			this.previewImageSize = parseInt(this.galleryInfo.maxPreviewImageWidth) + parseInt(2);
			var calculatedThumbsPerRow = parseInt((this.previewImageSize + parseInt(5)) / (this.thumbImageSize + 9));

			// Calculate number of max top navigation icon number
			var topNavWidth = this.showTopNavSetChangeButtons ? (this.previewImageSize - 107) : (this.previewImageSize - 44);
			var calculatedTopNavCount = parseInt(topNavWidth / (this.iconImageSize + 9));

			Ext.applyIf(this.galleryData, {
				title: this.title,
				page: 1,
				pages: 1,
				imagesPerPage: calculatedThumbsPerRow * this.galleryInfo.thumbRowNumber,
				navigationImagesStartIndex: 0,
				navigationImagesNumber: calculatedTopNavCount,
				galleryImages: [],
				images: [],
				current: {
					name: '',
					url: '#',
					description: '',
					galleryIndex: null
				}
			});
			// Check if top naav set change buttons should be visible
			if (this.galleryData.navigationImagesNumber >= this.galleryData.galleryImages.length) {
				this.showTopNavSetChangeButtons = false;
			}


			if (0 < this.galleryData.galleryImages.length) {
				this.galleryData.pages = parseInt(((this.galleryData.galleryImages.length - 1) / this.galleryData.imagesPerPage)) + 1;
				this.galleryData.current = this.galleryData.galleryImages[0];
				this.galleryData.startIndex = 0;
			}

			this.getHistory();

			// Initialize image selector
			this.galleryImageSelector = ('thumb' == this.galleryInfo.currentView) ? 'div.thumb' : 'li:has(img)';

			// Select appropriate tpl for current view
			this.selectTpl();

			// Call parent (required)
			WF.Imagegallery.GalleryPanel.superclass.initComponent.apply(this, arguments);

		},
		onRender: function() {
			WF.Imagegallery.GalleryPanel.superclass.onRender.apply(this, arguments);

			this.body.addListener('dblclick', this.onBodyDblClick, this);
			this.body.addListener('click', this.onBodyClick, this, {buffer: 200});

			// Hook in left and right keyboard nav
			var nav = new Ext.KeyNav(Ext.getDoc(), {
				'left': function(e){
					this.changeCurrentImage(false);
				},
				'right': function(e){
					this.changeCurrentImage(true);
				},
				scope : this
			});

			this.refreshContent();
		},
		getHash: function() {
			var str = document.location.hash;
			return str.substring(1, str.length); // Cut the '#'
		},
		getHistory: function() {
			var urlInfo = Ext.urlDecode(this.getHash());
			if (urlInfo) {
				var id = this.galleryData.id;
				if (urlInfo['img' + id]) {
					this.galleryData.current = this.galleryData.galleryImages[Number(urlInfo['img' + id])];
					this.galleryData.navigationImagesStartIndex = parseInt(Number(urlInfo['img' + id]) / this.galleryData.navigationImagesNumber) * this.galleryData.navigationImagesNumber;
				}
				if (urlInfo['view' + id]) {
					this.galleryInfo.currentView = urlInfo['view' + id];
				}
				if (urlInfo['page' + id]) {
					this.galleryData.page = urlInfo['page' + id];
				}
			}
		},
		createHashString: function() {
			var urlInfo = Ext.urlDecode(this.getHash());
			var id = this.galleryData.id;
			if ('image' == this.galleryInfo.currentView) {
				urlInfo['img' + id] = this.galleryData.current.galleryIndex;
				urlInfo['view' + id] = this.galleryInfo.currentView;
				delete urlInfo['page' + id];
			} else {
				urlInfo['page' + id] = this.galleryData.page;
				urlInfo['view' + id] = this.galleryInfo.currentView;
				delete urlInfo['img' + id];
			}
			return Ext.urlEncode(urlInfo);
		},
		getImageUrl: function(originalUrl, imageSize) {
			return this.imageResizeServiceUrl + 'x' + imageSize + '/x' + imageSize + '/' + originalUrl;
		},
		getPreviewImageUrl: function(originalUrl, imageSize) {
			return this.imageResizeServiceUrl + imageSize + '/' + parseInt(0.75 * imageSize) + '/' + originalUrl;
		},

		// Private functions
		selectTpl: function() {
			Ext.destroy(this.tpl);
			if ('thumb' == this.galleryInfo.currentView) {
				this.tpl = new Ext.XTemplate(this.thumbViewTpl, {scope: this});
				this.tpl = this.tpl.compile();
				return;
			}
			if ('image' == this.galleryInfo.currentView) {
				this.tpl = new Ext.XTemplate(this.detailViewTpl, {scope: this});
				this.tpl = this.tpl.compile();
				return;
			}
		},
		refreshContent: function() {
			document.location.hash = this.createHashString();
			// Update images that should be displayed in gallery
			var startIndex = 0;
			var endIndex = this.galleryData.imagesPerPage;
			if ('thumb' == this.galleryInfo.currentView) {
				startIndex = (this.galleryData.page - 1) * this.galleryData.imagesPerPage;
				endIndex = this.galleryData.page * this.galleryData.imagesPerPage;
			} else {
				startIndex = this.galleryData.navigationImagesStartIndex;
				endIndex = startIndex + this.galleryData.navigationImagesNumber;
			}

			this.galleryData.images = this.galleryData.galleryImages.slice(startIndex, endIndex);

			// Show images for current page
			this.tpl.overwrite(this.body, this.galleryData);

			// Update current local gallery image collection
			this.galleryImages.clear();
			this.galleryImages.fill(Ext.query(this.galleryImageSelector, this.getEl().dom));
			this.updateIndexes();

			this.galleryImages.each(function(el) {
				el.removeClass('active');
			});
			var activeItem = this.galleryImages.item(this.galleryData.current.galleryIndex - startIndex);
			if (activeItem) {
				activeItem.addClass('active');
			}

			var wrap = $$("#main .detail-view").first();
			if (wrap) {
				wrap.setStyle({width: this.previewImageSize + 'px'});
				var width = (this.previewImageSize - 2);
				var height = parseInt(this.previewImageSize * 0.75);
				var figwrap = $$("#main .detail-view .fig-wrap").first();
				$$("#main .detail-view .fig-wrap").each(function(figwrap) {
					figwrap.setStyle({
						width: width + 'px',
						height: height + 'px'
					});
				});
				//Links should only get a height
				$$("#main .detail-view .arrow-nav li a").each(function(element) {
					element.setStyle({
						height: height + 'px'
					});
				});
			}


		},
		updateIndexes : function() {
			var images = this.galleryImages.elements;
			for(var i = 0; i < images.length; i++) {
				images[i].viewIndex = i;
			}
		},
		dblClickTriggered: false,
		onBodyClick: function(e, target) {
			if (this.dblClickTriggered) {
				this.dblClickTriggered = false;
				return;
			}

			var prevEl = e.getTarget('p.prev', this.getEl());
			if (prevEl && e.within(prevEl)) {
				if ('image' == this.galleryInfo.currentView) {
					this.changeCurrentImage(false);
				} else {
					this.onPrevClick();
				}
				return;
			}
			var nextEl = e.getTarget('p.next', this.getEl());
			if (nextEl && e.within(nextEl)) {
				if ('image' == this.galleryInfo.currentView) {
					this.changeCurrentImage(true);
				} else {
					this.onNextClick();
				}
				return;
			}

			var imageEl = e.getTarget(this.galleryImageSelector, this.getEl());
			if (imageEl) {
				this.onGalleryImageClick(imageEl, true);
				return;
			}

			if ('image' != this.galleryInfo.currentView) {
				return;
			}

			var prevSetEl = e.getTarget('p.prev-set', this.getEl());
			if (prevSetEl && e.within(prevSetEl)) {
				this.onPrevClick();
				return;
			}
			var nextSetEl = e.getTarget('p.next-set', this.getEl());
			if (nextSetEl && e.within(nextSetEl)) {
				this.onNextClick();
				return;
			}

			var backEl = e.getTarget('a.back-link', this.getEl());
			if (backEl) {
				this.onBackClick();
				return;
			}

			// If it is a detail view check for current displayed image prev/next buttons
			var prevEl = e.getTarget('li.prev', this.getEl());
			if (prevEl && e.within(prevEl)) {
				this.changeCurrentImage(false);
				return;
			}
			var nextEl = e.getTarget('li.next', this.getEl());
			if (nextEl && e.within(nextEl)) {
				this.changeCurrentImage(true);
				return;
			}
		},
		onBodyDblClick: function(e, target) {
			e.stopEvent();
			var imageEl = e.getTarget(this.galleryImageSelector, this.getEl());
			var prevEl = e.getTarget('li.prev', this.getEl());
			var nextEl = e.getTarget('li.next', this.getEl());
			if ((prevEl && e.within(prevEl)) || (nextEl && e.within(nextEl)) || imageEl) {
				if (imageEl && ('image' == this.galleryInfo.currentView)) {
					this.onGalleryImageClick(imageEl, false);
				}
				var url = ('image' == this.galleryInfo.currentView) ? this.galleryData.current.url : this.galleryData.images[imageEl.viewIndex].url;
				window.open(url, 'previewImageGallery');
				this.dblClickTriggered = true;
			}
		},
		changeCurrentImagePossible: function(onNext) {
			if (onNext) {
				return (this.galleryData.current.galleryIndex < (this.galleryData.galleryImages.length - 1));
			} else {
				return (0 < this.galleryData.current.galleryIndex);
			}
		},
		changeCurrentImage: function(onNext) {
			if (!this.changeCurrentImagePossible(onNext)) {
				return false;
			}

			var newImageIndex = onNext ? (this.galleryData.current.galleryIndex + 1) : (this.galleryData.current.galleryIndex - 1);

			// Set the startindex to the relevant page
			this.galleryData.navigationImagesStartIndex = parseInt(newImageIndex / this.galleryData.navigationImagesNumber) * this.galleryData.navigationImagesNumber;

			this.galleryData.current = this.galleryData.galleryImages[newImageIndex];
			this.refreshContent();
		},
		prevPossible: function() {
			if (('thumb' == this.galleryInfo.currentView) && (1 >= this.galleryData.page)) {
				return false;
			}

			if (('image' == this.galleryInfo.currentView) && (0 >= this.galleryData.navigationImagesStartIndex)) {
				return false;
			}

			return true;
		},
		onPrevClick: function() {
			if (!this.prevPossible()) {
				return false;
			}

			if ('thumb' == this.galleryInfo.currentView) {
				this.galleryData.page--;
			}
			if ('image' == this.galleryInfo.currentView) {
				this.galleryData.navigationImagesStartIndex -= this.galleryData.navigationImagesNumber;

			}

			this.refreshContent();
		},
		onBackClick: function() {
			if ('image' == this.galleryInfo.currentView) {
				this.galleryInfo.currentView = 'thumb';
				this.galleryImageSelector = 'div.thumb';
				this.galleryData.page = parseInt(Number(this.galleryData.current.galleryIndex) / this.galleryData.imagesPerPage) + 1;
				this.selectTpl();
			}
			this.refreshContent();
		},
		nextPossible: function() {
			if (('thumb' == this.galleryInfo.currentView) && (this.galleryData.page >= this.galleryData.pages)) {
				return false;
			}

			if (('image' == this.galleryInfo.currentView) && ((this.galleryData.navigationImagesStartIndex + this.galleryData.navigationImagesNumber) >= this.galleryData.galleryImages.length)) {
				return false;
			}

			return true;
		},
		onNextClick: function(evt) {
			if (!this.nextPossible()) {
				return false;
			}

			if ('thumb' == this.galleryInfo.currentView) {
				this.galleryData.page++;
			}
			if ('image' == this.galleryInfo.currentView) {
				this.galleryData.navigationImagesStartIndex += this.galleryData.navigationImagesNumber;
			}

			this.refreshContent();
		},
		onGalleryImageClick: function(imageEl, forceOpenFullImage) {
			if ('thumb' == this.galleryInfo.currentView) {
				this.galleryData.current = this.galleryData.images[imageEl.viewIndex]
				// Change view type and refresh tpl that should be used
				var currentNavPage = parseInt(this.galleryData.current.galleryIndex / this.galleryData.navigationImagesNumber);
				this.galleryData.navigationImagesStartIndex = currentNavPage * this.galleryData.navigationImagesNumber;

				this.galleryInfo.currentView = 'image';
				this.galleryImageSelector = 'li:has(img)';
				this.selectTpl();
				this.refreshContent();
			} else if (this.galleryData.current != this.galleryData.images[imageEl.viewIndex]) {
				this.galleryData.current = this.galleryData.images[imageEl.viewIndex];
				this.refreshContent();
			} else if (forceOpenFullImage) {
				window.open(this.galleryData.current.url, 'previewImageGallery');
			}
		}
	});
}