// 
//  jquery.unfurl.js
//  unfurl
//  
//  Created by Sam Luther on 2009-09-03.
//  Copyright 2009 threesixty. All rights reserved.
// 

;(function($){
	
	// get preload in scope
	$.preload = $.preload || {};
	
	var $settings,
		$unfurlAccount,
		$thumbnailListCache = new ObjectCache('thumbnailListCache'),
		$messages = [],
		$selectedAlbum,
		$selectedImage,
		$selectedImageIndex = 0,
		$slideshowRunning = false,
		$slideshowTimer,
		$viewport;
	
	$.fn.unfurl = function(options){
		$settings = $.extend({}, $.fn.unfurl.defaults, options);
		debug($settings);
		return this.each(function(){
			var wireframe = " \
			<p><a id='unfurl-close-link' href='#'>close</a></p> \
			<div id='unfurl-status'>loading...</div> \
			<div class='clearer'>&nbsp;</div> \
			<div id='unfurl-albums'></div> \
			<div id='unfurl-thumbnails'><div id='unfurl-thumbnails-container'></div></div> \
			<ul id='unfurl-image-control-menu'> \
				<li><a id='previous-link' href='#'>previous</a></li> \
				<li><a id='next-link' href='#'>next</a></li> \
				<li><a id='slideshow-link' href='#'>slideshow</a></li> \
				<li><a id='comment-link' href='#'>comment</a></li> \
			</ul> \
			<div id='unfurl-image'> \
				<form id='unfurl-image-comment-form' style='display:none' action='#' method='post' accept-charset='utf-8'> \
					<label for='unfurl-email'>email</label><input type='text' name='unfurl-email' value='' id='unfurl-email'> \
					<label for='unfurl-comment'>comment</label><textarea id='unfurl-comment' name='unfurl-comment' rows='8' cols='40'></textarea> \
					<p><input type='submit' value='send'> \
					<a id='close-comment-link' href='#'>cancel</a></p> \
				</form> \
				<img id='lg-image' style='display:none'> \
				<div id='unfurl-image-description'></div> \
				<div class='clearer'>&nbsp;</div> \
				<div id='unfurl-campanion-image'> \
					<img id='sm-image' style='display:none'> \
				</div> \
			</div> \
			<div class='clearer'>&nbsp;</div> \
			";
			$viewport = $(this);
			$viewport.append(wireframe);
			$viewport.hide();
			loadAccountJson($settings.account);
		});
	};
	
	$.fn.unfurl.defaults = {
		baseUrl: 'http://services.three60.com/unfurl',
		albumSelectedIndicator: '»',
		thumbnailScroller: true,
		thumbnailScrollerHeight: 500,
		slideshowSpeed: 4,
		account: 1,
		thumbnail_width: 95,
		thumbnail_height: 71,
		portrait_width: 372,
		portrait_height: 495,
		landscape_width: 535,
		landscape_height: 404,
		square_width: 300,
		square_height: 300,
		onLoaded: function(){},
		onDisplayImage: function(){},
		onThumbnailClick: function(){},
		onAlbumClick: function(){}
	};
	
	$.fn.unfurl.makeScrollable = function(){
		// alert('gonna make scollable');
		makeScrollable('div#unfurl-thumbnails', 'div#unfurl-thumbnails-container');
	};
	
	function onAccountJsonLoaded(unfurlAccount){
		$unfurlAccount = unfurlAccount.account;
		debug($unfurlAccount);
		// get the first album, load the first albums thumbnails and first full size image by default 
		$selectedAlbum = $unfurlAccount.albums[0];
		
		// image menu rollover animate
		$("#unfurl-image-control-menu li").each(function(){
			// $(this).hover(
			// 	function(){$(this).animate({ width: "130px" }, 200);},
			// 	function(){$(this).animate({ width: "100px" }, 200);}
			// );
		});
		
		$('#slideshow-link').parent().click(function(e){
			if($("#unfurl-image-comment-form").is(':visible')){
				$("#unfurl-image-comment-form").slideUp();
			}	
			startSlideshow();
			return false;
		});
		
		$('#previous-link').parent().click(function(e){
			if($("#unfurl-image-comment-form").is(':visible')){
				$("#unfurl-image-comment-form").slideUp();
			}
			displayPreviousImage();
			return false;
		});
		
		$('#next-link').parent().click(function(e){
			if($("#unfurl-image-comment-form").is(':visible')){
				$("#unfurl-image-comment-form").slideUp();
			}
			displayNextImage();
			return false;
		});
		
		$('#comment-link').parent().click(function(e){
			if($("#unfurl-image-comment-form").is(':visible')){
				$("#unfurl-image-comment-form").slideUp();
			}else{
				$("#unfurl-image-comment-form").slideDown();
			}
			return false;
		});
		
		$('#close-comment-link').parent().click(function(e){
			$("#unfurl-image-comment-form").slideUp();
			return false;
		});
		
		$('#unfurl-image-comment-form').submit(function(e){
			// TODO: need to fix url, only need photo id i think
			// do ajax post to service, then return a response
			var postCommentUrl = $settings.baseUrl+'/photos/'+$selectedImage.id+'/comments.xml',
			comments = $('#unfurl-comment').val(), 
			author = $('#unfurl-email').val(),
			params = {'comment[photo_id]': $selectedImage.id,
					  'comment[album_id]': $selectedAlbum.id,
					  'comment[account_id]': $unfurlAccount.id,
					  'comment[comment]': comments,
					  'comment[author]': author};
			debug(postCommentUrl);
			
			$.post(postCommentUrl, params, function(){
				$('#unfurl-image-comment-form').slideUp();
				$('#unfurl-comment').val('');
				$('#unfurl-email').val('');
				setStatus('You\'re comment has been posted', 2);
			});
			
			return false;
		});
			
		$('#unfurl-thumbnails').css({height:$settings.thumbnailScrollerHeight+'px'});
		
		setStatus($unfurlAccount.albums.length > 1  ? $unfurlAccount.company+' : '+$unfurlAccount.albums.length+' albums loaded' 
										  			: $unfurlAccount.company+' : '+$unfurlAccount.albums.length+' album loaded')
		
		buildAlbumList($unfurlAccount.albums);
		var firstAlbumPhotos = $selectedAlbum.photos;
		buildThumbnailList(firstAlbumPhotos);
		// makeScrollable('div#unfurl-thumbnails', 'div#unfurl-thumbnails-container');
		// $viewport.fadeIn();
		$settings.onLoaded.call(this);
	};
	
	function displayPreviousImage(){
		$selectedImageIndex--;
		if($selectedImageIndex >= 0){
			var previousImage = $selectedAlbum.photos.photo[$selectedImageIndex];
			displayImage(previousImage);
		}
	};
	
	function displayNextImage(){
		$selectedImageIndex++;
		if($selectedImageIndex < $selectedAlbum.photos.photo.length){
			var nextImage = $selectedAlbum.photos.photo[$selectedImageIndex];
			displayImage(nextImage);
		}
	};
	
	function stopSlideshow(){
		clearInterval($slideshowTimer);
		setStatus('Slideshow stopped', 2);
	}
	
	function startSlideshow(){
		debug($selectedAlbum);
		setStatus('Slideshow running...');
		$slideshowRunning = true;
		// get array of image names
		var images = $.map($selectedAlbum.photos.photo, function(image){ return image.orientation; });
		// this craps out on a lot of images, over 40?		
		$.preload( images, {
			base: $settings.baseUrl+'/'+$selectedAlbum.photos.directory+'/'+$selectedAlbum.photos.photo[0].album_id,
			onComplete: function(){	
			},
			onFinish: function(){
				var speed = $settings.slideshowSpeed * 1000;
				$slideshowTimer = setInterval(displayNextSlide, speed);
				var num = 0;
				function displayNextSlide(){
					if(num >= $selectedAlbum.photos.photo.length){
						clearInterval($slideshowTimer);
						setStatus('Slideshow complete');
					}else{
						displayImage($selectedAlbum.photos.photo[num]);
					}
					num++;
				}
			}
		});
	}
	
	function debug(obj){
		if(window.console && window.console.log){
			window.console.log(obj);
		}
	};
	
	function loadAccountJson(id){
		$.getJSON($settings.baseUrl + "/accounts/"+ id +".json?callback=?", onAccountJsonLoaded);		
	};
	
	function setStatus(msg){
		$("#unfurl-status").html("<p>"+ msg + "</p>") //.effect("highlight", {color:'#555'}, 1000);
	};
	
	function buildAlbumList(albums){
		var ablumList = $('<ul id="unfurl-album-list"><ul>');
		$.each(albums, function(){
			var album = this;
			var listItem = $('<li>'+album.name+'</li>');
			var photos = album.photos;
			listItem.data('AlbumData', album);
			
			listItem.click(function(e){
				$("#unfurl-album-list li").each(function(){
					$(this).html(
						$(this).html().replace( $settings.albumSelectedIndicator, "" )
					);
				});
				e.preventDefault; 
				buildThumbnailList(photos);
				setStatus(album.name);
				$selectedAlbum = album;
				$selectedImageIndex = 0;
				$(this).html(album.name + " <span class='unfurl-selected-album-indicator'>" + $settings.albumSelectedIndicator + '</span>');
				$settings.onThumbnailClick.call(this, album);
				if($slideshowRunning){
					stopSlideshow();
				}
				if($("#unfurl-image-comment-form").is(':visible')){
					$("#unfurl-image-comment-form").slideUp();
				}
			});
			//  hand cursor on roll over
			listItem.hover(
				function(){
					$(this).css({cursor:'pointer'});
					$(this).animate({ width: "130px" }, 300); 
				},
				function(){
					$(this).animate({ width: "160px" }, 150);
				}
			);		
			ablumList.append(listItem);
		});
		$('#unfurl-albums').html(ablumList);		
	};
	
	function buildThumbnailList(photos){
		// alter this css to make custom layout
		$('#unfurl-thumbnails').addClass('listStyle-custom');
		if($settings.thumbnailScroller === true){
			$('#unfurl-thumbnails').removeClass('listStyle-custom').addClass('listStyle-verticalScroll');
			thumbnailListId = "unfurl-thumbnail-list-"+photos.photo[0].album_id;
		}
		var thumbnailListId = "unfurl-thumbnail-list-"+photos.photo[0].album_id;
		
			
		if($thumbnailListCache.contains(thumbnailListId)){
			// if we have in cache, hide all lists then fadeIn the cached list
			$('#unfurl-thumbnails ul').each(function(){
				$(this).hide();
			});
			$thumbnailListCache.fetch(thumbnailListId).fadeIn();
			// display first photo in thumbnail list
			displayImage(photos.photo[0]);
			debug('using cached thumbnail list');
		}else{
			var thumbnailList = $('<ul id="'+thumbnailListId+'"></ul>');
			var thumbnames = $.map(photos.photo, function (a) { return a.thumbnail; });
			var fullsize = $.map(photos.photo, function (a) { return a.orientation; });
					
			$.each(photos.photo, function(i, val){
				var image = this,
				thumbnailListItem = $("<li id='"+this.orientation.replace(/[^a-zA-Z 0-9]+/g,'')+"'><a href='#' title='"+this.description+"'><img src=\""+$settings.baseUrl + "/images/unfurl/accounts/" + image.directory + "/" + image.thumbnail+"\" alt='"+image.description+"'></a></li>");
				thumbnailListItem.data('ImageData', image);
				// add thumb click handler
				thumbnailListItem.click(function(e){
					e.preventDefault; 
					setStatus(image.label);
					$selectedImage = image;
					displayImage(image);
					$selectedImageIndex = i;
					// alert($selectedImageIndex);
					$settings.onThumbnailClick.call(this, image);
					if($slideshowRunning){
						stopSlideshow();
					}
					if($("#unfurl-image-comment-form").is(':visible')){
						$("#unfurl-image-comment-form").slideUp();
					}
					return false;
				});
				//  hand cursor on roll over
				thumbnailListItem.hover(
					function(){$(this).css({cursor:'pointer'})},
					function(){}				
				);
				thumbnailList.append(thumbnailListItem);
			});	
					
			// if we have any lists present, hide them
			$('#unfurl-thumbnails-container ul').each(function(){
				$(this).hide();
			});
			
			$('#unfurl-thumbnails-container').append(thumbnailList);
			// display first photo in thumbnail list
			$selectedImage = photos.photo[0];
			displayImage($selectedImage); 
			
			// cache it
			$thumbnailListCache.store(thumbnailListId, thumbnailList);
		}
	};
	
	function displayImage(imageData){
		var $image = $('img#lg-image');
		var $description = $('#unfurl-image-description');
			
		var $companion_image = $('img#sm-image');
		setStatus(imageData.label);
		if(imageData.has_companion){
			// show the container, hide the image, then set url and display
			$companion_image.parent().show();
			$companion_image.hide();
			$companion_image.attr('src', $settings.baseUrl + '/images/unfurl/accounts/' + imageData.directory + '/' + imageData.companion_thumbnail).show();			
			
			var onCompanionClick = function(e){
				e.preventDefault; 
				setStatus(imageData.companion_photo);
				var companionThumbnail = $("#"+imageData.companion_photo.replace(/[^a-zA-Z 0-9]+/g,''));
			 	displayImage(companionThumbnail.data('ImageData'));
				if($slideshowRunning){
					stopSlideshow();
				}
				debug("assigning click for companion")
				$companion_image.unbind('click', onCompanionClick); // remove this handler when done
			}
			$companion_image.click(onCompanionClick);
		}else{
			$companion_image.parent().hide();
		}
		
		// show description if we have one
		$description.hide();		
		if(imageData.description != null && imageData.description != ''){
			$description.html("<p>"+imageData.description+"</p>").fadeIn();
		}
		
		$image.hide();
		$image.attr('src', $settings.baseUrl + '/images/unfurl/accounts/' + imageData.directory + '/' + imageData.orientation).show();
		$settings.onDisplayImage.call(this, imageData);
	};
	
	function makeScrollable(wrapper, scrollable){
		// Get jQuery elements
		var wrapper = $(wrapper), scrollable = $(scrollable);
		// Hide images until they are not loaded
		scrollable.hide();
		// Timeout added to fix problem with Chrome
		setTimeout(function(){
			// Remove scrollbars	
			wrapper.css({overflow: 'hidden'});
			scrollable.fadeIn('slow', function(){
				enable();	
			});					
		}, 1000);

		function enable(){
			// height of area at the top at bottom, that don't respond to mousemove
			var inactiveMargin = 99;					
			// Cache for performance
			var wrapperWidth = wrapper.width();
			var wrapperHeight = wrapper.height();
			// Using outer height to include padding too
			var scrollableHeight = scrollable.outerHeight() + 2*inactiveMargin;
			var lastTarget;
			//When user move mouse over menu			
			wrapper.mousemove(function(e){
				// Save target
				lastTarget = e.target;
				var wrapperOffset = wrapper.offset();
				// Scroll menu
				var top = (e.pageY -  wrapperOffset.top) * (scrollableHeight - wrapperHeight) / wrapperHeight - inactiveMargin;
				if (top < 0){
					top = 0;
				}			
				wrapper.scrollTop(top);
			});	
		}
	};
	
	// object cache
	function ObjectCache(name){
		return{
			_cache : {},
			name : name,
			size: function(){
				var length = 0;
				for(var key in this._cache){
					length++;
				}	
				return length;
			},
			reset: function(){
				for(var key in this._cache){
					this._cache[key] = undefined;
				}
			},
			store: function(key,value){
				return this._cache[key] = value;
			},
			fetch: function(key){
				return this._cache[key] != undefined ? this._cache[key] : '';
			},	
			contains: function(key){
				return this._cache[key] === undefined ? false : true;
			},		
			remove: function(key){
				delete this._cache[key];
			}	
		}
	};
	
})(jQuery);

