(function($){
	/* Plugin Name:		
	 * Biber Product Carousel
	 * Programmed by:	Can Berkol
	 * Programmed for:	biber Ltd. of Istanbul, Turkiye.
	 * Licensed under:	GPL
	 * 
	 * version:			1.0
	 * 
	 * 
	 * http://www.biberltd.com
	 */
	$.fn.biberproductcarousel = function(options) {
	/**
	 * Plugin Options:
	 * mode				Sets the refresh mode of carousel items.
	 * 					ajax => If mode is set to ajax the set of items are loaded using an ajax call.
	 * 					local => If modei is set to local the set of items are loaded into HTML when the 
	 * 							 page is loaded for the first time.
	 * number_of_items	Sets the number of items visible in the carousel.
	 * 					Accepts only a positive and and odd integer value.
	 * 					i.e. 3 means that there are 3 items to be shown including the current item.
	 * scroll_direction Sets the scroll direction.
	 * 					forward => next item will be shown next.
	 * 					bakcward => previous item will be shown next.
	 * show_btn_scroll	Makes the navigational scroll button visible or hidden.
	 * 					true => Shows the navigational buttons (next, prev buttons)
	 * 					false => Hides the navigational buttons
	 * show_btn_all 	Makes the view all button visible or hidden.
	 * 					true => Shows the view all button
	 * 					false => disables the view all button.
	 * show_info		Shows or hides product information.
	 * 					true => Shows product information.
	 * 					false => Hides product information.
	 * show_item_prevs	Shows or hides previous and next item thumbnails and thumbnail based navigation
	 * 					true => Shows the item previews.
	 * 					false => Hides the item previews.
	 * slide_effect 	Defines the animation of carousel.
	 *					slide => Items slide in slide direction.
	 * 					fade => Items fade and reappear.
	 * preview_effect	Defines the mouse over effect for preview items.
	 * 					fadein => Items fade in..
	 *					slidehorizontal => Items slide horiontally
	 * 					slidevertical => Items slide vertically
	 * url_allitems 	Defines the url where the user wll be redirected when he/she clicks on view all 
	 *					button
	 *					Accepts a string.
	 * url_ajaxhandler	Defines the url of server side ajax handler file..
	 * 					Accepts a string.
	 * 
	 */
	var defaults = {
		ajaxdata: '',
		items: [],
		mode: 'ajax',
		nextbutton_src: '',
		number_of_items: 3,
		prevbutton_src: '',
		scroll_direction: 'forward',
	  	show_btn_scroll: true,
	  	show_btn_all: true,
	  	show_info: true,
	  	show_item_prevs: true,
	  	slide_effect: 'slide',
		startwith: 1,
		startwith_id: -1,
	  	preview_effect: 'slidedown',
	  	url_allitems: '#',
	  	url_ajaxhandler: '',
		viewalltxt: 'View All'
	  };
	  /*
	   * Merge user definedoptions with defaults.
	   */
	  var options = $.extend(defaults, options);
	  
	return this.each(function() {
		/*
		 * Store carousel div (jquery object) into carouselobj local variable.
		 */
		var containerobj = $(this);
		if(options.mode == 'ajax'){
			options.items = eval('('+getItemsFromServer(options).responseText+')');
		}
		if(options.startwith_id == -1){
			var currentitemno = options.startwith;
		}
		else{
			var currentitemno = options.startwith;
			for(var i=0; i<options.items.length;i++){
				if(options.items[i].id == options.startwith_id){
					currentitemno = i;
				}
			}
		}
		if(options.items.length > 0){
			create(containerobj, options, currentitemno);
		}
	});
  }
  getItemsFromServer = function(options){
  	var ajxobj = $.ajax({
	   type: 'GET',
	   url: options.url_ajaxhandler,
	   data: options.ajaxdata,
	   async: false
	 })
	 return ajxobj;
  }
  /*
   * create
   * 
   * This function creates the carousel for the first time.
   * 
   */
  create = function(containerobj, options, currentitemno){
  	var items = options.items;
	var totalitems = items.length;
	/*
	 * Define which item is current item, which item is previous item and which items is next item
	 */
	initialize.current = currentitemno;
	initialize.previous = initialize.current - 1;
	initialize.next = initialize.current + 1;
	/*
	 * If next item number is larger than the last item, set the first item as next item.
	 */
	if(initialize.next == totalitems){
		initialize.next = 0;
	}
	/*
	 * If previous item number is less than the first item, set the last item as previous item.
	 */
	if(initialize.previous < 0){
		initialize.previous = totalitems - 1;
	}
	var carouseldiv = '<ul id="bpc_innercarousel" class="bb_carousel_inner"></ul>';
	containerobj.prepend(carouseldiv);
	var carouselobj = $('#bpc_innercarousel');
	var currobj = this.injectCurrentItem(carouselobj, 'front');
	loadCurrImage(items[initialize.current], currobj);
	carouselobj.css('width', (totalitems+2) * currobj.width());
	/*
	 * Show next and previous items, if and only if show_item_prevs is set to true
	 */
  	if(options.show_item_prevs == true){
		var prevobj = this.injectPrevItem(carouselobj, 'front');
		var nextobj = this.injectNextItem(carouselobj, 'end');
		loadNextImage(items[initialize.next], nextobj);
		loadPrevImage(items[initialize.previous], prevobj);
	}
	if(options.show_btn_scroll == true || options.show_btn_all == true || options.show_info == true){
		injectInfo(containerobj, options, items);
	}
	initialize.current = currentitemno;
	initialize(carouselobj, options);
	/*
	 * Clear styles
	 */
	//carouselobj.append('<div class="clear"></div>');
  }
  /*
   * setItemCounter
   * 
   * This function keeps track of items during navigation through carousel.
   */
  setItemCounter = function(totalitems){  
  	/*
	 * Define which item is current item, which item is previous item and which items is next item
	 */
	if(initialize.current < 0){
		initialize.current = totalitems - 1;
	}
	if(initialize.current >= totalitems){
		initialize.current = 0;
	}
	initialize.previous = initialize.current - 1;
	initialize.next = initialize.current + 1;
	/*
	 * If next item number is larger than the last item, set the first item as next item.
	 */
	if(initialize.next >= totalitems){
		initialize.next = 0;
	}
	/*
	 * If previous item number is less than the first item, set the last item as previous item.
	 */
	if(initialize.previous < 0){
		initialize.previous = totalitems - 1;
	}
  }
  /*
   * initialize
   * 
   * This function initializes all events and other interactions of each carousel item.
   */
  initialize = function(carouselobj, options){
  	var items = options.items;
	var totalitems = items.length;
	setItemCounter(totalitems);
  	var currobj = $('#bpc_curritem');
	var prevobj = $('#bpc_previtem');
	var nextobj = $('#bpc_nextitem');
	var currobj = $('#bpc_curritem');
	initialize.animating = 0;
	/*
	 * Show next and previous items, if and only if show_item_prevs is set to true
	 */
	var currimg = $('#bpc_curritem_img');
	var nextimg = $('#bpc_nextitem_img');
	var previmg = $('#bpc_previtem_img');
	var objects = {
					'carouselobj': carouselobj,
					'currobj': currobj,
					'nextobj': nextobj,
					'prevobj': prevobj,
					'currimg': currimg,
					'previmg': previmg,
					'nextimg': nextimg	
				 };
  	if(options.show_item_prevs == true){
		nextobj.click(function(event){
			initialize.animating += 1;
			if(initialize.animating > 1){
				return false;
			}
			forward(objects, options, items);
			if(options.show_btn_scroll == true){
				$('#next_button_img').attr('title', items[initialize.next].title);
				$('#prev_button_img').attr('title', items[initialize.previous].title);
			}
		});
		prevobj.click(function(event){
			initialize.animating += 1;
			if(initialize.animating > 1){
				return false;
			}
			backward(objects, options, items);
			if(options.show_btn_scroll == true){
				$('#next_button_img').attr('title', items[initialize.next].title);
				$('#prev_button_img').attr('title', items[initialize.previous].title);
			}
		});
		addPreviewEffect(options.preview_effect);
	}
	if(options.show_btn_scroll == true){
		$('#next_button').unbind('click').click(function(event){
			initialize.animating += 1;
			if(initialize.animating > 1){
				return false;
			}
			forward(objects, options, items);
			$('#next_button_img').attr('title', items[initialize.next].title);
			$('#prev_button_img').attr('title', items[initialize.previous].title);
			event.preventDefault();
		});		
		$('#prev_button').unbind('click').click(function(event){
			initialize.animating += 1;
			if(initialize.animating > 1){
				return false;
			}
			backward(objects, options, items);
			$('#next_button_img').attr('title', items[initialize.next].title);
			$('#prev_button_img').attr('title', items[initialize.previous].title);
			event.preventDefault();
		});		
	}
	initialize.animating = 0
  }
  /*
   * forward
   * 
   * Attaches forward movement.
   */
  forward = function(objects, options, items){
  	addSlideEffect(options.slide_effect, 'forward', objects, items, options);
	  initialize.current += 1;
	  setItemCounter(items.length);
  }
  /*
   * backward
   * 
   * Attaches backward movement.
   */
  backward = function(objects, options, items){
  	  addSlideEffect(options.slide_effect, 'backward', objects, items, options);
	  initialize.current -= 1;
	  setItemCounter(items.length);
  }
  /*
   * prepareCurrentItem
   * 
   * This function prepares the HTML of current item excluding the image.
   */
  prepareCurrentItem = function(){
  	var curritem_div = '<li id="bpc_curritem" class="curr_item"></li>';
  	
	return curritem_div;
  }
  /*
   * preparePrevItem
   * 
   * This function prepares the HTML of previous item and returns the complete HTML.
   */
  preparePrevItem = function(){
  	var previtem_div = '<li id="bpc_previtem" class="prev_item"></li>';
	return previtem_div;
  }
  /*
   * prepareNextItem
   * 
   * This function prepares the HTML of next item and returns the complete HTML.
   */
  prepareNextItem = function(){
  	var nextitem_div = '<li id="bpc_nextitem" class="next_item"></li>';
	return nextitem_div;
  }
  prepareInfo = function(){
  	var info_div = '<div id="bb_carousel_info" class="bb_info"></div>';
	
	return info_div;
  }
  prepareNavigation = function(){
  	var navigation = '<div id="bb_navigation" class="bb_navigation"><div id="clear_floats_info" style="clear: both"></div></div>';
	
	return navigation;
  }
  prepareScrollNavigation = function(options, items){
  	var prev_button = '<a id="prev_button" class="prev button" href="#"><span><img id="prev_button_img" src="'+options.prevbutton_src+'" title="'+items[initialize.previous].title+'" alt="'+items[initialize.previous].title+'" /></span></a>';
	var next_button = '<a id="next_button" class="next button" href="#"><span><img id="next_button_img" src="'+options.nextbutton_src+'" title="'+items[initialize.next].title+'" alt="'+items[initialize.previous].title+'"/></span></a>'
	var buttons = prev_button + next_button;
	
	return buttons;
  }
  prepareViewAllNavigation = function(options){
  	var vall_button = '<a id="viewall_button" class="viewall button" href="'+options.url_allitems+'"><span>'+options.viewalltxt+'</span></a>'
	
	return vall_button;
  }
  prepareProductDetails = function(){
  	var pdetails_div = '<div class="bb_product_details"></div>';
	
	return pdetails_div;

  }
  injectInfo = function(containerobj, options, items){
	var info_div = prepareInfo();
	containerobj.append(info_div);
	var infobj = $('#bb_carousel_info');
	if (options.show_btn_scroll == true || options.show_btn_all == true) {
		var navigation = prepareNavigation();
		infobj.append(navigation);
		var navobj = $('#bb_navigation');
	}
	if(options.show_btn_scroll == true){
		var navbuttons = prepareScrollNavigation(options, items);
		navobj.prepend(navbuttons);
	}
	if(options.show_btn_all == true){
		var allbutton = prepareViewAllNavigation(options);
		navobj.prepend(allbutton);
	}
	if(options.show_info == true){
		var infocontent = prepareProductDetails();
		infobj.append(infocontent);
	}
	return infobj;
  }
  /*
   * Injects the current item into specified spot within DOM.
   */
  injectCurrentItem = function(carouselobj, where){
  	curr_item = prepareCurrentItem();
	switch(where){
		case 'front':
			carouselobj.prepend(curr_item);
			break;
		case 'end':
		default:
			carouselobj.append(curr_item);
			break;
	}
	
	var currobj = $('#bpc_curritem');
	
	return currobj;
  }
  /*
   * Injects current item after previous item in DOM.
   */
  injectCurrItemAfterPrev = function(prevobj){
  	curr_item = prepareCurrentItem();
	prevobj.after(curr_item);
	var currobj = $('#bpc_curritem');
	
	return currobj;
  }
  /*
   * Injects current item before next item in DOM.
   */
  injectCurrItemBeforeNext = function(nextobj){
  	curr_item = prepareCurrentItem();
	nextobj.before(curr_item);
	var currobj = $('#bpc_curritem');
	
	return currobj;
  }
  /*
   * Injects the previous item into specified spot within DOM.
   */
  injectPrevItem = function(carouselobj, where){
  	prev_div = preparePrevItem();
	switch(where){
		case 'front':
			carouselobj.prepend(prev_div);
			break;
		case 'end':
		default:
			carouselobj.append(prev_div);
			break;
	}
	
	var prevobj = $('#bpc_previtem');
	
	return prevobj;
  }
  /*
   * Injects the next item into specified spot within DOM.
   */
  injectNextItem = function(carouselobj, where){
  	next_div = prepareNextItem();
	switch(where){
		case 'front':
			carouselobj.prepend(next_div);
			break;
		case 'end':
		default:
			carouselobj.append(next_div);
			break;
	}
	var nextobj = $('#bpc_nextitem');
	
	return nextobj;
  }
  /*
   * addSlideEffect
   * 
   * This function is used to attach the requested slide effect.
   */
  addSlideEffect = function(style, direction, objects, items, options){
  	switch(style){	
		case 'slide':
			if(!($.browser.msie)){
 				addSlideEffect.slide(objects, items, options, direction);
	  		}
	  		else{
	  			addSlideEffect.slideIE(objects, items, options, direction);
	  		}
			
		default:
			break;
	}
  }
   /*
   * addSlideEffect.slide
   * 
   * This function is used to attach the slide effect.
   */
  addSlideEffect.slide = function(objects, items, options, direction){
  	var stdwidth = objects.currobj.width();
	objects.currobj.attr('id', 'bb_old_curr');
	objects.prevobj.attr('id', 'bb_old_prev');
	objects.nextobj.attr('id', 'bb_old_next');
	/*
	 * 1. Hide current image.
	 */
	objects.currimg.animate({
		'opacity': 0
	},
	{
		duration: 'slow',
		complete: function(){	
			/*
			 * 2. Change large image with small image.
			 */
			if(direction == 'forward'){
				objects.currimg.hide();
				objects.currimg.attr('src', items[initialize.previous].smallpath);
				var slide = '-=';
			}
			else if (direction == 'backward'){
				objects.currimg.hide();
				objects.currimg.attr('src', items[initialize.next].smallpath);
				var slide = '+=';
			}
			/*
			 * 3. Remove the class for currentimg and replace it with the class for small image.
			 */
			objects.currimg.parent().removeClass('currentimgframe').addClass('currentimgframe_small');
			/*
			 * 4. Show small image.
			 */
			objects.currimg.show();
			objects.currimg.animate({
				'opacity': 1
			},
			{
				duration: 'slow',
				complete: function(){
					if(direction == 'forward'){
						/*
						 * 5. Get the next object in line.
						 */
						var newnextobject = injectNextItem(objects.carouselobj, 'back');
						loadNextImage(items[initialize.next], newnextobject);
						objects.carouselobj.animate({
							'left': slide+stdwidth+'px'
						},
						{
							duration: 'slow',
							complete: function(){
								objects.prevobj.remove();
								objects.currobj.remove();
								var newprevobject = injectPrevItem(objects.carouselobj, 'front');
								loadPrevImage(items[initialize.previous], newprevobject);
								objects.carouselobj.css('left', '0');
								objects.nextimg.animate({
									'opacity': 0
								},
								{
									duration: 'slow',
									complete: function(){
										objects.nextimg.parent().removeClass('imgframe').addClass('currentimgframe');
										objects.nextimg.attr('src', items[initialize.current].largepath);
										objects.nextimg.animate({
											'opacity': 1
										},
										{
											duration: 'slow',
											complete: function(){
												objects.nextobj.unbind();
												objects.nextobj.remove();
												var newcurrobject = injectCurrItemAfterPrev(newprevobject);
												loadCurrImage(items[initialize.current], newcurrobject);
												var newcarouselobj = $('#bpc_innercarousel');
		  										initialize(newcarouselobj, options);
											}
										});
									}
								});
							}
						});
					}
					else if(direction == 'backward'){
						objects.carouselobj.css('left', '-'+stdwidth+'px');
						var newprevobject = injectPrevItem(objects.carouselobj, 'front');
						loadNextImage(items[initialize.previous], newprevobject);
						objects.carouselobj.animate({
							'left': slide+stdwidth+'px'
						},
						{
							duration: 'slow',
							complete: function(){
								objects.nextobj.remove();
								objects.currobj.remove();
								var newnextobject = injectNextItem(objects.carouselobj, 'back');
								loadNextImage(items[initialize.next], newnextobject);
								objects.nextimg.animate({
									'opacity': 0
								},
								{
									duration: 'slow',
									complete: function(){
										objects.previmg.attr('src', items[initialize.current].largepath);
										objects.previmg.parent().removeClass('imgframe').addClass('currentimgframe');
										objects.nextimg.animate({
											'opacity': 1
										},
										{
											duration: 'slow',
											complete: function(){
												objects.prevobj.unbind();
												objects.prevobj.remove();
												var newcurrobject = injectCurrItemBeforeNext(newnextobject);
												loadCurrImage(items[initialize.current], newcurrobject);
												var newcarouselobj = $('#bpc_innercarousel');
		  										initialize(newcarouselobj, options);
											}
										});
									}
								});
							}
						});			
					}
				}
			});
		}
	});
  }
     /*
   * addSlideEffect.slide
   * 
   * This function is used to attach the slide effect.
   */
  addSlideEffect.slideIE = function(objects, items, options, direction){
  	var stdwidth = objects.currobj.width();
	objects.currobj.attr('id', 'bb_old_curr');
	objects.prevobj.attr('id', 'bb_old_prev');
	objects.nextobj.attr('id', 'bb_old_next');
	objects.currimg.animate({
		'fontsize': 0	
	},
	{
		duration: 'slow',
		complete: function(){	
			if(direction == 'forward'){
				objects.currimg.hide();
				objects.currimg.attr('src', items[initialize.previous].smallpath);
				var slide = '-=';
			}
			else if (direction == 'backward'){
				objects.currimg.hide();
				objects.currimg.attr('src', items[initialize.next].smallpath);
				var slide = '+=';
			}
			objects.currimg.parent().removeClass('currentimgframe').addClass('currentimgframe_small');
			objects.currimg.show();
			objects.currimg.animate({
						'width':	150,
						'height':	185,
						'fontsize': 0
			},
			{
				duration: 'slow',
				complete: function(){
					if(direction == 'forward'){
						var newnextobject = injectNextItem(objects.carouselobj, 'back');
						loadNextImage(items[initialize.next], newnextobject);
						objects.carouselobj.animate({
							'left': slide+stdwidth+'px'
						},
						{
							duration: 'slow',
							complete: function(){
								objects.prevobj.remove();
								objects.currobj.remove();
								var newprevobject = injectPrevItem(objects.carouselobj, 'front');
								loadPrevImage(items[initialize.previous], newprevobject);
								objects.carouselobj.css('left', '0');
								objects.nextimg.animate({
									'fontsize': 0
								},
								{
									duration: 'slow',
									complete: function(){
										objects.nextimg.attr('src', items[initialize.current].largepath);
										objects.nextimg.parent().removeClass('imgframe').addClass('currentimgframe');
										objects.nextimg.animate({
											'fontsize': 0
										},
										{
											duration: 'slow',
											complete: function(){
												objects.nextobj.unbind();
												objects.nextobj.remove();
												var newcurrobject = injectCurrItemAfterPrev(newprevobject);
												loadCurrImage(items[initialize.current], newcurrobject);
												var newcarouselobj = $('#bpc_innercarousel');
		  										initialize(newcarouselobj, options);
											}
										});
									}
								});
							}
						});
					}
					else if(direction == 'backward'){
						objects.carouselobj.css('left', '-'+stdwidth+'px');
						var newprevobject = injectPrevItem(objects.carouselobj, 'front');
						loadNextImage(items[initialize.previous], newprevobject);
						objects.carouselobj.animate({
							'left': slide+stdwidth+'px'
						},
						{
							duration: 'slow',
							complete: function(){
								objects.nextobj.remove();
								objects.currobj.remove();
								var newnextobject = injectNextItem(objects.carouselobj, 'back');
								loadNextImage(items[initialize.next], newnextobject);
								objects.nextimg.animate({
									'fontsize': 0
								},
								{
									duration: 'slow',
									complete: function(){
										objects.previmg.attr('src', items[initialize.current].largepath);
										objects.previmg.parent().removeClass('imgframe').addClass('currentimgframe');
										objects.nextimg.animate({
											'fontsize': 0
										},
										{
											duration: 'slow',
											complete: function(){
												objects.prevobj.unbind();
												objects.prevobj.remove();
												var newcurrobject = injectCurrItemBeforeNext(newnextobject);
												loadCurrImage(items[initialize.current], newcurrobject);
												var newcarouselobj = $('#bpc_innercarousel');
		  										initialize(newcarouselobj, options);
											}
										});
									}
								});
							}
						});			
					}
				}
			});
		}
	});
  }
  /*
   * addPreviewEffect
   * 
   * This function is used to attach the requested effect to preview images.
   */
  addPreviewEffect = function(style){
  	switch(style){
		case 'slidedown':
			$('#bpc_previtem').addClass('slide');
			$('#bpc_nextitem').addClass('slide');
			$(document).ready(function(){  
				 addPreviewEffect.slideDown();
			});
			break;
		case 'fade':
		default:
			$('#bpc_previtem').addClass('fade');
			$('#bpc_nextitem').addClass('fade');
			$(document).ready(function(){  
				addPreviewEffect.fade();
			});
			break;
	}
  }
  /*
   * addPreviewEffect.fade
   * 
   * This function is used to attach fade animation to preview images.
   */
  addPreviewEffect.fade = function(){
  	if(!($.browser.msie)){
  		$(".fade").fadeTo("fast", 0.3);
		$(".fade").hover(function(){  
			$(this).fadeTo("slow", 1.0);  
		},function(){  
			$(this).fadeTo("slow", 0.3);  
		});  
  	}
  }
  /*
   * addPreviewEffect.slideDown
   * 
   * This function is used to attach slide down animation to preview images.
   */
  addPreviewEffect.slideDown = function(){
  	var times = 0;
	$('.slide').hover(function(){
		if(times == 0){
			$(this).slideToggle("slow"); 
		}
		times++;
	},function(){  
		if(times == 1){
			$(this).slideToggle("slow"); 
		}
		times++;
		if(times >= 3){
			times = 0;
		}
	}
	);  
  }
  /*
   * loadCurrImage
   * 
   * This function is used to load current item's image.
   */
  loadCurrImage = function(currentitem, currentobject){
  	var img = '<div id="bpc_curritem_imgdiv" class="currentimgframe"><img id="bpc_curritem_img" src="'+currentitem.largepath+'" title="'
				+currentitem.title+'" alt="'+currentitem.title+'" /></div>';
	currentobject.append(img);
	var imgobj = ('#bpc_curritem_imgdiv');
	return imgobj;
  }
  /*
   * loadPrevImage
   * 
   * This function is used to load previous item's image.
   */
  loadPrevImage = function(previousitem, prevobject){
  	var img = '<div id="bpc_previtem_imgdiv" class="imgframe"><img id="bpc_previtem_img" src="'+previousitem.smallpath+'" title="'
				+previousitem.title+'" alt="'+previousitem.title+'" /></div>';
	prevobject.append(img);
	var imgobj = ('#bpc_previtem_imgdiv');
	return imgobj;
  }
  /*
   * loadNextImage
   * 
   * This function is used to load next item's image.
   */
  loadNextImage = function(nextitem, nextobject){
  	var img = '<div id="bpc_nextitem_imgdiv" class="imgframe"><img id="bpc_nextitem_img" src="'+nextitem.smallpath+'" title="'
				+nextitem.title+'" alt="'+nextitem.title+'" /></div>';
	nextobject.append(img);
	var imgobj = ('#bpc_nextitem_imgdiv');
	return imgobj;
  }
})(jQuery);