/*
 * Plugin for jQuery
 * Author: Aleksey Rybitskyi
 * Name: acarousel
 * Author's site: http://najdem.com/ http://arybitskyi.com/
 * You can use this script by GPL license
 */
;jQuery.fn.acarousel = function(settings){
	if(this.size()==0)return this;	
	//Saving this object
	var o = this;
	//Settings
	this.settings = jQuery.extend({
		scroll_items:			2,
		scroll_time:			500,
		scroll:					'vertical',
		scroll_to_item_index:	-1,
		scroll_to_item_id:		null,
		scroll_to_position:		0
	},settings);
	//Variables
	this.vars = {
		scrolling:	false,
		loaded:		0,
		loading:	0,
		errors:		0,
		complete:	false,
		start_load:	false,
		actions:	new Array
	};
	//Binding events
	this.find('.arrow_top').bind('click',{object:this,move:'up'},scroll);
	this.find('.arrow_bottom').bind('click',{object:this,move:'down'},scroll);
	this.mousewheel(function(e,d){
		var move;
		if(d>0)
			move = 'up';
		else
			move = 'down';
		var e = {};
		e.data = {};
		e.data.move = move;
		if(scroll(e)||o.vars.scrolling)
			return false;
		else
			return true;
	});
	
	//Preloading all images
	preload(o);
	
	//Counting all vars for speed up
	//We do this once if height / width of each element in carousel is fixed
	//else we need to paste string "acount(o);" to scroll() function at the beginning of it
	//acount(o);
	//Checking if we need scroll to position or item at the beginning
	if(o.settings.scroll_to_position != 0){
		scrollToPosition(o.settings.scroll_to_position);
	}
	else if(o.settings.scroll_to_item_index != -1){
		scrollToItemByIndex(o.settings.scroll_to_item_index);
	}
	else if(typeof o.settings.scroll_to_item_id == 'string'){
		scrollToItemById(o.settings.scroll_to_item_id);
	}
	
	//add action to do after complete
	function addAction(action,value){
		o.vars.actions[o.vars.actions.length] = {action:action,value:value};
	}
	
	//scroll function
	function scroll(e){
		if(o.vars.scrolling)return false;

		if(!o.vars.complete)
			return false;

		switch(e.data.move){
			case 'up':
				return scrollToItemByIndex('-'+o.settings.scroll_items);
			break;
			case 'down':
				return scrollToItemByIndex('+'+o.settings.scroll_items);
			break;
		}
	}
	
	//parse integer with params:
	//	* min: minimum value
	//	* max: maximum value
	function parseInteger(cur_value,new_value,params){
		if(typeof params != 'object')params = {};
		if(typeof new_value == 'number'){
			cur_value = new_value;
		}
		else if(typeof new_value == 'string'){
			var action;
			if(new_value.indexOf('+')>=0){
				action = 'plus';
			}
			else if(new_value.indexOf('-')>=0){
				action = 'minus';
			}
			else{
				action = 'new';
			}
			if(action=='plus'||action=='minus')
				new_value = new_value.substring(1,new_value.length);
			new_value = isNaN(parseInt(new_value)) ? 0 : parseInt(new_value);
			switch(action){
				case 'plus':
					cur_value += new_value;
				break;
				case 'minus':
					cur_value -= new_value;
				break;
				case 'new':
					cur_value = new_value;
				break;
			}
		}
		if(typeof params.min == 'number')
			if(cur_value<params.min)
				cur_value = params.min;
		if(typeof params.max == 'number')
			if(cur_value>params.max)
				cur_value = params.max;
		return cur_value;
	}
	
	//scroll to item
	function scrollToItem(item){
		var
			window_start_x = -o.vars.inner_margin_left,
			window_end_x = window_start_x + o.vars.outer_width
			window_start_y = -o.vars.inner_margin_top,
			window_end_y = window_start_y + o.vars.outer_height;
		switch(o.settings.scroll){
			case 'horizontal':
		
				break;
			case 'vertical':
				if(item.item_start_y-item.prev_separator_height>=window_start_y&&item.item_end_y+item.next_separator_height<=window_end_y){
					return false;
				}
				if(item.item_start_y-item.prev_separator_height<window_start_y){
					return scrollToPosition(item.item_start_y - item.prev_separator_height);
				}
				else if(item.item_end_y+item.next_separator_height>window_end_y){
					return scrollToPosition(item.item_end_y-o.vars.outer_height + item.next_separator_height);
				}
			break;
		}
	}
	
	//scroll to item by id
	function scrollToItemById(item_id){
		if(o.vars.scrolling)return false;
		if(!o.vars.complete){
			addAction('scrollToItemById',item_id);
			return false;
		}
		for(var i=0;i<o.vars.els.length;i++)
			if(!o.vars.els[i].separator&&$(o.vars.els[i].node).attr('id')==item_id){
				var item = o.vars.els[i];
				break;
			}
		if(!item)return false;
		scrollToItem(item);
	}
	
	//scroll to item by index
	function scrollToItemByIndex(item_index){
		if(o.vars.scrolling)return false;
		if(!o.vars.complete){
			addAction('scrollToItemByIndex',item_index);
			return false;
		}
		//Searching needed node
		var i,j = 0,item = null;
		for(i=0;i<o.vars.els.length;i++){
			if(!o.vars.els[i].separator){
				j++;
			}
		}
		var
		window_start_x = -o.vars.inner_margin_left,
		window_end_x = window_start_x + o.vars.outer_width
		window_start_y = -o.vars.inner_margin_top,
		window_end_y = window_start_y + o.vars.outer_height;
		cur_item_index = -1;
		max = j - 1;
		j = 0;
		for(i=0;i<o.vars.els.length;i++){
			if(!o.vars.els[i].separator){
				switch(o.settings.scroll){
				case 'horizontal':
					
					break;
				case 'vertical':
						if(window_start_y<=o.vars.els[i].item_start_y-o.vars.els[i].prev_separator_height&&window_end_y>=o.vars.els[i].item_end_y+o.vars.els[i].next_separator_height){
							cur_item_index = j;
						}
					break;
				}
				if(typeof item_index =='string'&&item_index.substring(0,1)=='-')
					if(cur_item_index>=0)break;
				j++;
			}
		}
		item_index = parseInteger(cur_item_index,item_index,{min:0,max:max});
		i=0;
		j=0;
		for(i=0;i<o.vars.els.length;i++)
			if(!o.vars.els[i].separator){
				if(item_index==j){
					item = o.vars.els[i];
					break;
				}
				j++;
			}
		if(!item)return false;
		return scrollToItem(item);
	}
	
	//scroll to position
	function scrollToPosition(position){
		if(o.vars.scrolling)return false;
		if(!o.vars.complete){
			addAction('scrollToPosition',position);
			return false;
		}
		o.vars.scrolling = true;
		switch(o.settings.scroll){
			case 'horizontal':
				cur_position = -o.vars.inner_margin_left;
			break;
			case 'vertical':
				cur_position = -o.vars.inner_margin_top;
				break;
		}
		position = parseInteger(cur_position,position,{min:0,max:o.vars.position_max});
		switch(o.settings.scroll){
			case 'horizontal':
				o.vars.inner.animate({marginLeft:-position},o.settings.scroll_time,function(){
					o.vars.scrolling = false;
					o.vars.inner_margin_left = -position;
					//check arrows activity
					checkArrows();
				});
			break;
			case 'vertical':
				o.vars.inner.animate({marginTop:-position},o.settings.scroll_time,function(){
					o.vars.scrolling = false;
					o.vars.inner_margin_top = -position;
					//check arrows activity
					checkArrows();
				});
			break;
		}
		return true;
	}
	
	//check arrow_top and arrow_bottom active / inactive
	function checkArrows(){
		if(o.vars.inner_margin_top==0){
			o.find('.arrow_top').removeClass('arrow_top_active').addClass('arrow_top_inactive');
		}
		else{
			o.find('.arrow_top').removeClass('arrow_top_inactive').addClass('arrow_top_active');
		}
		if(o.vars.inner_height>o.vars.outer_height){
			if((o.vars.outer_height-o.vars.inner_height)==o.vars.inner_margin_top){
				o.find('.arrow_bottom').removeClass('arrow_bottom_active').addClass('arrow_bottom_inactive');
			}
			else{
				o.find('.arrow_bottom').removeClass('arrow_bottom_inactive').addClass('arrow_bottom_active');
			}
		}
	}
	
	//preload function
	function preload(o){
		var i = 0;
		o.find('img').each(function(){
			loadImage(this.src,'image_'+i);
		});
		o.vars.start_load = true;
	}
	
	//acount function
	function acount(){
		o.vars.outer = o.find('.outer_container');
		o.vars.inner = o.find('.inner_container');
		o.vars.outer_width = o.vars.outer.width();
		o.vars.outer_height = o.vars.outer.height();
		o.vars.inner_width = o.vars.inner.width();
		o.vars.inner_height = o.vars.inner.height();
		o.vars.inner_margin_top = isNaN(parseFloat(o.vars.inner.css('margin-top'))) ? 0 : parseFloat(o.vars.inner.css('margin-top'));
		o.vars.inner_margin_left = isNaN(parseFloat(o.vars.inner.css('margin-left'))) ? 0 : parseFloat(o.vars.inner.css('margin-left'));
		o.vars.els = [];
		o.vars.max_height = 0;
		o.vars.max_width = 0;
		o.vars.separators_count = 0;
		o.vars.items_count = 0;
		var
			sep_width = 0,
			sep_height = 0,
			last_index = 0;
		o.vars.inner.find('> *').each(function(){
			o.vars.els[o.vars.els.length] = {
				node:					this,
				separator:				(this.nodeName=='BR' || (this.nodeName=='DIV'&&this.className=='clear')) ? true : false,
				width:					$(this).width(),
				outer_width:			$(this).outerWidth(),
				outer_width_v:			$(this).outerWidth(true),
				height:					$(this).height(),
				outer_height:			$(this).outerHeight(),
				outer_height_v:			$(this).outerHeight(true),
				left:					$(this).position().left,
				top:					$(this).position().top,
				item_start_x:			this.offsetLeft,
				item_end_x:				this.offsetLeft + $(this).outerWidth(true),
				item_start_y:			this.offsetTop,
				item_end_y:				this.offsetTop + $(this).outerHeight(true),
				prev_separator_width:	0,
				next_separator_width:	0,
				prev_separator_height:	0,
				next_separator_height:	0
			};
			if(!o.vars.els[o.vars.els.length-1].separator)
				if(typeof o.settings.click != 'undefined')
					$(this).click(function(){
						return o.settings.click(this);
					}).focus(function(){
						$(this).blur();
					});
			if(o.vars.els[o.vars.els.length-1].separator){
				if(last_index<0){
					sep_width = 0;
					sep_height = 0;
					last_index = o.vars.els.length - 2;
				}
				sep_width += o.vars.els[o.vars.els.length-1].width;
				sep_height += o.vars.els[o.vars.els.length-1].height;
				o.vars.separators_count++;
			}
			else{
				o.vars.els[o.vars.els.length-1].prev_separator_width = sep_width;
				o.vars.els[o.vars.els.length-1].prev_separator_height = sep_height;
				if(last_index>=0){
					o.vars.els[last_index].next_separator_width = sep_width;
					o.vars.els[last_index].next_separator_height = sep_height;
					last_index = -1;
				}
				o.vars.items_count++;
			}
			if(o.vars.max_height<o.vars.els[o.vars.els.length-1].outer_height_v)
				o.vars.max_height = o.vars.els[o.vars.els.length-1].outer_height_v;
			if(o.vars.max_width<o.vars.els[o.vars.els.length-1].outer_width_v)
				o.vars.max_width = o.vars.els[o.vars.els.length-1].outer_width_v;
		});
		if(last_index>=0){
			o.vars.els[last_index].next_separator_width = sep_width;
			o.vars.els[last_index].next_separator_height = sep_height;
		}
		for(var i=0;i<o.vars.els.length;i++){
			o.vars.els[i].outer_height_v = o.vars.els[i].outer_height_v + o.vars.els[i].prev_separator_height + o.vars.els[i].next_separator_height;
			o.vars.els[i].outer_width_v = o.vars.els[i].outer_width_v + o.vars.els[i].prev_separator_width + o.vars.els[i].next_separator_width;
			if(o.vars.max_height<o.vars.els[i].outer_height_v)
				o.vars.max_height = o.vars.els[i].outer_height_v;
			if(o.vars.max_width<o.vars.els[i].outer_width_v)
				o.vars.max_width = o.vars.els[i].outer_width_v;			
		}
		o.vars.max_scroll_items_v = Math.floor(o.vars.outer_height / o.vars.max_height);
		o.vars.max_scroll_items_h = Math.floor(o.vars.outer_width / o.vars.max_width);
		switch(o.settings.scroll){
			case 'horizontal':
				if(o.settings.scroll_items>o.vars.max_scroll_items_h)
					o.settings.scroll_items = o.vars.max_scroll_items_h;
				o.vars.position_max = (o.vars.inner_width - o.vars.outer_width) > 0 ? (o.vars.inner_width - o.vars.outer_width) : 0;
			break;
			case 'vertical':
				if(o.settings.scroll_items>o.vars.max_scroll_items_v)
					o.settings.scroll_items = o.vars.max_scroll_items_v;
				o.vars.position_max = (o.vars.inner_height - o.vars.outer_height) > 0 ? (o.vars.inner_height - o.vars.outer_height) : 0;
			break;
		}
		//check arrows activity
		checkArrows();
	}
	
	//check for image load
	function checkImageLoad(){
		if(!o.vars.start_load||o.vars.complete)return false;
		if(o.vars.errors>0){
			return false;
		}
		else if(o.vars.loading>0){
			return false;
		}
		else if(o.vars.loaded>0&&o.vars.loading==0){
			acount();
			o.vars.complete = true;
			execActions();
		}
	}
	
	//execute actions
	function execActions(){
		for(var i=0;i<o.vars.actions.length;i++)
			switch(o.vars.actions[i].action){
				case 'scrollToPosition':
					scrollToPosition(o.vars.actions[i].value);
				break;
				case 'scrollToItemByIndex':
					scrollToItemByIndex(o.vars.actions[i].value);
				break;
				case 'scrollToItemById':
					scrollToItemById(o.vars.actions[i].value);
				break;
			}
	}
	
	//load image
	function loadImage(src,image_id){
		if(typeof o.vars.images == 'undefined')
			o.vars.images = {};
		var image = {};
		image.node = new Image();
		image.loaded = 0;
		o.vars.loading++;
		image.node.onload = function(){
			image.loaded = 2;
			o.vars.loading--;
			o.vars.loaded++;
			checkImageLoad();
		}
		image.node.onabort = function(){
			image.loaded = 1;
			o.vars.loading--;
			o.vars.errors++;
			checkImageLoad();
		}
		image.node.src = src;
		o.vars.images[image_id] = image;
		return image;
	}
};
