(function ($) {
    $.fn.extend({
        tileCarousel: function(options) {
            return this.each(function() {
                new $.TileCarousel(this, options);
            });
        }
    });
    
    $.TileCarousel = function(element, options) {
        var defaults = {
            increment: 1,
            incrementMode: 'frame', // tile or frame
            speed: 750,
			easing: 'swing',
			loop: false,
			pagination: false,
			centerPagination: true,
			encapsulateControls: false,
			displayCount: false,
			accessible: true,
			containerDelta: 0,
			viewportDelta: 0,
			callbacks: {
				preFrameChange: function() {},
				postFrameChange: function() {}
			}
        };
        
        this.element = $(element);
        this.options = $.extend({}, defaults, options || {});
		
		this.accessibilitySelectors = 'a,input,select,textarea,button';
      
        this.setup();
        
    };
    
    $.extend($.TileCarousel.prototype, {
        
		setup: function() {
			
            var self = this;
			var options = this.options;
			var loop = options.loop;
			
			var $carousel = this.element;
			var increment = options.increment;
			var callbacks = options.callbacks;
			
			this.preFrameChange = callbacks.preFrameChange;
			this.postFrameChange = callbacks.postFrameChange;
			
			var tiles = $carousel.children('li');
			this.tiles = tiles;
	        var tileCount = tiles.length;
			this.tileCount = tileCount;
			this.totalTileCount = tileCount; // totalTileCount will include the clones
			var frameCount = Math.ceil(tileCount / increment);
			this.frameCount = frameCount;
			this.index = 0;
            
			// wrap carousel in viewport and container
            $carousel.wrap('<div class="carousel-container"><div class="carousel-viewport"></div></div>');
			
			// get the dimensions of a single tile
			var tile = tiles[0];
			var tileWidth = $(tile).outerWidth(true);
			this.tileWidth = tileWidth;
			this.tileHeight = $(tile).outerHeight(true);
			
			// make sure tiles will fill the frames
			if (options.pagination) {
				// if pagination is enabled, pad final frame with blank tiles
				while (this.totalTileCount % increment !== 0) {
					$carousel.append('<li>&nbsp;</li>');
					this.totalTileCount++;
				}
			}
			
			// if looping
			if (loop && tileCount > increment) {
			
				var totalTileCount = this.totalTileCount;
				
				// make sure tiles will fill the frames
				if (!options.pagination) {
					// send in the clones
					while (totalTileCount % increment !== 0) {
						for (var i=0; i<tileCount; i++) {
							$carousel.append($(tiles[i]).clone());
						}
						totalTileCount += tileCount;
					}
				}
				
				this.totalTileCount = totalTileCount; // totalTileCount includes the clones
				var allTiles = $carousel.children('li'); // allTiles includes the clones
				
				// clone first frame onto end
				for (var i=0; i<increment; i++) {
					$carousel.append($(tiles[i]).clone());
					this.totalTileCount++;
				}
				
				// clone last frame onto beginning
				for (var i=0; i<increment; i++) {
					$carousel.prepend($(allTiles[totalTileCount - 1 - i]).clone());
					this.totalTileCount++;
				}
				
				// reset left margin & index to accommodate added frame
				$carousel.css({marginLeft: '-' + (increment * tileWidth) + 'px'});
				this.index = increment;
				
			}
			
			this.allTiles = $carousel.children('li'); // allTiles includes the clones
			this.totalFrameCount = Math.ceil(this.totalTileCount / increment); // totalFrameCount includes the clones
			
			// calculate viewport width
            var $viewport = $carousel.parent();
			var viewportWidth = tileWidth * increment + options.viewportDelta;
			this.viewportWidth = viewportWidth;
			$viewport.css('width', viewportWidth + 'px');
			
			// set container width
			var $container = $viewport.parent();
			this.container = $container;
			$container.css('width', (tileWidth * increment + options.containerDelta) + 'px');
			$carousel.css('width', (tileWidth * this.totalTileCount) + 'px');
			
			// add previous button
			var prev = '<a class="prevFrame" title="Previous">Previous</a>';
			if (options.encapsulateControls) {
				$container.append('<div class="carousel-controls"></div>');
				var $controls = $('.carousel-controls');
				$controls.append(prev);
			} else {
				$container.append(prev);
			}
			
			// place pagination between prev/next buttons
			if (options.pagination) {
				if (options.encapsulateControls) {
					this.paginationInit($controls);
				} else {
					this.paginationInit($container);
				}
			}
			// add next button
			var next = '<a class="nextFrame" title="Next">Next</a>';
			if (options.encapsulateControls) {
				$controls.append(next);
				// calculate width of controls and center beneath carousel
				var controlsWidth = $('.prevFrame', $container).outerWidth(true) + $('.carousel-pagination', $container).outerWidth(true) + $('.nextFrame', $container).outerWidth(true);
				$controls.css({
					'position': 'relative',
					'width': controlsWidth + 'px',
					'left': ((viewportWidth / 2) - (controlsWidth / 2)) + 'px'
				});
			} else {
				$container.append(next);
			}
			
			this.prevBtn = $('.prevFrame', $container);
			this.nextBtn = $('.nextFrame', $container);
			
			// set click events for prev/next buttons
			$container.delegate('.prevFrame,.nextFrame', 'click', function () {
				var method = $(this).attr('class');
				if(!$(this).hasClass('disabled'))
					self[method]();
				return false;
			});
			
			if (options.displayCount) {
				// append counter container
				this.container.append('<div class="carousel-display-counter"></div>');
				this.counterContainer = $('.carousel-display-counter', $container);
				this.updateDisplayCount();
			}
			// cache array for lazy loader
			this.lazyloadCache = new Array(this.allTiles.length);
			// lazy loading of images
			this.lazyloadImages(0, increment * 2); // load the visible frame & next frame
			if (loop) {
				this.lazyloadImages(increment * 2, (increment * 2) + increment); // load 'next' frame
				this.lazyloadImages(tiles.length, tiles.length + increment); // load final frame
			}
			// init accessibility
			if (options.accessible) {
				this.accessibilityInit();
			}
			if (!loop) {
				this.updateButtonStates();
			}
			// disable prev/next buttons if there is only one frame
			if (tileCount <= increment) {
				$(this.prevBtn).addClass('disabled');
				$(this.nextBtn).addClass('disabled');
			}      
    },
		
		paginationInit: function($container) {
			var self = this;
			// append pagination container
			$container.append('<ul class="carousel-pagination"></ul>');
			var $pagination = $('.carousel-pagination', $container);
			var frameCount = this.frameCount;
			var loop = this.options.loop;
			
			// build pagination links
			for (var i=0; i<frameCount; i++) {
				var p = i + 1;
				$pagination.append('<li><span class="carousel-frame" frame="' + p + '" href="#" title="' + p + '">' + p + '</span></li>');
			}
			
			var pageLink = $('.carousel-frame', $pagination).get(0);
			
			if (this.options.centerPagination) {
				// calculate width of pagination container and center beneath carousel
				var pageLinkWidth = $(pageLink).outerWidth(true);
				var paginationWidth = pageLinkWidth * frameCount;
				$pagination.css({
					'width': (pageLinkWidth * frameCount) + 'px',
					'left': ((self.viewportWidth / 2) - (paginationWidth / 2)) + 'px'
				});
			}
			
			this.paginationLinks = $('.carousel-frame', $pagination);
			
			$(pageLink).addClass('selected');
		},
		
		accessibilityInit: function() {
			var self = this;
			var pagination = this.options.pagination;
			var selectors = this.accessibilitySelectors;
			this.element.attr('role', 'listbox');
			this.tiles.each(function(i) {
				$(this).attr({
					'id': 'tile-' + i,
					'role': 'option',
					'aria-selected': 'true',
					'tabindex': -1
				})
			}).find(selectors).attr('tabindex', -1);
			if (this.options.loop) {
				$('li,' + selectors, this.container).attr('tabindex', -1); // for the extra cloned list items not included in this.tiles
			}
			this.tiles.first().attr('tabindex', 0).find(selectors).attr('tabindex', 0);
			this.tiles.focusin(function() {
				$(self.tiles).attr('tabindex', -1).find(selectors).attr('tabindex', -1);
				self.focusedTile = parseInt($(this).attr('id').replace('tile-', ''));
				$(this).attr('tabindex', 0).find(selectors).attr('tabindex', 0);
			});
			
			// set keypress events for carousel
			this.element.keypress(function(event) {
				switch(event.keyCode) {
					case 37: // left arrow
						self.focusPrevTile();
						return;
					case 39: // right arrow
						self.focusNextTile();
						return;
					default:
						return;
				}
			});
			
			var attr = {
				'role': 'button',
				'aria-controls': 'carousel',
				'tabindex': 0
			}
			
			// prev/next buttons
			this.prevBtn.attr(attr).keypress(function(event) {
				if (event.keyCode === 13) { // 13 is 'enter'
					self.prevFrame();
				}
			});
			
			this.nextBtn.attr(attr).keypress(function(event) {
				if (event.keyCode === 13) {
					self.nextFrame();
				}
			});
			
			if (pagination) {
			
				$('.carousel-pagination,.carousel-pagination li').attr('role', 'presentation');
				
				var $controls = $('.carousel-pagination a');
				$controls.attr({
					'role': 'button',
					'aria-controls': 'carousel',
					'tabindex': -1
				}).focusin(function() {
					$controls.attr('tabindex', -1);
					$(this).attr('tabindex', 0);
				}).keypress(function(event) {
					var focusedControl = parseInt($(this).attr('title'));
					switch(event.keyCode) {
						case 37: // left arrow
							self.focusPrevControl(focusedControl, $controls);
							return;
						case 39: // right arrow
							self.focusNextControl(focusedControl, $controls);
							return;
						default:
							return;
					}
				}).first().attr('tabindex', 0);	
			}
		},
		
		focusPrevControl: function(focusedControl, $controls) {
			var targetControl = focusedControl - 1;
			if (targetControl > 0) {
				$controls.get(targetControl - 1).focus();
			} else {
				$controls.get($controls.length - 1).focus();
			}
		},
		
		focusNextControl: function(focusedControl, $controls) {
			var targetControl = focusedControl + 1;
			if (targetControl < $controls.length + 1) {
				$controls.get(targetControl - 1).focus();
			} else {
				$controls.get(0).focus();
			}
		},
		
		focusPrevTile: function() {
			var targetTile = this.focusedTile - 1;
			var index = this.index;
			var loop = this.options.loop;
			this.keyPress = true;
			if (loop) {
				index = index - this.options.increment;
			}
			if (targetTile > -1) {
				// target tile is within range
				if (targetTile < index) {
					// target tile is not in visible frame
					this.prevFrame();
					this.delayFocus(targetTile);
				} else {
					// target tile is in visible frame
					this.tiles.get(targetTile).focus();
				}
			} else if (loop) {
				// set target tile last tile
				this.jumpToFrame(this.totalFrameCount - 1);
				this.delayFocus(this.tileCount - 1);
			}
			
		},
		
		focusNextTile: function() {
			var self = this;
			var targetTile = this.focusedTile + 1;
			var index = this.index;
			var loop = this.options.loop;
			this.keyPress = true;
			if (loop) {
				index = index - this.options.increment;
			}
			if (targetTile < this.tileCount) {
				// target tile is within range
				if (targetTile >= index + this.options.increment) {
					// target tile is not in visible frame
					this.nextFrame();
					this.delayFocus(targetTile);
				} else {
					// target tile is in visible frame
					this.tiles.get(targetTile).focus();
				}
			} else if (loop) {
				// set target tile to first tile
				this.jumpToFrame(2);
				this.delayFocus(0);
			}
		},
		
		delayFocus: function(targetTile) {
			var self = this;
			var delay = setInterval(function() {
				if (self.animationComplete) {
					self.tiles.get(targetTile).focus();
					clearInterval(delay);
				}
			}, 500);
		},
		
		jumpToFrame: function(frame) {
			
			var increment = this.options.increment;
			var index = (frame * increment) - increment;
			this.lazyloadImages(index, index + increment); // lazy load images
			this.index = index;
			this.animate();
		},

		prevFrame: function() {
			var self = this;
			var increment = this.options.increment;
			var index = this.index;
			if (this.options.incrementMode === 'tile') {
				this.index--;
			} else if (index - increment > 0) {
				this.index = index - increment;
			} else {
				this.index = 0;
			}
			this.animate();
		},
		
		nextFrame: function() {
			var self = this;
			var increment = this.options.increment;
			var index = this.index;
			var finalIndex = this.totalTileCount - increment;
			if (this.options.incrementMode === 'tile') {
				this.index++;
			} else if (index + increment < finalIndex) {
				this.index = index + increment;
			} else {
				this.index = finalIndex;
			}
			this.animate();
		},
		
		reset: function() {
			if (this.loop) {
				this.index = this.options.increment;
			} else {
				this.index = 0;
			}
			this.animate();
		},
		
		animate: function() {
			var self = this;
			var index = this.index;
			var options = this.options;
			var loop = options.loop;
			var increment = options.increment;
			var tileWidth = this.tileWidth;
			this.animationComplete = false;
			if (options.pagination) {
				var selectedFrame = Math.ceil((index + increment) / increment);
				if (loop) {
					var lastFrame = this.paginationLinks.length;
					if (selectedFrame === 1 || selectedFrame === lastFrame + 1) {
						selectedFrame = this.paginationLinks.length;
					} else if (selectedFrame > lastFrame + 1) {
						selectedFrame = 1;
					} else {
						selectedFrame--;
					}
				}
				this.selectedFrame = selectedFrame;
			}
			this.preFrameChange();
			this.element.stop().animate(
				{ 
					marginLeft: '-' + (index * tileWidth) + 'px'
				},
        options.speed,
				options.easing,
				function() {
					if (!loop) {
						self.updateButtonStates();
					} else {
						if (index === 0) {
							// reset margin & index to show 'last' frame
							self.index = self.totalTileCount - (increment * 2);
							self.element.css({marginLeft: '-' + (self.index * tileWidth) + 'px'});
						} else if (index === (self.totalTileCount - increment)) {
							// reset margin & index to show 'first' frame
							self.index = increment;
							self.element.css({marginLeft: '-' + (self.index * tileWidth) + 'px'});
						}
					}
					// lazy load images
					var targetIndex = index;
					if (loop) {
						if (targetIndex === 0) {
							targetIndex = self.allTiles.length - increment * 2;
						}
						self.lazyloadImages(targetIndex - increment, targetIndex); // load prev frame's images
					}
					self.lazyloadImages(targetIndex + increment, targetIndex + increment * 2); // load next frame's images
					if (options.pagination) {
						self.paginationLinks.removeClass('selected').each(function() {
							var frameNo = parseInt($(this).attr('frame'));
							if (frameNo === self.selectedFrame) {
								$(this).addClass('selected');
							}
						});
					}
					if (!self.keyPress) {
						if (loop) {
							var tileCount = self.tileCount;
							if (options.pagination) {
								if (index >= tileCount + increment) {
									self.allTiles.get(increment).focus();
								} else if (index === 0) {
									self.tiles.get(self.frameCount * increment - increment).focus();
								} else {
									self.tiles.get(index - increment).focus();
								}
							} else if (index > tileCount) {
								self.tiles.get(0).focus();
							} else {
								self.tiles.get(index - increment).focus();
							}
						} else {
							self.tiles.get(index).focus();
						}
					}
					self.keyPress = false;
					self.postFrameChange();
					self.animationComplete = true;
					if (options.displayCount) {
						self.updateDisplayCount();
					}
				}
			);
		},
		
		lazyloadImages: function(start, stop) {
			if (this.lazyloadCache[start]) {
				return;
			}
			var self = this;
			var tiles = this.allTiles;
			for (var i=start; i<stop; i++) {
				self.lazyloadCache[i] = true;
				$('img', tiles[i]).each(function() {
					if (!this.src) {
						this.src = $(this).attr('original');
					}
				});
			}
    },
		
		updateDisplayCount: function() {
			var index = this.index;
			var increment = this.options.increment;
			var tileCount = this.tileCount;
			if (this.options.loop) {
				index -= increment;
			}
			var first = index + 1;
			var last = index + increment;
			if (last > tileCount) {
				last = tileCount;
			}
			var text = first;
			if (last > first) {
				text += '-' + last;
			}
			text += ' of ' + tileCount;
			this.counterContainer.html(text);
    },
		
		updateButtonStates: function() {
			if (this.index === 0) {
				$(this.prevBtn).addClass('disabled').attr({'tabindex': -1});
			} else {
				$(this.prevBtn).removeClass('disabled').attr({'tabindex': 0});
			}
			if (this.index + this.options.increment >= this.tileCount) {
				$(this.nextBtn).addClass('disabled').attr({'tabindex': -1});
			} else {
				$(this.nextBtn).removeClass('disabled').attr({'tabindex': 0});
			}
		}
  });
})(jQuery);

$(function (){
// Terrible I know but here is the implementation right on the plugin script

/*--------------------------------------------------------
	MOD_GC_6
---------------------------------------------------------*/
	var iit = 0,
		i = 1,
		$activeState,
		t = 0,
		ttl = ($('.MOD_GC_6 .list li').length) - 1;

	/* Activate a thumbnail image to the large container*/
	function imgState(obj) {
		for (t = 0; t <= ttl; t++) {
			if ($('.MOD_GC_6 .list li:eq(' + t + ')').hasClass('on') === true) {
				break;
			}
		}
	    switch(obj) {
			case 'prevUp':
				if (t > 0) {
					$('.MOD_GC_6 .list li:eq(' + t + ')').removeClass('on');
					$('.MOD_GC_6 .list li:eq(' + t + ')').prev().addClass('on');
				}
	      		break;
			case 'nextUp':
				if (t < ttl) {
	        		$('.MOD_GC_6 .list li:eq(' + t + ')').removeClass('on');
					$('.MOD_GC_6 .list li:eq(' + t + ')').next().addClass('on');
				}
				break;
	    }
	    // When an image has a class of "on"
	    $activeState = $('.MOD_GC_6 .list li.on');
		getImage($activeState);
	}

	/* From the selected image, assign citation and image to container */
	function getImage(obj) {
		var $imgRel = $(obj).find('img').attr('rel'),
        $imgCaption = $(obj).find('p.caption').html();

		$('.MOD_GC_6 .list li').removeClass('on');
		$('.MOD_GC_6 .myImage').find('img').remove();

		$('<img src="' + $imgRel + '" />').load(function () {
			$('.MOD_GC_6 .myImage').append($(this));
		});
		$('.MOD_GC_6 .img cite').html($imgCaption);
		$(obj).addClass('on'); //Lastly, let's add in our active class.

		if ($imgCaption == null || $imgCaption == '')
		{
			$('.MOD_GC_6 .img cite').css('display', 'none');
		}
		else
		{
			$('.MOD_GC_6 .img cite').css('display', 'block');
		}
		
	}

	/* Click event over the Big Image */    
	$('.MOD_GC_6 .img a.prev').click(function (e){
		e.preventDefault();
		imgState('prevUp');
		if ((t % 4) === 0) {
      $('.carousel-container a.prevFrame').trigger('click');
		}
	});
	
	$('.MOD_GC_6 .img a.next').click(function (e){
		e.preventDefault();
		imgState('nextUp');
  	// If clicked after 4, Run the slide function
		if (((t + 1) % 4) === 0) {
			$('.carousel-container a.nextFrame').trigger('click');
		}
	});

	// Page has loaded for the first time.
	if($('.MOD_GC_6 .list li')[0])
	getImage($('.MOD_GC_6 .list li:first-child'));
	// If a thumbnail is clicked.
	$('.MOD_GC_6 .list li').click(function (e){ 
	  e.preventDefault();
	  getImage(this); 
	});

	/* Carousel the thumbnails*/
	if($('.MOD_GC_6 .list ul').parents('.tabContent').length==0) {
		$('.MOD_GC_6 .list ul').tileCarousel({
			increment: 4,
			loop: false,
			pagination: true
		});
	}
	
	$('.tabContent.on .MOD_GC_6 .list ul.thumbs').tileCarousel({
		increment: 4,
		loop: false,
		pagination: true
	});

	if (($('.carousel-pagination li').length ==1)){
	$('.carousel-pagination').hide()
	}else{
	$('.carousel-pagination').show()
	}

	
	/* Mouseover event on the big image */
	$('.MOD_GC_6 .img a.prev').mouseenter(function () {	
		// If this is NOT the first list item, show the prev button.
		if (!$('.MOD_GC_6 .list ul.thumbs li:first').hasClass('on')) {
			$(this).css('backgroundPosition','left center');
		} else {
			// If it IS: don't show.
			$(this).css('backgroundPosition','0 -1000px');
		}
	}).mouseleave(function () {
		$(this).css('backgroundPosition', '0 -1000px');
	});

	$('.MOD_GC_6 .img a.next').mouseenter(function () {
		// If this is NOT the last list item, show the prev button.
		if (!$('.MOD_GC_6 .list ul.thumbs li:last').hasClass('on')) {
			$(this).css('backgroundPosition','right center');
		} else {
			// If it IS: don't show.
			$(this).css('backgroundPosition', '0 -1000px');
		}
	}).mouseleave(function () {
		$(this).css('backgroundPosition','0 -1000px');
	});
	
});

