/**
 * Cognito Slider jQuery plugin 
 * 
 * version: 1.0b
 * author: Petr Janu (janu@cognito.cz)
 * 
 */

/* Usage:

$(document).ready(function()
{

	$('#slider .products').cSlider({
		inner: '.list',
		controlsAfter: '#slider .products',
		paddingCorrection: 2,			
		controls: {
			wrapper: '', // items will be wrapped by
			prev: '<a class="buttonPrevious"><span class="forBlind">{sliderprev}</span></a>',
			next: '<a class="buttonNext"><span class="forBlind">{slidernext}</span></a>'
		}
	});
	
	$('#slider2 .products').cSlider({
		inner: '.list',
		controlsAfter: '#slider2 .products',
		paddingCorrection: 2,			
		controls: {
			wrapper: '', // items will be wrapped by
			prev: '<a class="buttonPrevious"><span class="forBlind">{sliderprev}</span></a>',
			next: '<a class="buttonNext"><span class="forBlind">{slidernext}</span></a>'
		},
		autoSlideTimer: 1000
	});
	
	$('#refsSlider').cSlider({
		inner: '.inner',
		pagerAfter: '#refsSlider',
		pager: {
			wrapper: '<p class="switcher cleaned"></p>',
			prev: '<a class="buttonPrevious" href="#"><span class="forBlind">{pagerprev}</span></a>',
			next: '<a class="buttonNext" href="#"><span class="forBlind">{pagernext}</span></a>',
			item: ' <span class="buttonOff"><span class="forBlind">-</span></span>',
			selectedClass: 'buttonOn'
		}
	});
	
	$('#eventsSlider').cSlider({
		inner: '.list',
		controlsAfter: '#eventsSlider',
		controls: {
			wrapper: '<div class="switcher cleaned"></div>', // items will be wrapped by
			prev: '<a class="buttonPrevious" href="#"><span class="forBlind">&lt;</span></a>',
			next: '<a class="buttonNext" href="#"><span class="forBlind">&lt;</span></a>'
		}
	});
		
});

*/
(function($)
{
	$.fn.cSlider = function(settings)
	{
		var el = this;
		var cas = {
			
			config: {
				sliderActiveClass: 'enabledJS',
				inner: '.productinner', // inner element (wide with float items), must be children of slider !
				
				slideDuration: 500, // frame slide duration in ms
				slideDurationReset: 500, // frame slide duration when sliding last<->first in ms
				autoSlideTimer: 0, // auto slide after duration in ms
				continuous: true, // continue sliding at first or last item
				paddingCorrection: 0, //  padding, margin and border sum of an item
				
				controlsAfter: '.productinner', 	// after this element will be placed controls
				pagerAfter: '',	// '#slider' after this element will be placed pager
				pagerHasPrevAndNext: true,	// display prev and next links
				
				paddingCorrectionParams: [
					'padding-left',
					'padding-right',
					'border-left-width',
					'border-right-width',
					'margin-left',
					'margin-right'
				],
				
				lang: 'cz',
				
				controls: {
					wrapper: '', // items will be wrapped by
					prev: '<a class="sliderPrev"><span class="forBlind">{sliderprev}</span></a>',
					next: '<a class="sliderNext"><span class="forBlind">{slidernext}</span></a>',
					denyClass: 'deny'
				},
				
				pager: {
					wrapper: '<p class="pager"></p>', // items will be wrapped by
					prev: '<a class="prev" href="#">{pagerprev}</a>', // use {word_key} for insert word
					next: '<a class="next" href="#">{pagernext}</a>', // use {word_key} for insert word
					item: '<a href="#">%</a>', // use % for insert page number
					selectedClass: 'bold',
					denyClass: 'deny'
				},
				
				language: {
					cz: {
						sliderprev: '&lt;',
						slidernext: '&gt;',
						pagerprev: 'Predchozi',
						pagernext: 'Další'
					}
				},
				
				slideStepOneItem: false,
				
				debug: false // show log, requires console object
			},
			
			init: function(slider)
			{
				// store elements
				cas.el = {};
				cas.el.slider = slider;
				cas.el.inner = cas.el.slider.find(cas.config.inner);
				cas.el.firstItem = cas.el.inner.children(':first');
				cas.el.controlsAfter = cas.config.controlsAfter ? $(cas.config.controlsAfter) : false;
				cas.el.pagerAfter = cas.config.pagerAfter ? $(cas.config.pagerAfter) : false;
					
				cas.log('Slider initiating. ---------------------------------', 'info');	
				if(!cas.el.inner.length)
				{
					cas.log('Slider inner block not found! Stopping initialization.', 'error');
					return false;
				}		
				if(!cas.el.controlsAfter.length)
					cas.log('Controls after not found. Controls will not be placed.', 'info');
				if(!cas.el.pagerAfter.length)
					cas.log('Pager after not found. Pager will not be placed.', 'info');
								
				// counting params
				cas.itemsCount = cas.el.inner.children().length;
				cas.sliderWidth = parseInt(cas.el.slider.width());
				cas.inFrame = Math.round(cas.sliderWidth / cas.el.firstItem.width());
				
				cas.step = cas.sliderWidth; // FIXED puvodne Math.round(cas.sliderWidth / cas.inFrame);, ale to pak neposouva po celych framech ale jen po jejich castech, coz pusovi problemy pageru
				
				cas.active = 0;
				
				// more items in frame
				//if(cas.inFrame > 1)
					cas.pagesTotal = Math.round(cas.itemsCount/cas.inFrame);
				// only one item in frame
				//else
					//cas.pagesTotal = cas.itemsCount;
					
					
				cas.log('Found '+cas.itemsCount+' items in slider.', 'info');
				cas.log('Placing '+cas.inFrame+' items to frame.', 'info');
				cas.log('Slide step will be '+cas.step+'.', 'info');
		
				
				// items are more than in one frame
				if (cas.itemsCount > cas.inFrame) 
				{
					// add class enabled js to slider
					cas.el.slider.addClass(cas.config.sliderActiveClass);	
					// append pager
					cas.makeAndAppendPager();
					// append prev and next link
					cas.makeAndAppendControls();
					// reset state
					cas.slide(0);
					cas.changeControlsState('prev', 'deny');
				}
				else
					cas.log('Not enough items in slider. No pager or controls will be placed.', 'info');
			},
			
			
			/**
			 * Makes and appends pager
			 */
			makeAndAppendPager: function()
			{
				if(!cas.el.pagerAfter) return false;
				
				var item = '';
				
				var pager = $(cas.config.pager.wrapper);
				
				// show in pager prev and next
				if(cas.config.pagerHasPrevAndNext)
				{
					$(cas.replaceWord(cas.config.pager.prev)).click(function(){ cas.prev(); return false; }).appendTo(pager);
				}
				
				for (var i = 0; i < cas.pagesTotal; i++) 
				{
					cas.counter = i;
					
					// replace % by page number
					var item = $(cas.config.pager.item.replace('%', i+1));
					
					// create click function
					eval("var clickfcn = function(){ cas.slide("+i+", false, $(this)); return false; };");
					
					// first page => hightlight
					if(i==0)
					{
						item.click(clickfcn).addClass('ccnt-'+i).addClass(cas.config.pager.selectedClass).appendTo(pager);
					}
					// other pages
					else
					{
						item.click(clickfcn).addClass('ccnt-'+i).appendTo(pager);
					}
				}
				// store page count
				
				// show in pager prev and next
				if (cas.config.pagerHasPrevAndNext) 
				{
					$(cas.replaceWord(cas.config.pager.next)).click(function(){ cas.next(); return false; }).appendTo(pager);
				}
				
				cas.log('Appending pager with '+cas.pagesTotal+' pages.', 'info');
				// append pager
				cas.el.pagerAfter.after(pager);
				// trope pager element
				cas.el.pager = pager;
				
				return true;
			},
			
			/**
			 * Makes and appends control links (prev, next).
			 */
			makeAndAppendControls: function()
			{
				if(!cas.el.controlsAfter.length) return false;
				cas.log('Appending controls.', 'info');
				cas.el.controls = {};
				cas.el.controls.next = $(cas.replaceWord(cas.config.controls.next)).click(function(){ cas.next(); return false; });
				cas.el.controls.prev = $(cas.replaceWord(cas.config.controls.prev)).click(function(){ cas.prev(); return false; });
				if(typeof(cas.config.controls.wrapper)!='undefined'&&cas.config.controls.wrapper)
				{				 
					cas.el.controls.wrapper = $(cas.config.controls.wrapper);
					cas.el.controls.prev.appendTo(cas.el.controls.wrapper);
					cas.el.controls.next.appendTo(cas.el.controls.wrapper);
					cas.el.controls.wrapper.insertAfter(cas.el.controlsAfter);					
				}
				else
				{
					cas.el.controls.next.insertAfter(cas.el.controlsAfter);
					cas.el.controls.prev.insertAfter(cas.el.controlsAfter);
				}
				return true;
			},
			
			/**
			 * Hightlight page in pager
			 * 
			 * @param {Object} el
			 */
			hightlightPagerItem: function(el)
			{
				if (typeof(el)=='undefined' || typeof(cas.el.pager)!='object' )  return false;
				// is object
				if (typeof(el)=='object' && !el.length) return false;
				// no object, only string
				if(typeof(el)=='string')
				{
					var selected = cas.el.pager.find('.'+cas.config.pager.selectedClass);
					var offset = 0;
					// no prev and next
					if(cas.config.pagerHasPrevAndNext)
						offset = 1;
					// highlight prev
					if(el=='prev')
						el = selected.prev();
					// highlight next
					if(el=='next')
						el = selected.next();
					// highlight first
					if (el == 'first') 
					{
						el = selected.siblings('.page:first'); // FIXME pager problem - je nejak portebovat odlisit siblingy a toto reseni pres classu neni vhodne
					}
					// highlight last
					if(el=='last')
					{
						el = selected.siblings('.page:last'); // FIXME pager problem - je nejak portebovat odlisit siblingy a toto reseni pres classu neni vhodne
					}
				}
				// remove highlight
				el.siblings().removeClass(cas.config.pager.selectedClass);
				// highlight desired
				el.addClass(cas.config.pager.selectedClass);
				return true;
			},
			
			log: function(e, type)
			{
				if (typeof(console) == 'object' && cas.config.debug)
				{
					if(type=='error')
						console.error(e);
					else if(type=='warning')
						console.warning(e);
					else if(type=='info')
						console.info(e);
					else if(type=='debug')
						console.debug(e);
					else
						console.log(e);
				}
				else 
				{
					//alert(e);
				}
			},
			
			/**
			 * Slide to number
			 * 
			 * @param {integer} n
			 * @param {boolean} reset
			 * @param {object} el
			 */
			slide: function(n, reset, el)
			{
				cas.active = n;
				
				// hightlight pager item
				cas.hightlightPagerItem(el);
				
				//cas.blankFrameCount = cas.inFrame - (cas.itemsCount - Math.floor(cas.itemsCount / cas.inFrame) * cas.inFrame);
				
				var leftOffset = cas.active * cas.step + cas.active * cas.config.paddingCorrection;
				
				cas.el.inner.animate({
					marginLeft: -leftOffset + 'px'
				}, reset ? cas.config.slideDurationReset : cas.config.slideDuration);
				
				cas.log('Sliding to item '+cas.active+' ('+ (-leftOffset) + 'px)');
				
				//$(cas.config.pagerId).children('.page').removeClass('selected');
				//$(cas.config.pagerId).children('.page:eq(' + cas.active + ')').addClass('selected');
				
				if (cas.config.autoSlideTimer) 
				{
					clearTimeout(cas.timeoutHandler);
					cas.timeoutHandler = setTimeout( function(){ cas.next(); }, cas.config.autoSlideTimer);
				}
				
				cas.changeControlsState('reset');
			},
			
			/**
			 * Slide to prev
			 */
			prev: function()
			{
				if (cas.active > 0) 
				{
					cas.slide(cas.active - 1, false, 'prev' );
				}
				else 
				{
					if(cas.config.continuous)
					{
						cas.slide(cas.pagesTotal-1, true, 'last');
					}
				}
				if(!cas.config.continuous && cas.active == 0)
				{
					cas.changeControlsState('prev', 'deny');
				}
			},
			
			/**
			 * Slide to next
			 */
			next: function()
			{
				//log(cas.active+', '+(cas.pagesTotal-1));
				if (cas.active < cas.itemsCount - cas.inFrame/* - 1*/ && cas.active < cas.pagesTotal-1) // FIXED puvodne if (cas.active < cas.itemsCount - cas.inFrame) delalo neplechu ve spolupraci s pagerem
				{
					cas.slide(cas.active + 1, false, 'next');
				}
				else 
				{
					if(cas.config.continuous)
					{
						cas.slide(0, true, 'first');
					}
				}
				if(!cas.config.continuous && cas.active == cas.pagesTotal - 1)
				{
					cas.changeControlsState('next', 'deny');
				}
			},
			
			changeControlsState: function(dir, type)
			{
				if(dir=='reset')
				{
					if(typeof(cas.el.controls)=='object' && typeof(cas.config.pager.denyClass)!='undefined')
					{
						cas.el.controls.prev.removeClass(cas.config.controls.denyClass);
						cas.el.controls.next.removeClass(cas.config.controls.denyClass);
					}
					if(typeof(cas.el.pager)=='object')
					{
						if(cas.config.pagerHasPrevAndNext && typeof(cas.config.pager.denyClass)!='undefined' && cas.config.pager.denyClass)
						{
							cas.el.pager.children(':first').removeClass( cas.config.pager.denyClass );
							cas.el.pager.children(':last').removeClass( cas.config.pager.denyClass );
						}
					}	
				}
				else if(dir=='prev')
				{
					if(type='deny')
					{
						if(typeof(cas.el.controls)=='object')
						{
							cas.el.controls.prev.addClass(cas.config.controls.denyClass);
						}
						if(typeof(cas.el.pager)=='object' && typeof(cas.config.pager.denyClass)!='undefined' && cas.config.pager.denyClass)
						{
							if(cas.config.pagerHasPrevAndNext)
								cas.el.pager.children(':first').addClass(cas.config.pager.denyClass);
						}
					}
				}
				else if(dir=='next')
				{
					if(type='deny')
					{
						if(typeof(cas.el.controls)=='object')
						{
							cas.el.controls.next.addClass(cas.config.controls.denyClass);
						}
						if(typeof(cas.el.pager)=='object' && typeof(cas.config.pager.denyClass)!='undefined' && cas.config.pager.denyClass)
						{
							if(cas.config.pagerHasPrevAndNext)
								cas.el.pager.children(':last').addClass(cas.config.pager.denyClass);
						}
					}
				}
			},
			
			/**
			 * Replace keywords from dicctionary in string.
			 * 
			 * @param {string} text
			 */
			replaceWord: function(text)
			{
				var words = text.match(/{[^}]*}/);
				
				// no words found, break
				if( !words || !words.length) return text;
				
				var id = '';
				var error = 0;
				
				for(i=0; i<words.length; i++)
				{
					// remove brackets
					id = words[i].replace('{', '').replace('}','');
					
					// language check
					if(typeof(cas.config.language[cas.config.lang])=='undefined')
					{
						cas.log('Undefined language "'+cas.config.lang+'" in dictionary!');
						error++;
					}
					// word check
					else if(typeof(cas.config.language[cas.config.lang][id])=='undefined')
					{
						cas.log('Undefined word with id "'+id+'" in dictionary!');
						error++;
					}
					
					if(error==0)
					{
						// replace word
						text = text.replace( words[i], cas.config.language[cas.config.lang][id] );
					}
					else
					{
						cas.log('Unable to replace word with "'+id+'" in "'+text+'"!');						
					}
				}
				return text;
			}
		};
		
		// extend init settings by local settings
		$.each(settings, function(key, val){ 
			if(typeof(val)=='object')
			{
				$.extend(cas.config[key], val);
			}
			else
			{
				cas.config[key] = val;
			}
		});
		
		// init slider
		cas.init(el);
		
	};
	
})(jQuery);

