/*   2/14/2011
		PikaChoose
	Jquery plugin for photo galleries
    Copyright (C) 2011 Jeremy Fry

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
(function($) {
	var defaults = {
		autoPlay : true,
		speed : 5000,
		text : {
			play : "",
			stop : "",
			previous : "Previous",
			next : "Next"
		},
		transition : [ 1 ],
		showCaption : true,
		IESafe : false,
		showTooltips : false,
		animationFinished : null
	};
	$.fn.PikaChoose = function(o) {
		return this.each(function() {
			$(this).data('pikachoose', new $pc(this, o));
		});
	};
	$.PikaChoose = function(e, o) {
		this.options = $.extend({}, defaults, o || {});
		this.list = null;
		this.image = null;
		this.anchor = null;
		this.caption = null;
		this.imgNav = null;
		this.imgPlay = null;
		this.imgPrev = null;
		this.imgNext = null;
		this.textNext = null;
		this.textPrev = null;
		this.previous = null;
		this.next = null;
		this.aniDiv = null;
		this.thumbs = null;
		this.transition = null;
		this.active = null;
		this.tooltip = null;
		this.animating = false;
		this.stillOut = null;
		if (e.nodeName == 'UL' || e.nodeName == 'OL') {
			this.list = $(e);
			this.build();
			this.bindEvents();
		} else {
			return
		}
		var y = 0;
		var x = 0;
		for ( var t = 0; t < 25; t++) {
			var a = '<div col="' + y + '" row="' + x + '"></div>';
			this.aniDiv.append(a);
			y++;
			if (y == 5) {
				x++;
				y = 0;
			}
		}
	};
	var $pc = $.PikaChoose;
	$pc.fn = $pc.prototype = {
		pikachoose : '4.1.6'
	};
	$pc.fn.extend = $pc.extend = $.extend;
	$pc.fn
			.extend({
				build : function() {
					this.step = 0;
					this.wrap = $("<div class='pika-image'></div>")
							.insertBefore(this.list); 
					this.image = $("<img>").appendTo(this.wrap).hide();
					// Change from <span> to <a> if you want to add link on
					// images.
					this.anchor = this.image.wrap("<span>").parent(); 
					this.imgNav = $("<div class='pika-imgnav'></div>")
							.insertAfter(this.anchor);
							 
					this.imgPlay = $("<a></a>").appendTo(this.imgNav);
					if (this.options.autoPlay) {
						this.imgPlay.addClass('pause');
					} else {
						this.imgPlay.addClass('play');
					}
					  
					this.caption = $("<div class='caption'></div>")
							.insertAfter(this.imgNav);
					if (!this.options.showCaption) {
						this.caption.hide();
					}
					this.tooltip = $("<div class='pika-tooltip'></div>")
							.insertAfter(this.list);
					this.tooltip.hide();
					this.aniDiv = $("<div class='animation'></div>")
							.insertAfter(this.caption);
					
					// SS original code
					this.textNav = $("<div class='pika-textnav'></div>")
							.insertAfter(this.aniDiv);
					this.textPrev = $(
							"<a class='previous'>" + this.options.text.previous
									+ "</a>").appendTo(this.textNav);
					this.textNext = $(
							"<a class='next'>" + this.options.text.next
									+ "</a>").appendTo(this.textNav);
				
					this.list.addClass('pika-thumbs');
					this.list.children('li').wrapInner("<div class='clip' />");
					this.thumbs = this.list.find('img');
					this.active = this.thumbs.eq(0);
					this.finishAnimating({
						'source' : this.active.attr('ref')
								|| this.active.attr('src'),
						'caption' : this.active.parents('li:first').find(
								'span:first').html(),
						'clickThrough' : this.active.parent().attr('href')
								|| "",
						'clickThroughTitle' : this.active.parent()
								.attr('title')
								|| ""
					});
					
					
					var self = this;
					this.thumbs.each(function() {
						self.createThumb($(this), self);
					});
					if (typeof (this.options.buildFinished) == 'function') {
						this.options.buildFinished(this);
					}
					
					// SS: The Next and Previous navigation buttons.
					this.imgPrev = $("<a class='previous'></a>").insertAfter(
							this.imgPlay);
					this.imgNext = $("<a class='next'></a>").insertAfter(
							this.imgPrev); 
				},
				createThumb : function(ele) {
					var self = ele;
					var that = this;
					self.hide();
					$.data(ele[0], 'clickThrough', self.parent('a')
							.attr('href')
							|| "");
					$.data(ele[0], 'clickThroughTitle', self.parent('a').attr(
							'title')
							|| "");
					if (self.parent('a').length > 0) {
						self.unwrap();
					}
					$.data(ele[0], 'caption', self.next('span').html() || "");
					self.next('span').remove();
					$.data(ele[0], 'source', self.attr('ref')
							|| self.attr('src'));
					$.data(ele[0], 'order', self.closest('ul').find('li')
							.index(self.parents('li')));
					var data = $.data(ele[0]);
					$('<img />')
							.bind(
									'load',
									{
										data : data
									},
									function() {
										if (typeof (that.options.buildThumbStart) == 'function') {
											that.options.buildThumbStart(that);
										}
										var img = $(this);
										var w = img.width();
										var h = img.height();
										if (w === 0) {
											w = img.attr("width");
										}
										if (h === 0) {
											h = img.attr("height");
										}
										var rw = parseInt(self.parents('.clip')
												.css('width').slice(0, -2))
												/ w;
										var rh = parseInt(self.parents('.clip')
												.css('height').slice(0, -2))
												/ h;
										var ratio;
										if (rw < rh) {
											ratio = rh;
											var left = ((w * ratio - parseInt(self
													.parents('.clip').css(
															'width').slice(0,
															-2))) / 2)
													* -1;
											left = Math.round(left);
											self.css({
												left : left
											});
										} else {
											ratio = rw;
											self.css({
												top : 0
											});
										}
										var width = Math.round(w * ratio);
										var height = Math.round(h * ratio);
										self.css("position", "relative");
										var imgcss = {
											width : width + "px",
											height : height + "px"
										};
										self.css(imgcss);
										self
												.hover(
														function(e) {
															clearTimeout(that.stillOut);
															$(this)
																	.stop(true,
																			true)
																	.fadeTo(
																			250,
																			1);
															if (!that.options.showTooltips) {
																return
															}
															that.tooltip
																	.show()
																	.stop(true,
																			true)
																	.html(
																			data.caption)
																	.animate(
																			{
																				top : $(
																						this)
																						.parent()
																						.position().top,
																				left : $(
																						this)
																						.parent()
																						.position().left,
																				opacity : 1.0
																			},
																			'fast');
														},
														function(e) {
															if (!$(this)
																	.hasClass(
																			"active")) {
																$(this)
																		.stop(
																				true,
																				true)
																		.fadeTo(
																				250,
																				0.4);
																that.stillOut = setTimeout(
																		that.hideTooltip,
																		700);
															}
														});
										if (data.order == 0) {
											self.fadeTo(250, 1);
											self.addClass('active');
										} else {
											self.fadeTo(250, 0.4);
										}
										if (typeof (that.options.buildThumbFinish) == 'function') {
											that.options.buildThumbFinish(that);
										}
									}).attr('src', self.attr('src'));
				},
				bindEvents : function() {
					this.thumbs.bind('click', {
						self : this
					}, this.imgClick);
					this.imgNext.bind('click', {
						self : this
					}, this.nextClick);
					this.textNext.bind('click', {
						self : this
					}, this.nextClick);
					this.imgPrev.bind('click', {
						self : this
					}, this.prevClick);
					this.textPrev.bind('click', {
						self : this
					}, this.prevClick);
					this.imgPlay.bind('click', {
						self : this
					}, this.playClick);
					this.wrap.bind('mouseenter', {
						self : this
					}, function(e) {
						e.data.self.imgPlay.stop(true, true).fadeIn('fast');
					});
					this.wrap.bind('mouseleave', {
						self : this
					}, function(e) {
						e.data.self.imgPlay.stop(true, true).fadeOut('fast');
					});
					this.tooltip.bind('mouseenter', {
						self : this
					}, function(e) {
						clearTimeout(e.data.self.stillOut);
					});
					this.tooltip.bind('mouseleave', {
						self : this
					}, function(e) {
						e.data.self.stillOut = setTimeout(
								e.data.self.hideTooltip, 700);
					});
				},
				hideTooltip : function(e) {
					$(".pika-tooltip").animate({
						opacity : 0.01
					});
				},
				imgClick : function(e, x) {
					var self = e.data.self;
					var data = $.data(this);
					if (self.animating) {
						return
					}
					self.caption.fadeOut('slow');
					if (typeof (x) == 'undefined' || x.how != "auto") {
						if (self.options.autoPlay) {
							self.imgPlay.trigger('click');
						}
					}
					self.animating = true;
					self.active.fadeTo(300, 0.4).removeClass('active');
					self.active = $(this);
					self.active.addClass('active').fadeTo(200, 1);
					$('<img />').bind('load', {
						self : self,
						data : data
					}, function() {
						self.aniDiv.css({
							height : self.image.height(),
							width : self.image.width()
						}).fadeIn('fast');
						self.aniDiv.children('div').css({
							'width' : '20%',
							'height' : '20%',
							'float' : 'left'
						});
						var n = 0;
						if (self.options.transition[0] == -1) {
							n = Math.floor(Math.random() * 6) + 1;
						} else {
							n = self.options.transition[self.step];
							self.step++;
							if (self.step >= self.options.transition.length) {
								self.step = 0;
							}
						}
						if (self.options.IESafe && $.browser.msie) {
							n = 1;
						}
						self.doAnimation(n, data);
					}).attr('src', $.data(this).source);
				},
				doAnimation : function(n, data) {
					var self = this;
					var aWidth = self.aniDiv.children('div').eq(0).width();
					var aHeight = self.aniDiv.children('div').eq(0).height();
					self.aniDiv.children().each(
							function() {
								var div = $(this);
								var xOffset = Math
										.floor(div.parent().width() / 5)
										* div.attr('col');
								var yOffset = Math
										.floor(div.parent().height() / 5)
										* div.attr('row');
								div
										.css({
											'background' : 'url(' + data.source
													+ ') -' + xOffset + 'px -'
													+ yOffset + 'px',
											'width' : '0px',
											'height' : '0px',
											'position' : 'absolute',
											'top' : yOffset + 'px',
											'left' : xOffset + 'px',
											'float' : 'none'
										});
							});
					switch (n) {
					case 0:
						self.aniDiv.hide();
						self.image.stop(true, true).fadeOut(
								'slow',
								function() {
									self.image.attr('src', data.source).fadeIn(
											'slow', function() {
												self.finishAnimating(data);
											});
								});
						break;
					case 1:
						self.aniDiv.height(self.image.height()).hide().css(
								{
									'background' : 'url(' + data.source
											+ ') top left no-repeat'
								});
						self.aniDiv.children('div').hide();
						self.aniDiv.fadeIn('slow', function() {
							self.finishAnimating(data);
							self.aniDiv.css({
								'background' : 'transparent'
							});
						});
						break;
					case 2:
						self.aniDiv
								.children()
								.hide()
								.each(
										function(index) {
											var delay = index * 30;
											$(this)
													.css({
														opacity : 0.1
													})
													.show()
													.delay(delay)
													.animate(
															{
																opacity : 1,
																"width" : aWidth,
																"height" : aHeight
															},
															200,
															'linear',
															function() {
																if ($(this)
																		.parents(
																				'.animation')
																		.find(
																				"div")
																		.index(
																				this) == 24) {
																	self
																			.finishAnimating(data);
																}
															});
										});
						break;
					case 3:
						self.aniDiv
								.children("div:lt(5)")
								.hide()
								.each(
										function(index) {
											var delay = $(this).attr('col') * 100;
											$(this)
													.css({
														opacity : 0.1,
														"width" : aWidth
													})
													.show()
													.delay(delay)
													.animate(
															{
																opacity : 1,
																"height" : self.image
																		.height()
															},
															700,
															'linear',
															function() {
																if ($(this)
																		.parents(
																				'.animation')
																		.find(
																				" div")
																		.index(
																				this) == 4) {
																	self
																			.finishAnimating(data);
																}
															});
										});
						break;
					case 4:
						self.aniDiv
								.children()
								.hide()
								.each(
										function(index) {
											var delay = $(this).attr('col') * 10;
											aHeight = self.gapper($(this),
													aHeight);
											$(this)
													.css({
														opacity : 0.1,
														"height" : aHeight
													})
													.show()
													.delay(delay)
													.animate(
															{
																opacity : 1,
																"width" : aWidth
															},
															800,
															'linear',
															function() {
																if ($(this)
																		.parents(
																				'.animation')
																		.find(
																				" div")
																		.index(
																				this) == 24) {
																	self
																			.finishAnimating(data);
																}
															});
										});
						break;
					case 5:
						self.aniDiv
								.children()
								.show()
								.each(
										function(index) {
											var delay = index
													* Math
															.floor(Math
																	.random() * 5)
													* 10;
											aHeight = self.gapper($(this),
													aHeight);
											if ($(".animation div").index(this) == 24) {
												delay = 800;
											}
											$(this)
													.css({
														"height" : aHeight,
														"width" : aWidth,
														"opacity" : .01
													})
													.delay(delay)
													.animate(
															{
																"opacity" : 1
															},
															800,
															function() {
																if ($(this)
																		.parents(
																				'.animation')
																		.find(
																				" div")
																		.index(
																				this) == 24) {
																	self
																			.finishAnimating(data);
																}
															});
										});
						break;
					case 6:
						self.aniDiv.height(self.image.height()).hide().css(
								{
									'background' : 'url(' + data.source
											+ ') top left no-repeat'
								});
						self.aniDiv.children('div').hide();
						self.aniDiv.css({
							width : 0
						}).show().animate({
							width : self.image.width()
						}, 'slow', function() {
							self.finishAnimating(data);
							self.aniDiv.css({
								'background' : 'transparent'
							});
						});
						break;
					}
				},
				finishAnimating : function(data) {
					this.animating = false; 
					
					// SS Fixing an issue with Firefox 4.
					this.image.attr('src', data.source).show();
						
					var self = this;
					$('<img />').bind('load', function() {    
						 self.aniDiv.hide();  
					}).attr('src', data.source);
					// ------
					 
					this.anchor.attr('href', data.clickThrough);
					this.anchor.attr('title', data.clickThroughTitle);
					if (this.options.showCaption) {
						this.caption.html(data.caption).fadeIn('slow');
					}
					if (this.options.autoPlay == true) {
						var self = this;
						this.image.delay(this.options.speed).fadeIn(0,
								function() {
									if (self.options.autoPlay) {
										self.nextClick();
									}
								});
					}
					if (typeof (this.options.animationFinished) == 'function') {
						this.options.animationFinished(this);
					}
				},
				gapper : function(ele, aHeight) {
					if (ele.attr('row') == 9 && ele.attr('col') == 0) {
						var gap = ani_divs.height() - (aHeight * 9);
						return gap;
					}
					return aHeight;
				},
				nextClick : function(e) { 
					var how = "natural";
					try {
						var self = e.data.self;
						if (typeof (e.data.self.options.next) == 'function') {
							e.data.self.options.next(this);
						}
					} catch (err) {
						var self = this;
						how = "auto";
					}
					var next = self.active.parents('li:first').next().find(
							'img');
					if (next.length == 0) {
						next = self.list.find('img').eq(0);
					}
					;
					next.trigger('click', {
						how : how
					});
				},
				prevClick : function(e) {
					if (typeof (e.data.self.options.previous) == 'function') {
						e.data.self.options.previous(this);
					}
					var self = e.data.self;
					var prev = self.active.parents('li:first').prev().find(
							'img');
					if (prev.length == 0) {
						prev = self.list.find('img:last');
					}
					;
					prev.trigger('click');
				},
				playClick : function(e) {
					var self = e.data.self;
					self.options.autoPlay = !self.options.autoPlay;
					self.imgPlay.toggleClass('play').toggleClass('pause');
					if (self.options.autoPlay) {
						self.nextClick();
					}
				}
			});
})(jQuery);
