/**
 * When I noticed the growing popularity of JS-Slide and JS-Fade effects I have
 * decide to develop a plugin for jQuery. This plugin will help you to add thise
 * effects to the site in more simple way.
 * Note: If the mousewheel plugin has been included on the page then the slider will
 * also respond to the mouse wheel.
 *
 * @name jQuery ulSlide plugin
 * @license GPL
 * @version 1.4.8
 * @date January 31, 2011
 * @category jQuery plugin
 * @author Kotelnitskiy Evgeniy (evgennniy@gmail.com)
 * @copyright (c) 2011 Kotelnitskiy Evgeniy (http://4coder.info/en/)
 * @example Visit http://4coder.info/en/code/jquery-plugins/ulslide/ for more informations about this jQuery plugin
 */
(function($) {
    ulslide_last_id = 0;

    $.fn.ulslide = function(settings) {
        var thisObj = this;
        if (thisObj.length == 0) return false;
        var thisEl = thisObj[0];
        if (! $(thisEl).attr('id')) {
            ulslide_last_id ++;
            $(thisEl).attr('id', 'ulslide-' + ulslide_last_id);
        }
        var id = $(thisEl).attr('id');

        // Settings
        settings = $.extend({
            effect: {
                type: 'slide', // slide, fade or carousel (use showCount for carousel)
                axis: 'x',     // x, y
                distance: 20   // Distance between frames
            },
            duration: 1600,     // Changing duration
            direction: 'f',    // f, b
            autoslide: true,  // Autoscrolling interval (ms)
            current: 0,
			
            width: thisObj.width(),
            height: 'auto',    // pixels or 'auto'
			
            statusbar: true,
            lazyload: false,   // testing
            ajax: false,
			
            mousewheel: false, // Scroll on "mousewheel"
			
            // Selectors:
            pager: false,
            nextButton: false,
            prevButton: false,
            printCurrentTo: false,
			
            //framesOnPage: 2, 
            onAnimateStart: function(settings, thisEl){},
            onAnimate: function(settings, thisEl){},
            onAjaxStart: function(settings, thisEl){},
            onAjaxStop: function(settings, thisEl){}
        },settings);

        // Deprecated Options
        if (typeof settings['affect']        != 'undefined') settings['effect']['type']     = settings['affect'];
        if (typeof settings['axis']          != 'undefined') settings['effect']['axis']     = settings['axis'];
        if (typeof settings['padding']       != 'undefined') settings['effect']['distance'] = settings['padding'];
        if (typeof settings['navigator']     != 'undefined') settings['pager']              = settings['navigator'];
        if (typeof settings['print_current'] != 'undefined') settings['printCurrentTo']     = settings['print_current'];
        if (typeof settings['bnext']         != 'undefined') settings['nextButton']         = settings['bnext'];
        if (typeof settings['bprev']         != 'undefined') settings['prevButton']         = settings['bprev'];
        // end Deprecated Options
		
        if (typeof settings['effect']['distance'] == 'undefined') settings['effect']['distance'] = 20;
        settings['fwidth'] = settings['width'] + settings['effect']['distance'];
        settings['prev'] = settings['current'];
        settings['count'] = $('> *', thisObj).length;

        if (settings['lazyload']) {
            $('img', thisObj).each(function(i){
                var img = $(this);
                img.attr('rel', img.attr('src'));
                if (i > 0) {
                    img.removeAttr("src");
                }
            });
            /*settings['_lazyloaded'][0] = true;*/
        }

		
		function carouselGetFramePos(i, current){
			if (i >= settings['effect']['showCount'] - current) {
				var l = settings['count'] - settings['effect']['showCount'];
				var ci = (i + current - settings['effect']['showCount']) - l;
				return ci;
			}
			else return i + current;
		}
		
		// CSS for elements		
        $('> *', thisObj).each(function(i){
            var liel = $(this);
            liel.addClass('slide-node slide-node-'+i);
            liel.css("position", 'absolute');
            liel.css("margin", '0');
            liel.css("distance", '0');
            liel.css("width", settings['width']);
            liel.css("overflow", "hidden");
			
			if (settings['effect']['type'] == 'carousel') {
				var ci = carouselGetFramePos(i, settings['current']);
				
				liel.css("top", '0');
				liel.css("left", (ci * settings['fwidth']));
			}
			else {
				if (i == settings['current']){
					liel.css("top", '0');
					liel.css("left", '0');
				}
				else{
					liel.css("top", '0');
					liel.css("left", -(settings['width'] + settings['effect']['distance']));
				}
			}
        });

		// CSS for container
        thisObj.css("list-style", "none");
        thisObj.css("distance", "0");
        thisObj.css("position", "relative");
        thisObj.css("overflow", "hidden"); 
        thisObj.css("padding", 0);

		if (settings['effect']['type'] == 'carousel') {
			thisObj.css("width", settings['fwidth'] * settings['effect']['showCount'] - settings['effect']['distance']);
		}
		else {
			thisObj.css("width", settings['width']);
		}

		
        if (settings['height'] == 'auto'){
            thisObj.css("height", $('> *:eq('+settings['current']+')', thisObj).height());
        }
        else thisObj.css("height", settings['height']);
        settings['prevHeight'] = settings['height'];

        thisEl.getSlide = function getSlide(num) {
            return $('> *:eq('+num+')', thisEl);
        };
		
        function next() {
            var c = thisEl.uslCurrent();
            settings['direction'] = 'f';
            if (c + 1 < settings['count']) {
                thisEl.uslRefresh(c + 1);
            } else {
				
                thisEl.uslRefresh(0);
            }          
        }
		
        function prev() {
            var c = thisEl.uslCurrent();
            settings['direction'] = 'b';
            if (c > 0) {
                thisEl.uslRefresh(c - 1);
            } else {
                thisEl.uslRefresh(settings['count'] - 1);
            }
        }

        if (settings['height'] == 'auto')
            thisEl.currentHeight = thisEl.getSlide(settings['current']).height();
        else thisEl.currentHeight = settings['height'];

        thisEl.uslCurrent = function(new_value){
            if (new_value == undefined){
                return settings['current'];
            }
            else {
                var old = thisEl.uslCurrent();
                var c = new_value;

                settings['current'] = new_value;
                return new_value;
            }
        };

        thisEl.autoslideNext = function(){
			if (settings['direction'] == 'f') next();
            else prev();
        };

        thisEl.initAutoslide = function(){
            if (settings['TimeoutID']) clearTimeout(settings['TimeoutID']);
            settings['TimeoutID'] = setTimeout("jQuery('#"+$(thisEl).attr('id')+"')[0].autoslideNext()", settings['autoslide']);
        };

        thisEl.clearAutoslide = function(){
            if (settings['TimeoutID']) {
                clearTimeout(settings['TimeoutID']);
            }
        };

        thisEl.uslRefresh = function(slide_index, fast, callback){
            if (! thisEl.ready) {
                //console.log(settings['id'] + ': ! thisEl.ready');
                setTimeout("$('#"+$(thisEl).attr('id')+"')[0].uslRefresh()", 400);
                return;
            }
            thisEl.ready = false;
			
            if (typeof(slide_index) != 'undefined') {
                thisEl.uslCurrent(slide_index);
            }

            thisEl.clearAutoslide();
            var prev = thisEl.getSlide(settings['prev']);
            var current = thisEl.getSlide(settings['current']);
            current.css('display', 'block');

            function doRefresh() {
                settings['onAnimateStart'](settings, thisEl); // notification
                //console.log(settings['id'] + ': doRefresh');

                if (settings['height'] == 'auto') {
                    thisEl.currentHeight = thisEl.getSlide(settings['current']).height();
                    settings['prevHeight'] = thisEl.getSlide(settings['prev']).height();
                }

                function finish_animate() {
                    if (settings['printCurrentTo']) {
                        $(settings['printCurrentTo']).html(settings['current'] + 1);
                    }

                    if ((settings['prev'] != settings['current']) && (settings['effect']['type'] != 'carousel') ) {
                        prev.css('display', 'none');
                    }

                    thisObj.animate({
                        'height': thisEl.currentHeight
                    }, 250/*, function() { alert(settings['id'] + ': finish_animate()' + thisEl.currentHeight); }*/);
                    
                    //settings['prev'] = settings['current'];
                    if (settings['autoslide']) thisEl.initAutoslide();
                    settings['onAnimate'](settings, thisEl); // notification
                    settings['prev'] = settings['current'];
                    thisEl.uslRefreshClasses();
                    thisEl.ready = true;

                    if (typeof callback != 'undefined') callback();
                }

                if (settings['prev'] == settings['current']) {
                    finish_animate();
                    return;
                }
								
                if (settings['effect']['type'] == 'slide') {
                    if (settings['effect']['axis'] == 'x'){
						if (settings['prev'] != settings['current']){
							if (settings['direction'] == 'f'){
								prev.animate({
									'left': -(settings['width'] + settings['effect']['distance'])
								}, settings['duration']);
								current.css('left', settings['width'] + settings['effect']['distance']);
							}
							else{
								prev.animate({
									'left': settings['width'] + settings['effect']['distance']
								}, settings['duration']);
								current.css('left', -(settings['width'] + settings['effect']['distance']));
							}
						}
						current.animate({
							'left': 0
						}, settings['duration'], function(){
							finish_animate();
						});
                    }
                    else {
                        if (settings['prev'] != settings['current']){
                            if (settings['direction'] == 'f'){
                                prev.animate({
                                    'top': thisEl.currentHeight + settings['effect']['distance']
                                }, settings['duration'], function(){
                                    prev.css('left', -(settings['width'] + settings['effect']['distance']));
                                });
                                current.css('top', -(settings['prevHeight'] + settings['effect']['distance']));
                            }
                            else{
                                prev.animate({
                                    'top': -(thisEl.currentHeight + settings['effect']['distance'])
                                }, settings['duration'], function(){
                                    prev.css('left', -(settings['width'] + settings['effect']['distance']));
                                });
                                current.css('top', settings['prevHeight'] + settings['effect']['distance']);
                            }
                        }
                        current.css('left', 0);
                        current.animate({
                            'top': 0
                        }, settings['duration'], function(){
                            finish_animate();
                        });
                    }
                }
                else if (settings['effect']['type'] == 'fade') {
                    current.css('display', 'none');
                    //current.css('z-index', 2);
                    current.css('left', 0);
                    current.css('top', 0);
                    //prev.css('z-index', 1);
                    var duration = settings['duration'];
                    if (typeof fast != 'undefined') duration = 0;
                    
                    prev.fadeOut(duration, function(){
                        prev.css('display', 'none');
                        current.fadeIn(duration, function(){
                            finish_animate();
                        });
                    });
                }
				else if (settings['effect']['type'] == 'carousel') {
					$('> *', thisObj).each(function(i){
						liel = $(this);
						var ci = carouselGetFramePos(i, settings['current']);
						if (settings['direction'] == 'f')
							 var pi = carouselGetFramePos(i, settings['current'] - 1);
						else var pi = carouselGetFramePos(i, settings['current'] + 1);

						if ((settings['direction'] == 'f') && (ci == 0)) {
							liel.css('left', (-1 * settings['fwidth']));
							liel.animate({'left': ci * settings['fwidth']}, settings['duration']);
						}
						else if ((settings['direction'] == 'f') && (pi + 1 == settings['effect']['showCount'])) {
							liel.animate({'left': (settings['effect']['showCount']) * settings['fwidth']}, settings['duration']);
						}
						else if ((settings['direction'] == 'b') && (pi == 0)) {
							liel.animate({'left': -1 * settings['fwidth']}, settings['duration']);
						}
						else if ((settings['direction'] == 'b') && (ci + 1 == settings['effect']['showCount'])) {
							liel.css('left', (ci + 1) * settings['fwidth']);
							liel.animate({'left': ci * settings['fwidth']}, settings['duration']);
						}
						else {
							if ((ci < settings['effect']['showCount']) && (ci >= 0)) {
								liel.animate({'left': ci * settings['fwidth']}, settings['duration']);
							}
							else {
								liel.css('left', (ci * settings['fwidth']));
							}
						}
						
						setTimeout(function(){
								finish_animate();
						}, settings['duration'] + 100);					
					});
				}
            }
			
            if (settings['ajax']) {
                settings['onAjaxStart'](settings, thisEl); // notification
                var statusbar_loaded = thisEl.getSlide(settings['current'])[0].usl_ajax_loaded;

                thisEl.uslAjaxLoadSlide(settings['current'], function() {
					settings['onAjaxStop'](settings, thisEl); // notification
					doRefresh();
                })
            }
            else {
                if (settings['lazyload']) {
                    var $imgToLoad = $('img', current[0]);

                    $imgToLoad.each(function(i){
                        var img = $(this);
                        img.attr('src', img.attr('rel'));
                    });

                    settings['z_img_count'] = $imgToLoad.length;
                    settings['z_img_loaded'] = 0;
                    $imgToLoad.each(function(){
                        if (this.complete) {
                            settings['z_img_loaded'] ++;
                        }
                        else {
                            $(this).load(function(){
                                settings['z_img_loaded'] ++;
                                if (settings['z_img_loaded'] == settings['z_img_count']){
                                    doRefresh();
                                }
                            });
                        }
                    });

                    if (settings['z_img_loaded'] == settings['z_img_count']){
                        doRefresh();
                    }
                    return;
                }
                
                doRefresh();
            }
        };
		
        thisEl.uslAjaxLoadSlide = function(slide_num, callback) {
            var current = thisEl.getSlide(slide_num);

            if (current[0].usl_ajax_loaded) {
                callback();
            }
            else {
                var url = $(settings['pager']).eq(slide_num).attr('href');
                current[0].usl_ajax_loaded = true;
                current.load(url + '?ajax=1', false, callback);
            }
        };

        thisEl.uslRefreshClasses = function(){
            if (settings['count'] > 1){
                if (settings['nextButton']) $(settings['nextButton']).addClass('active');
                if (settings['prevButton']) $(settings['prevButton']).addClass('active');
            }
            if (settings['pager']){
                $(settings['pager']).removeClass('usl-current');
                $(settings['pager'] + '.usl-pager-'+thisEl.uslCurrent()).addClass('usl-current');
                $(settings['pager']).parent().removeClass('usl-current-parent');
                $(settings['pager'] + '.usl-pager-'+thisEl.uslCurrent()).parent().addClass('usl-current-parent');
            }
        };

        if (settings['nextButton']){
            $(settings['nextButton']).click(function(){
                next();
                return false;
            });
        }
		
        if (settings['prevButton']){
            $(settings['prevButton']).click(function(){
                prev();
                return false;
            });
        }

        function setNavigator(s_navigator) {
            var pager = $(s_navigator);
            pager.each(function(index){
                this.usl_navigator_index = index;
                $(this).addClass('usl-pager-' + index);
            });
					
            pager.click(function(){
                var c = this.usl_navigator_index;
                if ((c < settings['count']) && (c != thisEl.uslCurrent())) {
                    //thisEl.uslCurrent(c);
                    if (c > thisEl.uslCurrent()) settings['direction'] = 'f';
                    else settings['direction'] = 'b';
                    thisEl.uslRefresh(c);
                }
                return false;
            });
        }
		
        if (settings['pager']){
            setNavigator(settings['pager']);
        }
        if (settings['navigator2']){
            setNavigator(settings['navigator2']);
        }
        
        function loadingStatus(loading) {
            if (loading) {
                thisObj.addClass('usl-loading');
            }
            else {
                thisObj.removeClass('usl-loading');
            }
        }
		
        thisEl.uslStatusbar = function() {		
		
            if (settings['lazyload']) {
                var $imgToLoad = $('>li:eq('+settings['current']+') img', thisEl);
            }
            else {
                var $imgToLoad = $('img', thisEl);
            }
            
            settings['img_count'] = $imgToLoad.length;
            if (settings['img_count']) {
                loadingStatus(true);
            }

            settings['img_loaded'] = 0;
            $imgToLoad.each(function(){
                if (this.complete) {
                    settings['img_loaded'] ++;
                }
                else {
                    $(this).load(function(){
                        settings['img_loaded'] ++;
                        //alert(settings['img_loaded'] + ' of ' + settings['img_count']);
                        if (settings['img_loaded'] == settings['img_count']){
                            loadingStatus(false);
                            thisEl.ready = true;
                            thisEl.uslRefresh();
                        }
                    });
                }
            });

            if (settings['img_loaded'] == settings['img_count']){
                loadingStatus(false);
                thisEl.ready = true;
                thisEl.uslRefresh();
            }
        };

        // statusbar
        if (settings['statusbar'] && !settings['ajax']){
            thisEl.uslStatusbar();
        }

        /*
         * If the mousewheel plugin has been included on the page then
         * the slider will also respond to the mouse wheel.
         */
        if (settings['mousewheel']) {
            thisObj.bind(
                'mousewheel',
                function (event, delta) {
                    if (thisEl.ready) {
                        if (delta < 0) {
                            next();
                        }
                        else {
                            prev();
                        }
                    }
                    return false;
                });
        }
		
        if (! settings['statusbar'] || settings['ajax']) {
            thisEl.ready = true;
            thisEl.uslRefresh();
        }
    };
})(jQuery); 
