(function($) {
    $.jkSlider = function(element, options) {
	// To avoid confusion about "this" issues
	var base = this;

	var settings = {
	    startIndex: 0,
	    slideInterval: 5000,
	    duration: 500,
	    cycleForwardEffect: 'fade',
	    cycleBackwardEffect: 'fade',
	    width: '200px',
	    height: '400px',
	    autoPlay: true,
	    randomSwitch: false,
	    autoResize: false,
	    animateAutoResize: false
	}

	base.$element = $(element);
	$.extend(settings, options);
	base.settings = settings;

	base.initialize = function(){
	    base.effect = Array;
	    base.$slides = base.$element.children(".jks-slide");
	    base.current = settings.startIndex;
	    base.timer = new $.jkLoop(base.cycleForward, settings.slideInterval);
	    base.autoResize();
	    $.each(base.$slides, function(index, slide) {
		$slide = $(slide);
		$slide.css({
		    'position': 'absolute', 
		    'z-index': 0, 
		    'display': 'block', 
		    'left': 0, 
		    'right': 0, 
		    'top': 0, 
		    'bottom': 0
		});
		if(index != settings.startIndex) $slide.css({
		    'display': 'none'
		});
	    });
	    return base;
	}
	
	base.autoResize = function() {
	    if(settings.autoResize == true) {
		var slideSize = base.getSlideSize(base.current);
		base.setSlidesContainerSize(slideSize.width, slideSize.height);
	    } else {
		base.setSlidesContainerSize(settings.width, settings.height);
		base.setAllSlidesSize(settings.width, settings.height);
	    }
	}
	
	base.setSlidesContainerSize = function(width, height, animate) {
	    if(typeof(animate) == 'undefined' || animate == false) {
		base.$element.css({
		    "width": width,
		    "height": height
		});
	    } else {
		base.$element.animate({
		    "width": width,
		    "height": height
		}, settings.duration, 'linear', function() {/* Animation complete.*/});
	    }    
	}
	
	base.setAllSlidesSize = function(width, height) {
	    base.$slides.each(function(index, slide) {
		base.setSlideSize(index, width, height);
	    });
	}
	
	base.setSlideSize = function(index, width, height) {
	    $(base.$slides[index]).css({
		"width": width, 
		"height": height
	    });
	}
	
	base.getSlideSize = function(index) {
	    return {
		'width': $(base.$slides[index]).css('width'),
		'height': $(base.$slides[index]).css('height')
	    }
	}

	base.start = function() {
	    base.show(base.current);
	    if(settings.autoPlay) base.timer.startLoop();
	    return base;
	}

	base.show = function(slideIndex, effectName) {
	    $(base).trigger('onShowBegin');
	    if(slideIndex != base.current) {
		var $current = $(base.$slides[base.current]).css({
		    'z-index': 1, 
		    'display': 'block', 
		    'left': 0, 
		    'right': 0, 
		    'top': 0, 
		    'bottom': 0
		});
		var $next = $(base.$slides[slideIndex]).css({
		    'z-index': 0, 
		    'display': 'block', 
		    'left': 0, 
		    'right': 0, 
		    'top': 0, 
		    'bottom': 0
		});
		base.effect[effectName]($current, $next, settings.duration, base);
		base.current = slideIndex;
		base.autoResize();
		setTimeout(function() {
		    $(base).trigger('onShowComplete');
		    $current.css({
			'display': 'none'
		    });
		},settings.duration);
	    } else {
		$(base).trigger('onShowComplete');
	    }
	    return base; 
	}
	
	base.getSlideByIndex = function(index) {
	    return base.$slides[index];
	}

	base.getSlides = function() {
	    return base.$slides;
	}

	base.getCurrentSlideIndex = function() {
	    return base.current;
	}

	base.getNextSlideIndex = function() {
	    return (base.current < base.$slides.length-1) ? base.current+1 : 0;
	}

	base.getPreviousSlideIndex = function() {
	    return (base.current > 0) ? base.current-1 : base.$slides.length-1;
	}

	base.cycleForward = function() {
	    $(base).trigger('onCycleForward');
	    if(settings.randomSwitch) base.show(parseInt(Math.random() * (base.$slides.length)));
	    else base.show(base.getNextSlideIndex(), settings.cycleForwardEffect);
	    return base;
	}

	base.cycleBackward = function(){
	    $(base).trigger('onCycleBackward');
	    if(settings.randomSwitch) base.show(parseInt(Math.random() * (base.$slides.length)));
	    else base.show(base.getPreviousSlideIndex(), settings.cycleBackwardEffect);
	    return base;
	}

	base.play = function() {
	    $(base).trigger('onPlay');
	    base.timer.startLoop();
	    return base;
	}

	base.pause = function() {
	    $(base).trigger('onPause');
	    base.timer.stopLoop();
	    return base;
	}

	base.togglePlayPause = function(){
	    if(base.getState() == "play") {
		base.pause();
	    } else if (base.getState() == "stop") {
		base.play();
	    }
	    return base;
	}

	//returns the state: play or stop
	base.getState = function() {
	    return base.timer.getState();
	}

	base.reverse = function() {
	    var loopFunction = (base.timer.loopMethod == base.cycleForward) ? base.cycleBackward : base.cycleForward;
	    base.timer.setLoop(loopFunction, settings.slideInterval);
	    $(base).trigger('onReverse');
	    return base;
	}
	
	base.addEffect = function(name, fn) {
	    this.effect[name] = fn;
	}

	//init
	base.initialize();
	
    } //end Class

})(jQuery);
