(function($)
{
	$.fn.CreateSlider = function(settings)
	{
		// Config Array
		var config = $.extend(
		{
			// Animation Type
			animationType:	'slide',
			
			// Whether to slide all viewable image at once
			// if more than 1 is shown
			slideAllViewItems: true,
			
			// Animation Time
			animationTime:	500,
			
			// Slider Control Type
			// 0 - Previous, Next
			// 1 - Dynamic Numbers
			// 2 - Dynamic Categories
			// 3 - Previous, Next, Dynamic Numbers
			// 4 - Previous, Next, Dynamic Categories
			controlType:			0,
			dynamicCategoriesTag:	'h1',
			hideFirstCategory:		false,
			
			// The length of each slide on auto scroll
			autoSlideDelay:		5000,
			// Whether the slider will scroll automatically
			isAutoSlide:		false,
			
			// Whether the the slider stops on the last item or slides back to the first
			disableOnLast: 	true,
			// Whether the slider loops indefinitely 
			// Otherwise if disableOnLast is set to false, the slider will slide back the opposite direction
			// to the first or last element
			loopSlider:		false,
			
			// Used if the items are diffrent widths
			// If set to true, it will ignore the slideAllViewItems variable
			differentWidths: false,
			
			// Button Config
			btnHeight:		'fixed',
			btnNextStr:		'slider-btnNext',
			btnPrevStr:		'slider-btnPrev',
			
			// Slider HTML Markup
			slideItem:			'slideItem',
			slideControls:		'slider-controls',
			slideItemHolder:	'slider-holder',
			slideItemBound:		'slider-bound'
			
		}, settings || {});
		
	//  =============
	//  Global Object
		var global = 
		{
			// The slider references
			slider: $(this),
			sliderHolder: null,
			sliderControls: null,
			sliderBound: null,
			sliderItemWidth: 0,
			
			// Buttons
			btnNext: null,
			btnPrev: null,
			
			// Slide Properties
			visibleItems: 1,
			
			// Slide Value
			moveValue: 0,
			// Slide End Position
			endPos: 0,
			
			// Reference to the timer object
			timer: null,
			
			// Slide Count
			currentSlideNum: 0,
			nextSlideNum: 0,
			prevSlideNum: 0,
			totalSlideCount: 0,
			defaultSlideCount: 0
		};
		
	//  =================
	//  Initiate Function
		var jQuerySlider = function() 
		{		
			// Set the HTML for the slider
			global.slider.html(setHTML(global.slider));
			
			// Assign the controls
			global.btnNext = $('.' + config.btnNextStr, global.slider);
			global.btnPrev = $('.' + config.btnPrevStr, global.slider);
			
			// Assign the slider holder
			global.sliderHolder = $('.' + config.slideItemHolder, global.slider);
			global.sliderBound = $('.' + config.slideItemBound, global.slider);
			
			// Assign the height/width of the slider
			var h = global.sliderBound.height();
			
			var full_width = global.slider.width() + 'px';
			var boundWidth = global.sliderBound.width() + 'px';
			
			global.slider.css({ height: h + 'px', width: '100%' });
			global.sliderHolder.css({ height: h + 'px' });
			global.sliderBound.css({ height: h + 'px', width: boundWidth });
			
			// Set the height of the control buttons is defined as full
			if (config.btnHeight == 'full')
			{
				// Ensure to keep track of the margin/padding and borders for the full height
				var btnHeight = global.slider.outerHeight(true);
				
				// Grab the padding information and border from the slider to ensure proper placement of the buttons
				var padTop = parseInt(global.slider.css('padding-top').replace('px', ''));
				var padBot = parseInt(global.slider.css('padding-bottom').replace('px', ''));
				var borTop = parseInt(global.slider.css('border-top-width').replace('px', ''));
				
				// Find the top position for the buttons based on the padding top properties
				var topPos = borTop + padTop + parseInt(global.btnNext.css('padding-top').replace('px', ''));
				
				// Assign the height and top position for each button
				global.btnNext.css({ height: btnHeight + 'px', top: -topPos + 'px' });
				global.btnPrev.css({ height: btnHeight + 'px', top: -topPos + 'px' });
				
				// Assign the height of the visual items
				// These items are controlled via CSS and may not necessarly be used
				// They have been added to allow flexibility on the look and feel of the slider
				$('.icon', global.btnNext).css({ height: btnHeight + 'px' });
				$('.icon', global.btnPrev).css({ height: btnHeight + 'px' });
				$('.visual-holder', global.btnNext).css({ height: btnHeight + 'px' });
				$('.visual-holder', global.btnPrev).css({ height: btnHeight + 'px' });
			}
			
			// Assing the total number of items
			global.totalSlideCount = global.defaultSlideCount = $('.' + config.slideItem, global.slider).length;
			
			global.sliderItemWidth = $('.' + config.slideItem, global.slider).outerWidth(true);
			global.visibleItems = Math.floor(global.sliderBound.width() / global.sliderItemWidth);
			
			// Setup slides
			setupSlideItems();
		
			// Setup controls
			global.sliderControls = controls();
			
			// Disable both button to begin
			global.sliderControls.disable();
			
			// If the slider gets disabled on each end, start with only the next button enabled
			var string = null;
			
			if (config.disableOnLast)
			{
				string = 'next';
				// Adds class of disable to the passed button
				global.sliderControls.onLast('prev');
			}
			
			// Only enable the buttons if the amount of items is greater than the amount of visible items
			if (global.sliderHolder.outerWidth(true) > global.sliderBound.width())
			{
				global.sliderControls.enable(string);
			}
			else if (config.controlType == 2)
			{
				global.sliderControls.enable();
			}
			else
			{
				// Add class of disable to prev/next buttons
				global.sliderControls.onLast();
			}
			
			if (config.isAutoSlide)
			{
				setTimer();
			}
		};
		
	//  ===============
	//  Build Functions
		function setupSlideItems()
		{
			// Setup the slide item based on the animation type
			switch (config.animationType)
			{
				// Setup for a slide animation
				case 'slide':
					
					// Determine the amount of pixels the slider needs to move on each slide
					global.moveValue = global.sliderItemWidth;
					
					// Position the slides one next to another
					var leftPos = 0;
					$('.' + config.slideItem, global.slider).each(function(num)
					{
						// Left position is calculated based on the current number
						// and the width of the slide item
						leftPos = num * global.moveValue;
						$(this).css({left: leftPos + 'px'}).removeClass('hide');
					});
					break;
				
				case 'customSlide':
				
					break;
			};
		};
		
	//  =================
	//  Control Functions
		
		var controls = function()
		{
			var methods = {};
		
			// Enabling all the controls
			methods.enable = function(str)
			{
				
				switch (config.controlType)
				{
					// Previous and Next Buttons
					case 0:
						if (str == null)
						{
							global.btnNext.bind('click', clickNext);
							global.btnPrev.bind('click', clickPrev);
							
							global.btnNext.removeClass('disable');
							global.btnPrev.removeClass('disable');
						}
						else if (str == 'next')
						{
							global.btnNext.bind('click', clickNext);
							
							global.btnNext.removeClass('disable');
						}
						else if (str == 'prev')
						{
							global.btnPrev.bind('click', clickPrev);
							
							global.btnPrev.removeClass('disable');
						}
						break;
					// Dynamic Numbers
					case 1:
						break;
					// Dynamic Categories
					case 2:
							$('a', '.ss-controls-bound').each(function()
							{
								currentItem = $(this).attr('rel');
								$j(this).bind('click', { num: currentItem }, clickNext);
							});
					
						break;
					// Previous, Next, Dynamic Numbers
					case 3:
						break;
					// Previous, Next, Dynamic Categories
					case 4:
						break;
				};
			};
			
			// Disabling all the controls
			methods.disable = function(str)
			{
				if (str == null)
				{
					global.btnNext.unbind('click');
					global.btnPrev.unbind('click');
				}
				else if (str == 'next')
				{
					global.btnNext.unbind('click');
				}
				else if (str == 'prev')
				{
					global.btnPrev.unbind('click');
				}
			};
			
			// Adding a disable class to the buttons
			methods.onLast = function(str)
			{
				if (str == null)
				{
					global.btnNext.addClass('disable');
					global.btnPrev.addClass('disable');
				}
				else if (str == 'next')
				{
					global.btnNext.addClass('disable');
				}
				else if (str == 'prev')
				{	
					global.btnPrev.addClass('disable');
				}
			};
			
			// Keep track of current slide number on increase
			methods.increase = function(num, maxNum, minNum, by)
			{
				var increaseBy = (by != null) ? by : 1;
				var finalNum = (num + increaseBy >= maxNum) ? minNum : num + increaseBy;
				
				return finalNum;
			};
			
			// Keep track of current slide number on decrease
			methods.decrease = function(num, minNum, maxNum, by)
			{	
				var decreaseBy = (by != null) ? by : 1;
				var finalNum = (num - decreaseBy < minNum) ? maxNum : num - decreaseBy;
				
				return finalNum;
			};
			
			return methods;
		};
	
		function clickNext(e)
		{
			// Disable controls until animation is complete
			global.sliderControls.disable();
			
			if (e.data.num != global.currentSlideNum)
			{
				global.nextSlideNum = parseInt(e.data.num);
				nextItem();
			}
			
			return false;
		};
		
		function clickPrev()
		{
			// Disable controls until animation is complete
			global.sliderControls.disable();
			
			prevItem();
			return false;	
		};
		
		function nextItem()
		{	
			// Setup the slide item based on the animation type
			switch (config.animationType)
			{
				// Setup for a slide animation
				case 'slide':
				
					if (config.differentWidths)
					{	
						// Determine the item that will be cloned.
						var cloneItem = $('.' + config.slideItem + ':eq(' + (global.totalSlideCount - global.defaultSlideCount) + ')', global.slider);
						// Determine the item that needs to be moved
						var slideItem = $('.' + config.slideItem + ':eq(' + (global.currentSlideNum) + ')', global.slider);
						
						// Increase the current count
						global.currentSlideNum++;
						
						// Clone the item to make the loop possible
						$(cloneItem, global.sliderHolder).clone().appendTo(global.sliderHolder);
						
						// Increase the total slide count
						global.totalSlideCount++;
						
						// Set the move value based on the slide item's width
						global.moveValue = slideItem.outerWidth(true);
						global.endPos -= global.moveValue;
					}
					else
					{
						// Temporary variable to determine the amount of items to much each time
						var by = (config.slideAllViewItems) ? global.visibleItems : 1;
						
						// Set the current slide number
						// increase(CURRENT NUMBER, MAXIMUM NUMBER, MINIMUM NUMBER, INCREMENT VALUE
						global.currentSlideNum = global.sliderControls.increase(global.currentSlideNum, global.totalSlideCount, 0, by);
					
						// Reset the move value to 0
						global.moveValue = 0;
						
						if (global.currentSlideNum == 0)
						{
							// If the slider is not looping, reset the end position at 0
							// This will slide the slider the opposite way back to the first item
							if (!config.loopSlider)
							{
								global.endPos = 0;
							}
						}
						else
						{
							// Calculate the move value based on moving 1 item or all visible items
							global.moveValue = (config.slideAllViewItems) ? global.sliderItemWidth * global.visibleItems : global.sliderItemWidth;
							// Substract the move value from end position - lower value = slide to the left
							global.endPos -= global.moveValue;
						}
						
						// Check which buttons to enable when the animation ends
						var btnString = null;
						if (config.disableOnLast)
						{
							// Check the value of slide number when increased
							// If the value is 0, only enable the previous button
							if (global.sliderControls.increase(global.currentSlideNum, global.totalSlideCount, 0, by) == 0)
							{
								btnString = 'prev';
								global.sliderControls.onLast('next');
							}
							// Otherwise we are NOT on the last items so enable both buttons
							else
							{
								btnString = null;
							}
						}
					}
					
					// Animate the slider holder
					global.sliderHolder.animate({ left: global.endPos + 'px'}, config.animationTime, function() { global.sliderControls.enable(btnString) });
					
					break;
					
				case 'customSlide':
					
					$('.' + config.slideItem + ':eq(' + global.currentSlideNum + ')', global.slider).css({top: 0}).animate({ opacity: 0, left: '-1000px' }, config.animationTime, function() { $(this).css({display: 'none'}); });
					$('.' + config.slideItem + ':eq(' + global.nextSlideNum + ')', global.slider).css({display: 'block', left: '1000px'}).animate({ opacity: 1, left: 0 }, config.animationTime / 1.2);
					
					$('p', '.' + config.slideItem + ':eq(' + global.nextSlideNum + ')').css({position: 'relative', left: '750px'}).animate({left: 0}, config.animationTime);
					$('h1', '.' + config.slideItem + ':eq(' + global.nextSlideNum + ')').css({position: 'relative', left: '450px'}).animate({left: 0}, config.animationTime);
					
					global.prevSlideNum = global.currentSlideNum;
					global.currentSlideNum = global.nextSlideNum;
					
					setActiveControls();
					
					break;
			};
			
			if (config.isAutoSlide)
			{
				clearTimer();
				setTimer();
			}
		};
		
		function prevItem()
		{
			// Setup the slide item based on the animation type
			switch (config.animationType)
			{
				// Setup for a slide animation
				case 'slide':
					
					if (config.differentWidths)
					{
						// Store the left position of the slider
						var tPos = global.sliderHolder.position().left;
						
						// Find the element to clone
						var count = global.defaultSlideCount - 1;
						var cloneItem = $('.' + config.slideItem + ':eq(' + (count) + ')', global.slider);
						var endLeft = tPos - cloneItem.outerWidth(true);
						
						// Store the slider HTML
						// Use it to insert the clone element at the front of the list
						var temp_html = global.sliderHolder.html();
						global.sliderHolder.html('<div class="slideItem">' + cloneItem.html() + '</div>' + temp_html).css({ left: endLeft + 'px' });
						
						// Increase the total slide count
						global.totalSlideCount++;
						
						// Determine the item to slide
						var slideCount = global.currentSlideNum;
						var slideItem = $('.' + config.slideItem + ':eq(' + slideCount + ')', global.slider);
						
						// Set the move value based on the left position of the slider and the slide item's width
						global.moveValue = endLeft + slideItem.outerWidth(true);
						global.endPos = global.moveValue;						
					}
					else
					{					
						// Temporary variable to determine the amount of items to much each time
						var by = (config.slideAllViewItems) ? global.visibleItems : 1;
						
						// Calculate the max value the current slide number can be
						var maxValue = ((Math.ceil(global.totalSlideCount / global.visibleItems) - 1) * global.visibleItems);
						
						// Set the current slide number
						// decrease(CURRENT NUMBER, MINIMUM NUMBER, MAXIMUM NUMBER, INCREMENT VALUE
						global.currentSlideNum = global.sliderControls.decrease(global.currentSlideNum, 0, maxValue, by);
						
						// Reset the move value to 0
						global.moveValue = 0;
						
						if (global.currentSlideNum == maxValue)
						{
							// If the slider is not looping, reset the end position
							// This will slide the slider the opposite way back to the last items
							if (!config.loopSlider)
							{
								global.endPos = -(global.sliderItemWidth * maxValue);
							}
						}
						else
						{
							// Calculate the move value based on moving 1 item or all visible items
							global.moveValue = (config.slideAllViewItems) ? global.sliderItemWidth * global.visibleItems : global.sliderItemWidth;
							// Add the move value from end position - higher value = slide to the right
							global.endPos += global.moveValue;
						}
						
						// Check which buttons to enable when the animation ends
						var btnString = null;
						if (config.disableOnLast)
						{
							// Check the value of slide number when decreased
							// If the value is the max allowed, only enable the next button
							if (global.sliderControls.decrease(global.currentSlideNum, 0, maxValue, by) == maxValue)
							{
								btnString = 'next';
								global.sliderControls.onLast('prev');
							}
							// Otherwise we are NOT on the first items so enable both buttons
							else
							{
								btnString = null;
							}
						}
					}
					
					// Animate the slider holder
					global.sliderHolder.animate({ left: global.endPos + 'px'}, config.animationTime, function() { global.sliderControls.enable(btnString) });
					
					break;
			};
		};
		
		
		
		
		function setActiveControls()
		{
			if (global.nextSlideNum != 0)
			{
				var cItem = $('li:eq(' + global.nextSlideNum + ')', '.ss-controls');
				
				var pos = cItem.position();
				var leftPos = Math.round(pos.left + (cItem.width() / 2));
				
				$('#selected-arrow').css({opacity: 1, display: 'block', left: leftPos + 'px', bottom: cItem.height() + 'px'});
				
				if ($.browser.msie && $.browser.version <= 6 )
				{
					$('#selected-arrow').css({bottom: (cItem.height() - 5) + 'px'});
				}
				
				$('li:eq(' + global.prevSlideNum + ')', '.ss-controls').removeClass('active');
				cItem.addClass('active');
			}
			else
			{
				$('li:eq(0)', '.ss-controls').removeClass('active');
				$('#selected-arrow').css({opacity: 0});
				$('li:eq(' + global.prevSlideNum + ')', '.ss-controls').removeClass('active');
			}
		}
		
		function setTimer()
			{
				timer = setTimeout(timerNext, config.autoSlideDelay);
			}
		function timerNext()
			{
				global.prevSlideNum = global.currentSlideNum;
				global.nextSlideNum = ((global.currentSlideNum + 1) > (global.defaultSlideCount - 1)) ? 0 : (global.currentSlideNum + 1);	
				nextItem();
			}
		function clearTimer()
			{
				clearTimeout(timer);
			}
		
		
	
	//  =========================================================
	//  Function to setup the markup needed to created the slider 
		function setHTML(this_obj)
		{
			//  Empty string to hold new markup
			var html_str = '';
		
			switch (config.controlType)
			{
				// Previous and Next Buttons
				case 0:
				
					//  HTML for the controls
					html_str += '<div class="' + config.slideControls + '">';
				
					html_str += '<div class="button btn-' + config.btnPrevStr + '"><a class="' + config.btnPrevStr + '"><span class="visual-holder">Prev<span class="icon"></span></span></a></div>';
					html_str += '<div class="button btn-' + config.btnNextStr + '"><a class="' + config.btnNextStr + '"><span class="visual-holder">Next<span class="icon"></span></span></a></div>';
					
					html_str += '</div>';
					break;
				// Dynamic Numbers
				case 1:
					break;
				// Dynamic Categories
				case 2:
					var cat_str = 	'<div class="ss-controls">';
					cat_str += 		'<div id="selected-arrow"></div>';
					cat_str += 		'<div class="ss-controls-bound"><div class="ss-controls-holder"><ul>';
					
					// Used to determine whether to hide the first item
					var classString = '';
					
					$(config.dynamicCategoriesTag, global.slider).each(function(num)
					{
						if (config.hideFirstCategory)
						{
							classString = (num == 0) ? ' class="hide active"' : '';
						}
						cat_str += '<li' + classString + '><a href="/" rel="' + num + '">' + $(this).text() + '</a></li>';
					});
					
					cat_str += '</ul></div></div></div>';
					break;
				// Previous, Next, Dynamic Numbers
				case 3:
					break;
				// Previous, Next, Dynamic Categories
				case 4:
					break;
			};
			
			//  HTML for the slider holder
			html_str += '<div class="' + config.slideItemBound + '">';
			html_str += '<div class="' + config.slideItemHolder + ' clearfix">';
			// Add existing markup inside addition
			html_str += this_obj.html();
			html_str += '</div></div>';
			
			if (cat_str)
			{
				html_str += cat_str;
			}
			
			return html_str;
		};
		
		// Initiate the slider
		jQuerySlider();
	};
})(jQuery);