/*
 * simplyScroll 2 Alpha - a scroll-tastic jQuery plugin
 *
 * http://logicbox.net/jquery/simplyscroll
 * http://plugins.jquery.com/project/simplyScroll
 *
 * Copyright (c) 2009-2011 Will Kelly - http://logicbox.net
 *
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Last revised: 15/09/2011 21:13
 *
 */

(function($,window,undefined) {

$.fn.simplyScroll = function(options) {
	return this.each(function() {
		new $.simplyScroll(this,options);
	});
};

var defaults = {
	customClass: 'simply-scroll',
	frameRate: 24, //No of movements per second
	speed: 1, //No of pixels per frame
	orientation: 'horizontal', //'horizontal or 'vertical' - not to be confused with device orientation
	auto: true,
	autoMode: 'loop', //auto = true, 'loop' or 'bounce',
	manualMode: 'end', //auto = false, 'loop' or 'end'
	direction: 'forwards', //'forwards' or 'backwards'.
	pauseOnHover: true,
	pauseButton: false, //generates an extra element to allow manual pausing autoMode = loop|bounce only
	startOnLoad: false, //use this to delay starting of plugin until all page assets have loaded
	flickrFeed: '',
	json: '', //format [{"src":"images/pic.jpg","title":"title","link":"http://"},{etc..}]
	jsonImgWidth: 240,
	jsonImgHeight: 180
};
	
$.simplyScroll = function(el,options) {
	
	var self = this;
	
	this.o = $.extend({}, defaults, options || {});
	this.isAuto = this.o.auto!==false && this.o.autoMode.match(/^loop|bounce$/)!==null;
	this.isHorizontal = this.o.orientation.match(/^horizontal|vertical$/)!==null && this.o.orientation==defaults.orientation; 
	this.isRTL = this.isHorizontal && $("html").attr('dir') == 'rtl';
	this.isForwards = this.isAuto && this.o.direction.match(/^forwards|backwards$/)!==null && this.o.direction==defaults.direction && !this.isRTL;
	this.isLoop = this.o.autoMode == 'loop' || this.o.manualMode == 'loop';
	
	//console.log(this.isForwards);
	
	//console.log(this.isLTR);
	
	this.$list = $(el); //called on ul/ol/div etc
	var $items = this.$list.children();
	
	//generate extra markup
	this.$list.addClass('simply-scroll-list')
		.wrap('<div class="simply-scroll-clip"></div>')
		.parent().wrap('<div class="' + this.o.customClass + ' simply-scroll-container"></div>');
	
	if (!this.isAuto) { //button placeholders
		this.$list.parent().parent()
		.prepend('<div class="simply-scroll-forward"></div>')
		.prepend('<div class="simply-scroll-back"></div>');
	} else {
		if (this.o.pauseButton) {
			this.$list.parent().parent()
			.prepend('<div class="simply-scroll-btn simply-scroll-pause"></div>');
			this.o.pauseOnHover = false;
		}
	}
	
	//wrap an extra div around the whole lot if elements scrolled aren't equal
	if ($items.length > 1) {
		
		var extra_wrap = false,
			total = 0;
			
		if (this.isHorizontal) {
			$items.each(function() { total+=$(this).outerWidth(true); });
			extra_wrap = $items.eq(0).outerWidth(true) * $items.length !== total;
		} else {
			$items.each(function() { total+=$(this).outerHeight(true); });
			extra_wrap = $items.eq(0).outerHeight(true) * $items.length !== total;
		}
		
		if (extra_wrap) {
			this.$list = this.$list.wrap('<div></div>').parent().addClass('simply-scroll-list');
			if (this.isHorizontal) {
				this.$list.children().css({float:'left',width: total + 'px'});	
			} else {
				this.$list.children().css({height: total + 'px'});
			}
		}
	}
	
	//load image data
	if (this.o.flickrFeed) {
		$.getJSON(this.o.flickrFeed + "&format=json&jsoncallback=?",
			function(data) {
				json = [];
				$.each(data.items, function(i,item) {
					json.push({
						"src": item.media.m,
						"title": item.title,
						"link": item.link
					});
				});
				self.renderData(json);
			}
		);
	} else if (this.o.json) {
		//TODO need to coerce to json if string
		this.renderData(json);
	} else {
		
		if (!this.o.startOnLoad) {
			this.init();
		} else {
			//wait for load before completing setup
			$(window).load(function() { self.init();  });
		}
		
	}
		
};
	
$.simplyScroll.fn = $.simplyScroll.prototype = {};

$.simplyScroll.fn.extend = $.simplyScroll.extend = $.extend;

$.simplyScroll.fn.extend({
	init: function() {

		this.$items = this.$list.children();
		this.$clip = this.$list.parent(); //this is the element that scrolls
		this.$container = this.$clip.parent();

		if (!this.isHorizontal) {
			this.itemMax = this.$items.eq(0).outerHeight(true); 
			this.clipMax = this.$clip.height();
			this.dimension = 'height';			
			this.moveBackClass = 'simply-scroll-btn-up';
			this.moveForwardClass = 'simply-scroll-btn-down';
			this.scrollPos = 'Top';
		} else {
			this.itemMax = this.$items.eq(0).outerWidth(true);
			this.clipMax = this.$clip.width();			
			this.dimension = 'width';
			this.moveBackClass = 'simply-scroll-btn-left';
			this.moveForwardClass = 'simply-scroll-btn-right';
			this.scrollPos = 'Left';
		}
		
		this.posMin = 0;
		
		this.posMax = this.$items.length * this.itemMax;
		
		this.$list.css(this.dimension,this.posMax +'px');
		
		if (this.isAuto && this.o.autoMode=='loop') {
			
			var addItems = Math.ceil(this.clipMax / this.itemMax);
			this.$list.css(this.dimension,this.posMax+(this.itemMax*addItems) +'px');
			
			this.posMax += (this.clipMax - this.o.speed);
			
			if (this.isForwards) {
				this.$items.slice(0,addItems).clone(true).appendTo(this.$list);
				this.resetPosition = 0;
				this.$clip[0]['scroll' + this.scrollPos] = 0; //ensure scroll position is reset
			} else {
				this.$items.slice(-addItems).clone(true).prependTo(this.$list);
				this.resetPosition = this.$items.length * this.itemMax;
				this.$clip[0]['scroll' + this.scrollPos] = this.resetPosition; 
				//due to inconsistent RTL implementation force back to LTR then fake
				if (this.isRTL) {
					this.$clip[0].dir = 'ltr';
					//this.$items.css('float','right');
				}
			}
			
		} else if (!this.isAuto && this.o.manualMode=='loop') {
			//TODO
			var addItems = Math.ceil(this.clipMax / this.itemMax);
		}
		
		
		
		this.interval = null;	
		this.intervalDelay = Math.floor(1000 / this.o.frameRate);
		
		//ensure that speed is divisible by item width. Helps to always make images even not odd widths!
		while (this.itemMax % this.o.speed !== 0) {
			this.o.speed--;
			if (this.o.speed===0) {
				this.o.speed=1; break;	
			}
		}
		
		var self = this;
		this.trigger = null;
		this.funcMoveBack = function() { 
			self.trigger=this; 
			if (self.isAuto) {
				self.isForwards ? self.moveBack() : self.moveForward(); 
			} else {
				self.moveBack();	
			}
		};
		this.funcMoveForward = function() { 
			self.trigger=this; 
			if (self.isAuto) {
				self.isForwards ? self.moveForward() : self.moveBack(); 
			} else {
				self.moveForward();	
			}
		};
		this.funcMoveStop = function() { self.moveStop(); };
		this.funcMoveResume = function() { self.moveResume(); };
		
		if (this.isAuto) {
			if (this.o.pauseOnHover) {
				this.$clip.hover(this.funcMoveStop,this.funcMoveResume);
			} else {
				if (this.o.pauseButton) {
					this.$btnPause = $(".simply-scroll-pause",this.$container)
				}
			}
			this.funcMoveForward();
		} else {
			this.$btnBack = $('.simply-scroll-back',this.$container)
				.addClass('simply-scroll-btn' + ' ' + this.moveBackClass + ' ' + 'disabled')
				.hover(this.funcMoveBack,this.funcMoveStop);
			this.$btnForward = $('.simply-scroll-forward',this.$container)
				.addClass('simply-scroll-btn' + ' ' + this.moveForwardClass)
				.hover(this.funcMoveForward,this.funcMoveStop);
		}
	},
	moveForward: function() {
		var self = this;
		this.movement = 'forward';
		if (this.trigger !== null) {
			//this.$btnBack.removeClass('disabled');
		}
		self.interval = setInterval(function() {
			//console.log(self.$clip[0]['scroll' + self.scrollPos]);
			if (self.$clip[0]['scroll' + self.scrollPos] < (self.posMax-self.clipMax)) {
				self.$clip[0]['scroll' + self.scrollPos] += self.o.speed;
			} else if (self.isLoop) {
				self.resetPos();
			} else {
				self.moveStop(self.movement);
			}
		},self.intervalDelay);
	},
	moveBack: function() {
		var self = this;
		this.movement = 'back';
		if (this.trigger !== null) {
			//this.$btnForward.removeClass('disabled');
		}
		self.interval = setInterval(function() {
			//console.log(self.$clip[0]['scroll' + self.scrollPos]);
			if (self.$clip[0]['scroll' + self.scrollPos] > 0) {
				self.$clip[0]['scroll' + self.scrollPos] -= self.o.speed;
			} else if (self.isLoop) {
				self.resetPos();
			} else {
				self.moveStop(self.movement);
			}
		},self.intervalDelay);
	},
	moveStop: function(moveDir) {
		clearInterval(this.interval);	
		if (this.trigger!==null) {
			if (typeof moveDir !== 'undefined') {
				$(this.trigger).addClass('disabled');
			}
			this.trigger = null;
		}
		if (this.isAuto) {
			if (this.o.autoMode=='bounce') {
				moveDir == 'forward' ? this.moveBack() : this.moveForward();
			}
		}
	},
	moveResume: function() {
		this.movement=='forward' ? this.moveForward() : this.moveBack();
	},
	resetPos: function() {
		this.$clip[0]['scroll' + this.scrollPos] = this.resetPosition;
	},
	renderData: function(json) {
		if (json.length>0) { //render json data
			var self = this;
			$.each(json, function(i,item) {
				$("<img/>").attr({
					src: item.src,
					title: item.title,
					alt: item.title,
					width: self.o.jsonImgWidth,
					height: self.o.jsonImgHeight
				}).appendTo(self.$list);
			});
			this.init();
		}
	}
});
		  
})(jQuery,window);
