var scroller = function() {
	this.initialize.apply(this, arguments);
}

scroller.prototype = {
	initialize: function(selector, options) {
		options = options || new Object();
		this.visible_children = options.visible_children || 1;
		this.selector = selector;
		this.locked = false;
		this.scroll_queue = [];
		this.loop = options.loop || false;
		this.data_selector = options.data_selector || ".data";
		this.scroll_window = $(selector + ".body").get(0);
		this.content_width = options.content_width || (this.scroll_window && this.scroll_window.clientWidth);
		this.new_page_callback = options.new_page_callback;
		if(!this.content_width) return;
		
		/* Ajax loading !! */
		this.url = options.url;
		this.per_page = options.per_page;
		this.total_pages = options.total_pages;
		this.current_page = options.current_page;
		
		
		this.auto_slider_paused = false;
		this.auto_slider_timeout = options.auto_slide*1000 || false;
		if(this.auto_slider_timeout) {
		  var self = this;
		  var auto_slider;
		  
		  auto_slider = function() {
        // console.log("autoslider");
		    if (!self.auto_slider_paused) {
          // console.log("slide auto");
  		    self.scrollRight();
		    }
		    setTimeout(auto_slider, self.auto_slider_timeout);
		  }
		  setTimeout(auto_slider, self.auto_slider_timeout);
		}
		
		if(this.url)
			this.ajax = true;
		else
			this.ajax = false;
		
		if(this.ajax) {
			this.markFirstLast();
		} else {
			$(this.data_selector+":first", selector).addClass("first");
			$(this.data_selector+":last", selector).addClass("last");
		}
		this.duration = options.duration || 0.7;
		this.steps = options.steps || 100;
		this.custom_duration = null;
		this.custom_steps = null;
		
		var self = this;
		$(".left", selector).click(function() { self.scrollLeft(); return false; });
		$(".right", selector).click(function() { self.scrollRight(); return false; });

		// $(selector).bind('mousewheel', function(event){self.mouseSideScroll(event); return false;})
		this.tryShowHideNav();
	},
	
	
	pause_auto_slide: function() {
		//console.log("paused");
	  this.auto_slider_paused = true;
	},
	
	resume_auto_slide: function() {
		//console.log("resumed");
	  this.auto_slider_paused = false;
	},
	
	markFirstLast: function() {
		if(this.current_page == 1) {
			$(this.selector+" "+this.data_selector+":first").addClass("first");
		}
		if(this.current_page == this.total_pages) {
			$(this.selector+" "+this.data_selector+":last").addClass("last");
		}
	},

	tryShowHideNav: function() {
		if(this.hideNavigationControls()) {
			$(this.selector).find(".left").css('visibility', 'hidden').end().find(".right").css('visibility', 'hidden');
		} else {
			$(this.selector).find(".left").css('visibility', 'visible').end().find(".right").css('visibility', 'visible');
		}
	},
	
	hideNavigationControls: function() {
		if(this.ajax) {
			this.activateDeactivateNav();
			return this.total_pages <= 1;
		} else {
			var data = $(this.selector).find(this.data_selector).get();
			return (data.length < this.visible_children+1);
		}
	},
	
	mouseSideScroll: function(event) {
		if(!event.wheelDeltaX) return;
		this.scroll(event.wheelDeltaX > 0);
	},
	
	activateDeactivateNav: function() {
		if(!this.ajax) return;
		$(this.selector + " .left, "+this.selector + " .right").removeClass("not-act");
		if(this.current_page == 1) {
			$(this.selector + " " + ".left").addClass("not-act");
		}
		if(this.current_page == this.total_pages) {
			$(this.selector + " " + ".right").addClass("not-act");
		}
	},
	
	preloadPage: function(left) {
		var new_page = left ? this.current_page - 1 : this.current_page + 1;
		if(new_page < 1 || new_page > this.total_pages) { this.locked = false; return; }
		$(this.selector + " .left, "+this.selector + " .right").addClass("not-act");
		$(this.selector + " .scroll-overlay").show();
		var self = this;
		$.ajax({
		url : this.url, 
		data : {page : new_page, per_page : this.per_page}, 
		success : function(reply) {
			$(self.selector + " " + self.data_selector + ":last").after(reply);
			self.current_page = new_page;
			$(self.selector + " .scroll-overlay").hide();
			self.locked = false;
			self.realScroll(left);
		},
		error : function() { 
			$(self.selector + " .scroll-overlay").hide();
			self.locked = false; 
		},
		dataType : "html"});
	},
	
	schedule_scroll: function(left, duration, steps) {
		this.custom_duration = (duration == undefined ? null : duration);
		this.custom_steps = (steps == undefined ? null : steps);
		
	  if(this.locked) {
	    this.scroll_queue[this.scroll_queue.length] = left;
	  } else {
	    this.scroll(left);
	  }
	},

	scroll: function(left) {
		if(this.locked) return;
		$(this.selector).trigger('scroller.start', [left ? 'left' : 'right']);
		if(this.ajax) {
			this.locked = true;
			this.preloadPage(left)
		} else {
			this.realScroll(left);
		}
	},

	realScroll: function(left) {
		var data = $(this.selector+" "+this.data_selector).get();
		
		// No need to scroll at all, because all children are visible
		if(data.length <= this.visible_children) return;
		
		if(!this.loop) {
			if(left && $(data[0]).hasClass("first")) {return;}
			if(!left && data[this.visible_children] && $(data[this.visible_children]).hasClass("first")) { return;}
		}
		
		this.locked = true;
		
		if(left) {
			data[data.length - 1].style.position = "absolute";
			data[data.length - 1].style.left = "-"+this.content_width+"px";
			data[0].parentNode.insertBefore(data[data.length - 1], data[0]);
			data = $(this.selector+" "+this.data_selector).get();
			var shift = -1;
			var sign = 1;
		} else {
			var shift = 0;
			var sign = -1;
		}
		
		for(var i = 0; i < data.length; i++) {
			data[i].style.position = "absolute";
			data[i].style.left = this.content_width*(i+shift)+"px";
		}

		var self = this;
		this.mover(function(percent) {
			var offset = Math.round(self.content_width*(shift + sign * percent));
			for(var i = 0; i <= self.visible_children; i++) {
				data[i].style.left = "" + (self.content_width*i + offset)+"px";
			}
		}, function() {
			if(!left) {
				data[0].parentNode.appendChild(data[0]);
			}
			$(self.selector+" "+self.data_selector).css('position', '').css('left', '');
			if(self.ajax) {
				for(var i = 0; i < self.visible_children; i++) {
					$(self.selector + " " + self.data_selector + ":last").remove();
				}
				self.activateDeactivateNav();
			}
			if(self.new_page_callback) {
				self.new_page_callback(self.total_pages, self.current_page);
			}
			if (self.scroll_queue.length > 0) {
			  self.realScroll(self.scroll_queue.shift());
			} else {
  			$(self.selector).trigger('scroller.stop', [left ? 'left' : 'right']);
  			self.locked = false;
			}
			
			self.custom_duration = null;
			self.custom_steps = null;
		});
	},
	
	scrollLeft: function() {
		this.scroll(true);
	},
	
	
	scrollRight: function() {
		this.scroll(false);
	},

	mover: function(offsetter, callback) {
		var self = this;
		
		var steps = (this.custom_steps == null ? this.steps : this.custom_steps);
		var duration = (this.custom_duration == null ? this.duration : this.custom_duration);
				
		var timeout = duration*970.0 / steps;
		var step_count = 0;
		var runner = function(){
			var steps_left = steps - step_count;
			offsetter(1.0 - steps_left*1.0/steps);
			step_count += 1;
			if(step_count <= steps) { window.setTimeout(runner, timeout);}
			else { callback(); }
		};
		window.setTimeout(runner, timeout);		
	}
};

scroller.prototype.constructor = scroller;



