/**
 * fsCarousel with jQuery
 * @since 2011
 * @author h.arao
 */

$.fn.fsCarousel = function(options) {
	var self = $(this);
	self.options = {
		auto              : false,
		mouseoverStopAuto : true,
		zoom              : 0.9,
		foregroundWidth   : 200,
		foregroundZoom    : 1.5,
		itemWidth         : 140,
		tilt              : 2,
		shuffle           : false,
		autoInterval      : 2000,
		autoDuration      : 1000,
		feedMaxDuration   : 1500,
		feedMinDuration   : 200,
		feedAcceleration  : 1000,
		nextIcon          : 'js/fsCarousel/images/next_white.gif',
		prevIcon          : 'js/fsCarousel/images/prev_white.gif',
		iconOpacity       : 0.7
	};

	self.initImages = self.find('img');

	var imagesWaitId = null;
	imagesWaitId = setInterval(function(){
		if (self.chkImagesComplete()) {
			clearInterval(imagesWaitId);
			self.init();
		}
	}, 50);

	self.chkImagesComplete = function() {
		var compleatCount = 0;
		self.initImages.each(function() {
			if (this.complete) {
				compleatCount++;
			}
		});
		return compleatCount == self.initImages.length;
	};


	self.init = function() {
		$.extend(self.options, options);

		self.isPositive = true;
		self.duration = self.options.autoDuration;

		self.items = new Array();
		var i = 0;
		self.ch = self.children();
		self.css('position', 'relative');
		self.css('margin', '0');
		self.css('overflow', 'hidden');
		self.css('padding', '0');

		self.ch.css('position', 'absolute');
		self.ch.css('opacity', '0');
		self.ch.css('display', 'block');
		self.ch.css('padding', '0');

		if (self.options.auto) {
			if (self.options.mouseoverStopAuto) {
				self.mouseover(function(){self.stopAuto();});
			}
			self.mouseout(function(e){
				if (self.position().left > e.pageX || self.position().left + self.width() < e.pageX || self.position().top > e.pageY || self.position().top + self.height() < e.pageY ) {
					self.auto();
				}
			});
		}
		self.ch.each(function() {
			var item = $(this);
			$.extend(item, fsCarouselItem);
			item.par     = self;
			item.img     = item.find('img');
			item.canvas  = item.find('canvas');
			item.oWidth  = item.img.width();
			item.oHeight = item.img.height();
			if (self.options.auto && self.options.mouseoverStopAuto) {
				item.mouseover(function(){self.stopAuto();});
			}
			i ++;
			self.items.push(item);
		});

		if (self.options.shuffle) {
			var i = self.items.length;
			while(i) {
				var j = Math.floor(Math.random()*i);
				var temp = self.items[--i];
				self.items[i] = self.items[j];
				self.items[j] = temp;
			}
		}

		self.iw                    = self.options.itemWidth * self.options.zoom; // item width
		self.dm                    = self.width() - self.iw;                     // diameter
		self.bzi                   = 1000;                                       // base z-index
		self.rfr     = (self.options.foregroundWidth * self.options.zoom + self.iw) / (self.dm/2); // range of the foreground area radian
		var unitRad                = (Math.PI * 2 - self.rfr)/ (self.items.length - 2);
		self.cfr    = 1/2 * Math.PI;              // center of the foreground area radian
		self.sfr = self.cfr - self.rfr / 2; // start of the foreground area radian
		self.efr   = self.cfr + self.rfr / 2; // end of the foreground area radian
		self.tr                    = (90 - self.options.tilt) * Math.PI / 180; // tilt rad
		self.bzo                   = 0.5 * self.options.zoom; // base zoom
		self.tb                    = Math.cos(self.tr) * self.dm / 2 * self.bzo; // top bias

		self.baseRads = new Array();
		self[0].offset = 0;
		// foreground item
		self.baseRads[0] = 1/2 * Math.PI;

		// other item
		for (var i = 0; i < self.items.length - 1; i++) {
			var rad = unitRad * i + self.efr;
			if (rad > Math.PI * 2) {
				self.baseRads[i+1] = rad - Math.PI * 2;
			} else {
				self.baseRads[i+1] = rad;
			}
		}
		self.display();
	};

	self.calcPos = function(rad, zf) {
		var result        = {};
		result.zoom       = (Math.sin(rad) + 1) / 4 * self.options.zoom * zf + self.bzo;
		result.zIndex     = Math.floor(self.bzi + Math.sin(rad) * self.bzi);
		result.left       = (Math.cos(rad) + 1) * self.dm / 2 - self.options.itemWidth * result.zoom / 2 + self.iw / 2;
		result.top        = Math.sin(rad) * Math.cos(self.tr) * self.dm / 2 * result.zoom + self.tb;
		result.opacity    = Math.sin(rad) + 0.9;
		return result;
	};

	self.display = function() {
		self.displayIcon();
		self.moveRad(0);
		for (var i in self.items) {
			self.items[i].fadeIn2('slow');
		}
		self.auto();
	};

	self.displayIcon = function() {
		if (self.options.nextIcon || self.options.prevIcon) {
			var iconArea = $('<li></li>').width(self.innerWidth()).css({
				'z-index' : self.bzi * 3,
				position  : 'absolute',
				bottom    : '0',
				display   : 'block',
				padding   : 0,
				margin    : 0
			});
			if (self.options.nextIcon) {
				var nextIcon = $('<a style="float: left; margin: 5px;" class"fsCarousel_icon"><img src="' + self.options.nextIcon + '" /></a>');
				nextIcon.attr('href', 'javascript:void(0);');
				nextIcon.css('opacity', self.options.iconOpacity);
				nextIcon.mousedown(function(e) {
					self.stopAuto();
					var biginTime = (new Date).getTime();
					self.feed(1, biginTime);
					self.feedId = setInterval(function(){self.feed(1, biginTime);}, 50);
				});
				nextIcon.mouseout(self.stopFeed).mouseup(self.stopFeed);
				iconArea.append(nextIcon);
			}
			if (self.options.nextIcon) {
				var prevIcon = $('<a style="float: right; margin: 5px;" class"fsCarousel_icon"><img src="' + self.options.prevIcon + '" /></a>');
				prevIcon.attr('href', 'javascript:void(0);');
				prevIcon.css('opacity', self.options.iconOpacity);
				prevIcon.mousedown(function(e) {
					self.stopAuto();
					var biginTime = (new Date).getTime();
					self.feed(-1, biginTime);
					self.feedId = setInterval(function(){self.feed(-1, biginTime);}, 50);
				});
				prevIcon.mouseout(self.stopFeed).mouseup(self.stopFeed);
				iconArea.append(prevIcon);
			}
			self.append(iconArea);
		}
	};

	self.feed = function(offset ,biginTime) {
		var now = (new Date).getTime();
		self.duration = Math.min(self.options.feedMaxDuration, Math.max(self.options.feedMinDuration, self.options.feedMaxDuration / ((now - biginTime) / self.options.feedAcceleration)));
		self.moveRad(offset);
	};

	self.stopFeed = function() {
		clearInterval(self.feedId);
		if (self.options.auto && !self.options.mouseoverStopAuto) {
			self.auto();
		}
	};

	self.moveRadCompFlg = true;
	self.moveRad = function(offset) {
		if (!self.moveRadCompFlg) return;
		self.moveRadCompFlg = false;
		setTimeout (self.moveRadComplete, self.duration);
		self.stop(true, false).animate({offset : self[0].offset + offset}, {
			step : function(now, f) {
				for (var i in self.items) {
					var pos     = now + Number(i) + self.items.length * 2;
					var flPos   = Math.floor(pos);
					var baseRad = self.baseRads[flPos % self.items.length];
					var nextRad = self.baseRads[(flPos + 1) % self.items.length];
					if (baseRad > nextRad) {
						nextRad += Math.PI * 2;
					}
					var rad = baseRad + (nextRad - baseRad) * (pos - flPos);

					var zf = 1;
					if (rad >= self.sfr && rad <= self.cfr) {
						zf = 1 + Math.abs((self.options.foregroundZoom - 1) * (rad -self.sfr) / (self.rfr / 2));
					} else if (rad > self.cfr && rad <= self.efr){
						zf = 1 + Math.abs((self.options.foregroundZoom - 1) * (self.efr - rad) / (self.rfr / 2));
					}
					p = self.calcPos(rad, zf);
					if (offset == 0) {
						self.items[i].init(p);
					} else {
						self.items[i].refresh(p);
					}
				}
			},
			duration : self.duration,
			complete :  self.moveRadComplete
		});
	};

	self.moveRadComplete = function() {
		self[0].offset = Math.floor(self[0].offset) % self.items.length;
		self.moveRadCompFlg = true;
	};


	self.auto =function () {
		if (self.options.auto) {
			self.stopAuto();
			self.duration = self.options.autoDuration;
			self.autoId = setInterval(function(){
					self.moveRad(1);
				}, self.options.autoInterval);
		}
	};
	self.stopAuto =function () {
		clearInterval(self.autoId);
	};
	return self;
};

var fsCarouselItem = {
	init : function(p) {
		this.po = p;
		this.img.width(this.oWidth * p.zoom);
		this.img.height(this.oHeight * p.zoom);
		if (this.canvas) {
			this.canvas.width(this.oWidth * p.zoom);
		}
		this.css('left', p.left);
		this.css('top', p.top);
		this.css('z-index', p.zIndex);
	},
	refresh : function(p) {
		this.init(p);
		this.css('opacity', p.opacity);
	},
	fadeIn2 : function(duration) {
		this.animate({opacity:this.po.opacity}, duration);
	}
};

