var galleries = [];

function redrawGalleries(filter)
{
	for(var i = 0; i < galleries.length; i++)
	{
		galleries[i].redraw(filter);
	}
}

(function($) {
    $.fn.extend({
		loopingGallery: function(options) {
			
			return this.each(function(){
				var o = {
					gallery: null,
					items: [],
					dragIcon: null,
					dragIconDisplayed: false,
					visibleItems: [],
					lastDragValue: 0,
					itemsLoaded: 0,
					stepCount: 0,
					negativeVelocity: false,
					galleryMoved: false,
					currentIndex: 0,
					movePoints: [],
					filter: 'all',
					origCount: 0,
					addedItems: 0,
					animating: false,
					MAX_POSITION_VELOCITY: 1000,
					MAX_POSITION_TIME: 100,
					ITEM_SIZE: 222,
					offset: 0,
					timeOffset: 0,
					init : function (obj, opts) 
					{
						galleries.push(o);
						o.gallery = jQuery(obj);
						o.dragIcon = o.gallery.parent().children('.dragDemo');
						o.dragIcon.hide();
						o.origCount = o.gallery.children().length;
						o.gallery.mousedown(o.onMouseDown);
						if(obj.addEventListener != null) obj.addEventListener('touchstart', o.onMouseDown,true);
						
						var items = o.gallery.children().clone();
						
						items.appendTo(o.gallery);
						while(o.gallery.children().length < 50)
						{
							items.clone().appendTo(o.gallery);
						}
						
						o.reverseHover = opts.reverseHover;
						
						var items = o.gallery.children();
						for (var i = 0; i < items.length; i++){
							var itm = createGalleryItem($(items[i]),o,i,o.reverseHover);
							o.items[i] = itm;
						};
						
						o.offset = opts.offset;
						o.timeOffset = opts.timeOffset;
						o.filter = (opts.startFilter != null && opts.startFilter != '') ? opts.startFilter : 'all';
						
						o.addItems(0,o.offset, o.timeOffset);
						o.showDrag();
					},
					addItems : function (startPoint, offset, tOffset) {
						o.animating = false;
						if(!offset) offset = 0;
						
						var pos = startPoint - offset;
						var toPos = -800 - offset;
						
						o.negativeVelocity = true;
						o.visibleItems = [];
						
						var numItems = o.items.length;
						
						//Below there is logic to calculate how many duplicates of a set of content is required
						//This is done by recording the first item of the set
						//Once the required number of items are in the DOM, a marker is set to say this is the last cycle
						//Once the first item comes around again with this marker (stopAfterThisCycle) then cycleDone is set to true and items are no longer added
						
						o.addedItems = 0;
						var firstItem = null;
						var stopAfterThisCycle = false;
						var cycleDone = false;
						for (var i = 0; i < numItems; i++){
							var itm = o.items[i];
							itm.obj.stop();
							if((o.filter == "all" || itm.obj.hasClass(o.filter)) && !cycleDone)
							{
								if(firstItem == null) firstItem = itm;
								if(firstItem == itm && stopAfterThisCycle) {
									cycleDone = true;
									itm.enabled = false;
									itm.content.hide();
									itm.obj.remove();
								} else {
									itm.obj.appendTo(o.gallery);
									
									itm.enabled = true;
									itm.content.show();
									o.visibleItems.push(itm);
									itm.obj.stop();
									itm.obj.css('left', pos.toString() + "px");
									itm.obj.css('position','absolute');
									itm.pos = toPos;
									itm.addToStage();
									o.addedItems += 1;
									itm.obj.animate({left: toPos}, {duration: 2000 + tOffset, easing: 'easeOutQuint', step: o.onStep, complete: o.forceCheckPositions});
									
									pos += o.ITEM_SIZE;
									toPos += o.ITEM_SIZE;
									if(o.visibleItems.length > 16) {
										stopAfterThisCycle = true;
									}
								}
								
							}
							else
							{
								itm.enabled = false;
								itm.content.hide();
								itm.obj.remove();
							}
						};
						o.gallery.fadeIn(200);
						o.stepCount = -o.visibleItems.length;
						o.currentIndex = Math.floor(Math.round(o.visibleItems[0].pos) / o.ITEM_SIZE);
					},
					onMouseDown : function (event)
					{
						var pageX = event.pageX;
						if(event.type == "touchstart")
						{
							var touches = event.touches,
							first = touches[0];
							
							event.preventDefault();
							pageX = first.clientX;
						}
						
						$(document).mousemove(o.onDragging);
						if(document.addEventListener != null) document.addEventListener('touchmove', o.onDragging, true);
						$(document).mouseup(o.onMouseUp);
						if(document.addEventListener != null) document.addEventListener('touchend', o.onMouseUp,true);
						
						for (var i = 0; i < o.visibleItems.length; i++){
							var itm = o.visibleItems[i];
							itm.obj.stop();
							itm.obj.animate({left: itm.pos}, 0);
						}
						
						o.movePoints = [];
						o.galleryMoved = false;
						o.lastDragValue = pageX;
						o.gallery.addClass('dragging');
						event.preventDefault();
						return false;
					},
					onDragging : function (event) 
					{
						var pageX = event.pageX;
						if(event.type == "touchmove")
						{
							//event.stopPropagation();
							event.preventDefault();
							//event = convertToMouseEvent(evt);
							var touches = event.touches,
							first = touches[0];
							
							pageX = first.clientX;
						}
						
						var dif = (pageX - o.lastDragValue);
						//if(dif > -3 && dif < 3) return;
						if(!o.galleryMoved && dif != 0) o.galleryMoved = true;
						
						if(o.movePoints.length > 6) { o.movePoints.shift(); }
						
						o.movePoints.push({dif: dif, time: new Date().getTime()});
						
						if(dif < 0)
						{
							o.negativeVelocity = true;
						}
						else if (dif > 0)
						{
							o.negativeVelocity = false;
						}
						
						for (var i = 0; i < o.visibleItems.length; i++){
							var itm = o.visibleItems[i];
							
							var pos = itm.pos + dif;
							itm.obj.css('left',pos + "px");
							itm.pos = pos;
						}
						o.checkPositions(true);
						o.lastDragValue = pageX;
						return false;
					},
					onMouseUp : function (event)
					{
						if(event.type == "touchend")
						{
							if(o.galleryMoved){
								event.stopPropagation();
								event.preventDefault();
							}
							//event = convertToMouseEvent(evt);
						}
						
						$(document).unbind('mousemove',o.onDragging);
						$(document).unbind('mouseup',o.onMouseUp);
						if(document.removeEventListener != null) document.removeEventListener('touchmove',o.onDragging,true);
						if(document.removeEventListener != null) document.removeEventListener('touchend',o.onMouseUp,true);
						
						o.checkPositions(true);
						
						var totalRecentMovement = 0;
						var rate = 0;
						var time = new Date().getTime();
						for (var i = 0; i < o.movePoints.length - 1; i++){
							if((time - o.movePoints[i].time) < o.MAX_POSITION_TIME)
							{
								totalRecentMovement += o.movePoints[i].dif;
								rate += o.movePoints[i].dif / (2000 / (o.movePoints.length - i));
							}
						}
						if(rate < 0) rate = rate *-1;
						
						var posChange = totalRecentMovement * 2;
						if(posChange > o.MAX_POSITION_VELOCITY) posChange = o.MAX_POSITION_VELOCITY;
						if (posChange < -o.MAX_POSITION_VELOCITY) posChange = -o.MAX_POSITION_VELOCITY;
						
						if(posChange > -70 && posChange < 70) posChange = 0;
						for (var i = 0; i < o.visibleItems.length ; i++){
							var itm = o.visibleItems[i];
							
							var pos = itm.pos + posChange;
							
							itm.pos = pos;
							itm.obj.animate({left: pos}, {duration: (1000 * (rate)) , easing: 'easeOutQuint', complete: o.forceCheckPositions, step: o.onStep});
						}
						o.gallery.removeClass('dragging');
						//--------------						
						
					},
					checkPositions : function (force)
					{
						var index = Math.floor(Math.round(o.visibleItems[0].pos) / o.ITEM_SIZE);
						//Find out if the first image in the array has moved enough to trigger any repositioning
						//Used in order use this function as little as possible as it's a CPU hog
						if(force != true && o.currentIndex == index)
						{
							return false;
						}
						o.currentIndex = index;
						
						var total = o.visibleItems.length;
						var jumpAmount = total * o.ITEM_SIZE;
						var leftLimit = -o.ITEM_SIZE;
						var rightLimit = document.body.clientWidth + o.ITEM_SIZE;
						for (var i = 0; i < total; i++){
							var itm = o.visibleItems[i];
							var leftVal = itm.obj.offset().left;
							var val;
							
							if(o.negativeVelocity && leftVal < leftLimit)
							 {
								val = itm.pos + jumpAmount;
								itm.obj.stop().css('left', val + "px");
								itm.pos = val;
							}
							else if (!o.negativeVelocity && leftVal > rightLimit)
							{
								val = itm.pos - jumpAmount;
								itm.obj.stop().css('left', val + "px");
								itm.pos = val;
							}
						}
						return true;
					},
					forceCheckPosition: function ()
					{
						o.checkPositions(true);
					},
					onStep : function ()
					{
						if(o.stepCount < (o.visibleItems.length - 1)/ 2)
						{
							o.stepCount += 1;
							return;
						}
						else
						{
							o.stepCount = 0;
							o.checkPositions(true);
						}
					},
					destroy : function ()
					{
						o.gallery.unbind('mousedown',o.onMouseDown);
					},
					redraw : function (filter)
					{
						o.filter = filter;
						
						o.gallery.stop()
						
						times = {};
						o.addItems(0, o.offset, o.timeOffset);
					},
					showDrag : function ()
					{
						var cookie = readCookie('dragIconDisplayed')
						if(o.dragIconDisplayed || cookie == 'true')
						{
							 return;
						}
						o.dragIcon.fadeIn("slow");
						o.dragIcon.hover(function(){
							o.dragIcon.fadeOut("slow");
						},function(){});
						o.dragIconDisplayed = true;
						createCookie('dragIconDisplayed', 'true')
					}
				}
				o.init(this, options);
			});
		}
	});
})(jQuery);

var times = {};
var browser = null;
if(jQuery.browser.msie && jQuery.browser.version < 9) { browser = "ie"; };

function createGalleryItem(itm, gal,index,hRev)
{
	var timeControl = {
		times: {},
		increment: 80,
		getAvailableTime: function (perspectiveTime) {	
			var now = new Date().getMilliseconds();
			var executeTime = now + perspectiveTime;
			
			var slot = Math.floor(executeTime / timeControl.increment);
			if(times[slot] != true){
				times[slot] = true;
				return perspectiveTime;
			} else {
				var success = false;
				while(!success) {
					perspectiveTime += timeControl.increment;
					slot = Math.floor((now + perspectiveTime) / timeControl.increment);
					if(times[slot] != true){
						times[slot] = true;
						success = true;	
						return perspectiveTime;
					}
				}
			}
		}
	}
	
	var gItem = {
		obj: itm,
		pos: 0,
		content: null,
		overlay: null,
		gallery: gal,
		enabled: true,
		loaded: false,
		flashObj: null,
		index: index,
		init: function ()
		{
			gItem.content = gItem.obj.children('a').fadeOut(0);
			gItem.overlay = gItem.content.children('.over');
			
			gItem.lineObj = jQuery("<div class='line'></div>").fadeTo(0,0);
			gItem.flashObj = jQuery("<div class='flash'></div>").fadeTo(0,0);
			gItem.obj.append(gItem.flashObj,gItem.lineObj);
			
			gItem.content.children('img').bind('load', gItem.onImageLoaded);
		},
		addToStage : function () {
			gItem.content.children('img').bind('load', gItem.onImageLoaded);
			var source = gItem.content.children('img').attr('src');
			gItem.content.children('img').attr('src','');
			gItem.content.children('img').attr('src',source);
			
			gItem.overlay.hide();
			
			if(hRev == true) {
				browser == 'ie' ? gItem.overlay.css('display','block') : gItem.overlay.stop().fadeTo(200,1);
			}
			
			gItem.obj.children('a').hide();
			gItem.obj.removeClass('loaded');
			gItem.flashObj.fadeTo(0, 0);
			if(gItem.loaded)
			{
				gItem.flash();
			}
		},
		onMouseOver : function (){
			gItem.lineObj.stop().animate({height: 6, opacity: 1}, 100, 'easeInOutQuad');
			if(hRev == false) {
				browser == 'ie' ? gItem.overlay.css('display','block') : gItem.overlay.stop().fadeTo(200,1);
				//gItem.overlay.stop().fadeTo(200,1);		
			}else {
				browser == 'ie' ? gItem.overlay.css('display','none') : gItem.overlay.stop().fadeOut(180, "easeOutQuad");		
				//browser == 'ie' ? null : gItem.obj.siblings().find('.over').stop().fadeTo(200,1);
				//gItem.obj.siblings().find('.over').stop().fadeTo(200,1);	
			};
		},
		onMouseOut : function (){
			gItem.lineObj.stop().animate({height: 0, opacity: 0}, 100, 'easeInOutQuad');
			if(hRev == false) {
				browser == 'ie' ? gItem.overlay.css('display','none') : gItem.overlay.stop().fadeOut(180, "easeOutQuad");		
			}else {
				browser == 'ie' ? gItem.overlay.css('display','block') : gItem.overlay.stop().fadeTo(200,1);
				//browser == 'ie' ? null : gItem.obj.siblings().find('.over').stop().fadeOut(180, "easeOutQuad");	
			};
		},
		onClick : function (event){
			if(gal.galleryMoved)
			{
				event.preventDefault();
				event.stopPropagation();
				return false;
			}
			// comemmted out because the target=_blank was not working corectly
//			else
//			{
//				window.location = gItem.content.attr('href');
//			}
			gal.galleryMoved = false;
		},
		onTouchStart : function (event){
			//alert('touch started');
		},
		onImageLoaded : function(){
			gItem.loaded = true;
			gItem.flash();
		},
		flash : function(){
			var delayTime = (Math.random() * 2000);
			delayTime = timeControl.getAvailableTime(delayTime);
			gItem.flashObj.delay(delayTime).fadeTo(80, 0.5, 'easeOutQuad', gItem.showImage).fadeOut(120, 'easeOutQuad');
		},
		remove : function (){
			//gItem.obj.children('.flash').remove();
		},
		showImage : function (){
			gItem.content.children('img').show();
			gItem.content.show();
			//gItem.obj.hoverIntent({over: gItem.onMouseOver,out: gItem.onMouseOut, interval: 0});
			gItem.obj.children('a').show();
			gItem.obj.hover(gItem.onMouseOver,gItem.onMouseOut);
			gItem.obj.click(gItem.onClick);
			
			if(gItem.content.get(0).addEventListener != null) gItem.content.get(0).addEventListener('touchend', gItem.onClick, true);
			if(gItem.content.get(0).addEventListener != null) gItem.content.get(0).addEventListener('touchstart', gItem.onTouchStart, true);
			
			gItem.obj.addClass('loaded');
			
			gal.itemsLoaded += 1;
			
		}
	}
	gItem.init();
	return gItem;
}
