(function($) {
	var $window                   = $(window),
	    $document                 = $(document),
	    html                      = document.documentElement,
	    $html                     = $(html),
	    root                      = $('#fotonovela'),
	    container                 = $('#fotonovela-slides'),
	    openBtn                   = $('a.show-fotonovela'),
	    closeBtn                  = $('#fotonovela-close'),
	    screenModeOverrideBtn     = $('#fotonovela-scroll-override'),
	    screenModeOverrideBtnText = screenModeOverrideBtn.text(),
	    slides                    = container.children(),
	    totalSlides               = slides.length,
	    minHeight                 = 600,
	    hasPrev                   = false,
	    hasNext                   = false,
	    screenModeOverride        = false,
	    smallScreenMode           = false,
	    running                   = false,	    opened_once               = false,
	    
		/**
		 * Runs when page loads
		 */
		init = function() {
			slides.each(function(i, slide) {
				slide.id = 'slide-' + (++i);
			});
		},
		
		/**
		 * Opens the slideshow and starts everything
		 */
		open = function(e) {
			e.preventDefault();
			
			running = true;						if ( ! opened_once) {				slides.each(function(i, slide) {					slide.src = slide.getAttribute('data-src');				});								opened_once = true;								slides.first().on('load', open);								return;			}
			
			// Keep the user's scroll position
			$html
				.data('scrollTop', html.scrollTop)
				.addClass('fotonovela');
			
			html.scrollTop = $html.data('scrollTop');
			
			// Show slideshow but keep it visually hidden while things initialize
			if ( ! Modernizr.opacity) {
				root.css('opacity', 0);
			}
			
			root.addClass('open');
			
			// Get things started			setup();
			
			// Show slideshow
			root.addClass('show');
			
			if ( ! Modernizr.opacity) {
				root.animate({opacity : 1}, 500);
			}
		},
		
		/**
		 * Closes the slideshow and unbinds certain events
		 */
		close = function(e) {
			e.preventDefault();
			
			// Fade slideshow out
			root.removeClass('show');
			
			// Completely hide slideshow after fade is complete
			setTimeout(function() {
				root.removeClass('open');
				
				// Reset to user's scroll position again
				$html.removeClass('fotonovela');
				
				html.scrollTop = $html.data('scrollTop');
			}, 500);
			
			running = false;
		},
		
		/**
		 * Overrides the default screen mode
		 */
		overrideScreenMode = function(e) {
			e.preventDefault();
			
			screenModeOverride = ! screenModeOverride;
			
			// Change link text to reflect action
			screenModeOverrideBtn.text(screenModeOverride ? screenModeOverrideBtn.data('alt') : screenModeOverrideBtnText);
			
			// Restart everything
			setup();
		},
		
		/**
		 * Runs when fotonovela is opened or resized
		 * Centers the slides in the window
		 */
		setup = function() {
			if ( ! running)
				return;
				
			// Enable/disable SSM
			root.toggleClass('small', smallScreenMode());
			
			// Center the slides
			if ( ! smallScreenMode()) {
				var slideWidth = slides.first().width();				
				container.css({
					width      : slideWidth,
					marginLeft : -(slideWidth / 2)
				});
			} else {
				container.css({
					top    : 'auto',
					width  : 'auto',
					margin : '0 auto'
				});
			}
			
			// Go to current slide
			changeSlide();
			
			// This helps with using the keyboard to scroll on small screens
			root.focus();
		},
		
		/**
		 * Shows the current slide
		 */
		changeSlide = function() {
			if ( ! running || smallScreenMode())
				return;
				
			var slide  = getSlide(),
			    height = slides.first().outerHeight(),
			    top    = height * (slide - 1);
			
			// Move slide into view
			if (Modernizr.csstransitions) {
				container.css('top', -top);
			} else {
				container.animate({top : -top}, 1200);
			}
			
			// Update counter display
			root.attr('data-counter', slide + '/' + totalSlides);
			
			// Determine if there are slides ahead of and behind this one
			hasPrev = slide > 1;
			hasNext = slide < totalSlides;
		},
		
		/**
		 * Handles a click to move to the next/previous slide
		 * Also handles up and down arrows
		 */
		navigate = function(e) {
			if ( ! running || smallScreenMode())
				return;
			
			var slide   = getSlide(),
			    keycode = e.keyCode ? e.keyCode : e.which,
			    dir;
			
			e.preventDefault();
			
			if (e.type === 'click') {
				dir = e.clientY > ($window.height() / 2);
			} else {
				if (keycode === 40) {
					dir = true;
				} else if (keycode === 38) {
					dir = false;
				} else {
					return;
				}
			}
			
			if (dir) {
				if (++slide <= totalSlides) {
					window.location.hash = 'slide-' + slide;
				}
			} else {
				if (--slide > 0) {
					window.location.hash = 'slide-' + slide;
				}
			}
		},
		
		/**
		 * Determines what cursor should be shown when hovering slides, based on position of cursor
		 */
		showCursor = function(e) {
			if (smallScreenMode())
				return;
			
			var dir = e.clientY > ($window.height() / 2);
			
			if (dir && hasNext) {
				container.removeClass('hover-up').addClass('hover-down');
			} else if ( ! dir && hasPrev) {
				container.removeClass('hover-down').addClass('hover-up');
			} else {
				container.removeClass('hover-up hover-down');
			}
		},
		
		/**
		 * Gets the slide number from the URL hash
		 */
		getSlide = function() {
			var hash  = window.location.hash,
			    slide = /^#slide-\d+$/.test(hash) ? +hash.replace('#slide-', '') : 1;
			
			return Math.min(Math.max(1, slide), totalSlides);
		},
		
		/**
		 * Determines if window is small enough to run in small screen mode
		 */
		smallScreenMode = function() {
			return screenModeOverride ? true : ($window.height() < minHeight);
		},
		
		/**
		 * Disables scrolling when in full view
		 */
		disableKeydown = function(e) {
			if (running && ! smallScreenMode()) {
				var keycode = e.keyCode ? e.keyCode : e.which;
				
				if (keycode === 38 || keycode === 40) {
					e.preventDefault();
				}
			}
		};
		
		// Bind events to get things rolling
		$window
			.on('resize', setup)
			.on('hashchange', changeSlide);
		
		$document
			.on('keydown', disableKeydown)
			.on('keyup', navigate);
		
		container
			.on('click', navigate)
			.on('mousemove', showCursor);
			
		openBtn.on('click', open);
		
		closeBtn.on('click', close);
		
		screenModeOverrideBtn.on('click', overrideScreenMode);				init();
})(jQuery);
