(function($){
	
	$.fn.flickrGallery = function(options) {
	
		var defaults = {
			apiKey: 'dcf29c7cc958a400e7b3f43e85dc582f',
			userID: '10435166@N02', // Flickr user ID can be found at idgettr.com
			photosetID: '72157604126037887',
			subnav: false,
			get: 'allPhotos', //options are allPhotos, photoset, photosetList
			perPage: '100',
			subnavLocation: '',
			galleryLocation: '',
			imageTitle: '',
			subnavThumbnails: true
		};
		
		var options = $.extend(defaults, options);
		
		var s = 300;
		var imgIndex, newIndex, images, modal, modalContainer, imgContainer, controls, subnav;
		
		return this.each(function(){
			subnav = $(defaults.subnavLocation);	

			if (defaults.get == 'allPhotos'){
				var ajaxUrl = 'http://api.flickr.com/services/rest/?&method=flickr.photos.search&api_key=' + defaults.apiKey + '&user_id=' + defaults.userID + '&per_page=' + defaults.perPage + '&page=1&privacyFilter=1&format=json&jsoncallback=?';
				
				displayAllPhotos(ajaxUrl);
			}
			if (defaults.get == 'photoset'){
				var ajaxUrl = 'http://api.flickr.com/services/rest/?&method=flickr.photosets.getPhotos&api_key=' + defaults.apiKey + '&photoset_id=' + defaults.photosetID + '&per_page=' + defaults.perPage + '&privacyFilter=1&format=json&jsoncallback=?';
				
				displaySinglePhotoset(ajaxUrl);
			}
			if (defaults.get == 'photosetList') {
				var ajaxUrl = 'http://api.flickr.com/services/rest/?&method=flickr.photosets.getList&api_key=' + defaults.apiKey + '&user_id=' + defaults.userID + '&privacyFilter=1&format=json&jsoncallback=?'
				
				displayPhotosets(ajaxUrl);
			}
			
			
			function displayAllPhotos(ajaxUrl){
				$.getJSON(ajaxUrl, function(data){
					if (data.photos == undefined){
						alert(data.message);
						return false;
					} 
					buildPhotoGallery(data);
				});
			}
			
			function displaySinglePhotoset(ajaxUrl, title){
				$.getJSON(ajaxUrl, function(data){
					if (data.photoset == undefined){
						alert(data.message);
						return false;
					} 
					buildPhotosetGallery(data, title);
				});
				
			}
			
			function displayPhotosets(ajaxUrl){
				$.getJSON(ajaxUrl, function(data){
					if (data.photosets == undefined){
						alert(data.message);
						return false;
					} 
					buildPhotosets(data);
				});
			}
			
			function buildPhotoGallery(data){
				var ul;
				
				if ($(defaults.galleryLocation).is('ul')) {
					ul = $(defaults.galleryLocation);
				} else {	
					$(defaults.galleryLocation).empty().append('<ul></ul>');
					ul = $(defaults.galleryLocation).find('ul');
				}
				ul.empty();
				$.each(data.photos.photo, function(i, item){
					var thumbUrl = 'http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.id + '_' + item.secret + '_s.jpg',
						largeUrl = 'http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.id + '_' + item.secret + '.jpg';
						
					ul.append(
						'<li>' +
						'	<a href="' + largeUrl + '"><img src="' + thumbUrl + '" title="' + defaults.imageTitle + '"/></a>' +
						'</li>'
					);
				});
				
				ul.find('a').click(function(e){
					e.preventDefault();
					handleThumbClick(e, ul);
				});	
			}
			
			function buildPhotosetGallery(data, title){
				var ul;
				var titleArea = $('h3.photosetTitle');
				
				titleArea.text(title).show();
				if ($(defaults.galleryLocation).is('ul')) {
			
					ul = $(defaults.galleryLocation);
					
				} else {
		
					$(defaults.galleryLocation).empty().append('<ul></ul>');
					ul = $(defaults.galleryLocation).find('ul');
				}
				ul.empty();
				$.each(data.photoset.photo, function(i, item){
					var thumbUrl = 'http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.id + '_' + item.secret + '_s.jpg',
						largeUrl = 'http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.id + '_' + item.secret + '.jpg';
						
					ul.append(
						'<li>' +
						'	<a href="' + largeUrl + '"><img src="' + thumbUrl + '" title="' + defaults.imageTitle + '"/></a>' +
						'</li>'
					);
				});
				
				ul.find('a').click(function(e){
					e.preventDefault();
					handleThumbClick(e, ul);
				});
			}
			
			function buildPhotosets(data){
				
				if (defaults.subnavThumbnails == false){
					if(subnav.is('ul')){
						subnav.empty();
						$.each(data.photosets.photoset, function(i, item){
							subnav.append('<li><a id="' + item.id + ' "href="">' + item.title._content + '</a></li>');
						});
						subnav.find('a').unbind().bind('click',function(e){
							e.preventDefault();
							var photosetID = $(this).attr('id');
							var ajaxUrl = 'http://api.flickr.com/services/rest/?&method=flickr.photosets.getPhotos&api_key=' + defaults.apiKey + '&photoset_id=' + photosetID + '&per_page=' + defaults.perPage + '&privacyFilter=1&format=json&jsoncallback=?';
							
							displaySinglePhotoset(ajaxUrl);
						});
					} else {
						subnav.append('<ul></ul>');
						$.each(data.photosets.photoset, function(i, item){
							subnav.find('ul').append('<li><a id="' + item.id + ' "href="">' + item.title._content + '</a></li>');
						});
						subnav.find('a').unbind().bind('click',function(e){
							e.preventDefault();
							var photosetID = $(this).attr('id');
							var ajaxUrl = 'http://api.flickr.com/services/rest/?&method=flickr.photosets.getPhotos&api_key=' + defaults.apiKey + '&photoset_id=' + photosetID + '&per_page=' + defaults.perPage + '&privacyFilter=1&format=json&jsoncallback=?';
							
							displaySinglePhotoset(ajaxUrl);
						});
					}
				}
				if (defaults.subnavThumbnails == true){
					if(subnav.is('ul')){
						subnav.empty();
						$.each(data.photosets.photoset, function(i, item){
							subnav.append(
								'<li class="photoset">' +
								'	<ul class="photosetContent">' +
								'		<li class="photo"><a class="' + item.id + ' "href=""><img src="http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.primary +'_' + item.secret + '_s.jpg"/></a></li>' +
								'		<li class="title"><a class="' + item.id +'" href="">' + item.title._content + '</a></li>' +
								'		<li class="count">' + item.photos + ' photos</li>' +
								'	</ul>' +
								'</li>'
							);
						});
						subnav.find('a').unbind().bind('click',function(e){
							e.preventDefault();
							var photosetID = $(this).attr('class');
							var title = $(this).parents('.photosetContent').find('li.title a').text();
							var ajaxUrl = 'http://api.flickr.com/services/rest/?&method=flickr.photosets.getPhotos&api_key=' + defaults.apiKey + '&photoset_id=' + photosetID + '&per_page=' + defaults.perPage + '&privacyFilter=1&format=json&jsoncallback=?';
	
							displaySinglePhotoset(ajaxUrl, title);
						});
					} else {
						subnav.append('<ul class="photosetList"></ul>');
						subnav.find('ul.photosetList').empty();
						$.each(data.photosets.photoset, function(i, item){
							subnav.find('ul.photosetList').append(
								'<li class="photoset">' +
								'	<ul class="photosetContent">' +
								'		<li class="photo"><a class="' + item.id + ' "href=""><img src="http://farm' + item.farm + '.static.flickr.com/' + item.server + '/' + item.primary +'_' + item.secret + '_s.jpg"/></a></li>' +
								'		<li class="title"><a class="' + item.id +'" href="">' + item.title._content + '</a></li>' +
								'		<li class="count">' + item.photos + ' photos</li>' +
								'	</ul>' +
								'</li>'
							);
						});
						subnav.find('a').unbind().bind('click',function(e){
							e.preventDefault();
							var photosetID = $(this).attr('class');
							var title = $(this).parents('.photosetContent').find('li.title a').text();
							var ajaxUrl = 'http://api.flickr.com/services/rest/?&method=flickr.photosets.getPhotos&api_key=' + defaults.apiKey + '&photoset_id=' + photosetID + '&per_page=' + defaults.perPage + '&privacyFilter=1&format=json&jsoncallback=?';

							displaySinglePhotoset(ajaxUrl, title);
						});
					}
				} 
			}
			
			function handleSubnavClick(e){
				e.preventDefault();
				var target = $(e.target);
				var photosetID = target.attr('class');
				var ajaxUrl = 'http://api.flickr.com/services/rest/?&method=flickr.photosets.getPhotos&api_key=' + defaults.apiKey + '&photoset_id=' + photosetID + '&per_page=' + defaults.perPage + '&privacyFilter=1&format=json&jsoncallback=?';
				
				displaySinglePhotoset(ajaxUrl);
			}
			
			function handleThumbClick(e, ul){
				var target = $(e.target);
				var li = target.parents('li');
				var href;
				
				if (target.is('img')){
					href = target.parent().attr('href');
				} else if (target.is('a')){
					href = target.attr('href');
				}
				
				imgIndex = $(defaults.galleryLocation + ' li').index(li);

				openImageModal(ul);
			}
			
			function preloadImages(images){
				$(images).each(function(){
					$('<img/>')[0].src = this;
				});
			}
			
			function openImageModal(ul){
				var currentImg = imgIndex;
	 			images = new Array();
				var img = new Image();
				
				$.each(ul.find('li a'), function(){
					images.push($(this).attr('href'));
				});
				
				preloadImages(images);
				
				$('body').append(
					'<div id="flickrImageModal">' +
					'	<div class="modalBg"></div>' +
					'	<div class="modalContainer">' +
					'		<div class="imageContainer"></div>' +
					'		<ul class="actions">' +
					'			<li class="prev"><a class="prev" href="#">&lt;&lt;Previous</a></li>' +
					'			<li class="next"><a class="next" href="#">Next&gt;&gt;</a></li>' +
					'			<li class="close"><a class="close" href="#">Close</a></li>' +
					'		</ul>' +
					'	</div>' +
					'</div>'
				);
				
				modal = $('#flickrImageModal');
				modalContainer = modal.find('.modalContainer');
				imgContainer = modal.find('.imageContainer');
				controls = modal.find('.actions');
				
				controls.hide();
				modal.find('.modalBg').animate({opacity: '0.7'}, s, function(){
					modalContainer.fadeIn(s);
					modalContainer.append('<div class="loading"><p>Loading....</p></div>');
					$(img).attr('src', images[imgIndex]).attr('class','loadedImg').load(function(){
						modalContainer.find('div.loading').remove();
						$(this).hide();
						
						imgContainer.append(this);
						var image = $('img.loadedImg');
						
						var imgW = $('img.loadedImg').width() + 20,
							imgH = $('img.loadedImg').height() + 20;
						
						modalContainer.animate({width: imgW + 'px', marginLeft: '-' + imgW / 2 + 'px'}, s, function(){
							modalContainer.animate({height: imgH + 'px', marginTop: '-' + imgH / 2 + 'px'}, s, function(){
								image.fadeIn(s);
								controls.fadeIn(s);
							});
						});										
					});
				});
				handleControls();
				$('#flickrImageModal .modalBg').click(function(e){
					e.preventDefault();
					modal.remove();
				});
			}
			
			function handleControls(){
				modal.click(function(e){
					var target = $(e.target);
					
					if (target.is('img')){
						nextImage();
					}
				});
				controls.unbind('click').bind('click',function(e){
					e.preventDefault();
					var target = $(e.target);
					if (target.attr('class') == 'next'){
						nextImage();
					}
					if (target.attr('class') == 'prev'){
						prevImage();
					}
					if (target.attr('class') == 'close'){
						modal.remove();
					}
				});
				$(document).bind('keyup' , function(e){
					e.preventDefault();
					if (e.keyCode == '37'){	
						prevImage();
						return false;
					} 
					if (e.keyCode == '39'){
						nextImage();
					}
					if (e.keyCode == '27'){
						modal.remove();
						$(document).unbind('keyup');
					}
				});
			}
			
			function nextImage(){
				if (imgIndex === images.length - 1){
					newIndex = 0;
				} else {
					newIndex = imgIndex + 1;
				}

				var img = new Image();
				imgContainer.find('img').fadeOut(s, function(){
					modalContainer.append('<div class="loading"><p>Loading....</p></div>');
					imgContainer.empty();
					$(img).attr('src', images[newIndex]).attr('class','loadedImg').load(function(){
						modalContainer.find('div.loading').remove();
						$(this).hide();

						imgContainer.append(this);
						var image = $('img.loadedImg');

						var imgW = $('img.loadedImg').width() + 20,
							imgH = $('img.loadedImg').height() + 20;
							
						imgContainer.width($('img.loadedImg').width()).height($('img.loadedImg').height());
						modalContainer.animate({width: imgW + 'px', marginLeft: '-' + imgW / 2 + 'px'}, s, function(){
							modalContainer.animate({height: imgH + 'px', marginTop: '-' + imgH / 2 + 'px'}, s, function(){
								image.fadeIn(s);
								imgIndex = newIndex;
							});
						});										
					});
				});
				//controls.unbind('click');
				//$(document).unbind('keyup');
				//handleControls();
			}
			
			function prevImage(){
				if (imgIndex === 0){
					newIndex = images.length - 1;
				} else {
					newIndex = imgIndex - 1;
				}
				
				var img = new Image();
				imgContainer.find('img').fadeOut(s, function(){
					modalContainer.append('<div class="loading"><p>Loading....</p></div>');
					imgContainer.empty();
					$(img).attr('src', images[newIndex]).attr('class','loadedImg').load(function(){
						modalContainer.find('div.loading').remove();
						$(this).hide();

						imgContainer.append(this);
							var image = $('img.loadedImg');

						var imgW = $('img.loadedImg').width() + 20,
							imgH = $('img.loadedImg').height() + 20;
						
						imgContainer.width($('img.loadedImg').width()).height($('img.loadedImg').height());	
						modalContainer.animate({width: imgW + 'px', marginLeft: '-' + imgW / 2 + 'px'}, s, function(){
							modalContainer.animate({height: imgH + 'px', marginTop: '-' + imgH / 2 + 'px'}, s, function(){
								image.fadeIn(s);
								imgIndex = newIndex;
							});
						});										
					});
				});
				// controls.unbind('click');
				// 				$(document).unbind('keyup');
				// 				handleControls();
			}
		});	
	};
	
})(jQuery);
