/**
 * 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.6
 * @date January 25, 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/jquery-ulslide-2/ 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 or fade
				axis: 'x',     // x, y
				distance: 20   // Distance between frames
			},
			duration: 600,     // Changing duration
			direction: 'f',    // f, b
			autoslide: false,  // 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'] = $('> li', 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;*/
        }

        $('> li', 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 (i == settings['current']){
                liel.css("top", '0');
                liel.css("left", '0');
            }
            else{
                liel.css("top", '0');
                liel.css("left", -(settings['width'] + settings['effect']['distance']));
            }
        });

        thisObj.css("list-style", "none");
        thisObj.css("distance", "0");
        thisObj.css("position", "relative");
        thisObj.css("overflow", "hidden");
        thisObj.css("width", settings['width']);
        if (settings['height'] == 'auto'){
            thisObj.css("height", $('> li:eq('+settings['current']+')', thisObj).height());
        }
        else thisObj.css("height", settings['height']);
        settings['prevHeight'] = settings['height'];

        thisEl.getSlide = function getSlide(num) {
            return $('> li:eq('+num+')', thisEl);
        };
		
        function next() {
            settings['show_intermediate'] = false;
            var c = thisEl.uslCurrent();
			settings['direction'] = 'f';
            if (c + 1 < settings['count']) {
				thisEl.uslRefresh(c + 1);
            } else {
				
                thisEl.uslRefresh(0);
            }          
        }
		
        function prev() {
            settings['show_intermediate'] = false;
            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;

                //if (c > thisEl.uslCurrent()) settings['direction'] = 'f';
                //else settings['direction'] = 'b';

                settings['current'] = new_value;
                return new_value;
            }
        };

        thisEl.autoslideNext = function(){
            settings['show_intermediate'] = false;
            if (settings['current'] < settings['count'] - 1) settings['current'] ++;
            else settings['current'] = 0;
            this.uslRefresh();
        };

        thisEl.initAutoslide = function(){
            if (settings['TimeoutID']) clearTimeout(settings['TimeoutID']);
            settings['TimeoutID'] = setTimeout("$('#"+$(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['print_current']) {
						$(settings['print_current']).html(settings['current'] + 1);
					}

                    if (settings['prev'] != settings['current']) {
                        prev.css('display', 'none');
                    }

                    //console.log(settings['id'] + ': finish_animate(): h = ' + thisEl.currentHeight);
                    //console.log(thisEl.getSlide(settings['current']));
					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['show_intermediate'] !== false) {
                            var intermediate = thisEl.getSlide(settings['show_intermediate']);

                            if (settings['direction'] == 'f'){
                                intermediate.css('left', settings['fwidth']);
                                current.css('left', settings['fwidth'] * 2);

                                prev.animate({
                                    'left': -(settings['fwidth'] * 2)
                                }, settings['duration']);

                                intermediate.animate({
                                    'left': -(settings['fwidth'])
                                }, settings['duration']);

                                current.animate({
                                    'left': 0
                                }, settings['duration'], function(){
                                    finish_animate();
                                });
                            }
                            else {
                                intermediate.css('left', -(settings['fwidth']));
                                current.css('left', -(settings['fwidth'] * 2));

                                prev.animate({
                                    'left': settings['fwidth'] * 2
                                }, settings['duration']);

                                intermediate.animate({
                                    'left': settings['fwidth']
                                }, settings['duration']);

                                current.animate({
                                    'left': 0
                                }, settings['duration'], function(){
                                    finish_animate();
                                });
                            }
                        }
                        else {
                            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();
						});
					});
                }
            }
			
            if (settings['ajax']) {
                settings['onAjaxStart'](settings, thisEl); // notification
                var statusbar_loaded = thisEl.getSlide(settings['current'])[0].usl_ajax_loaded;

                thisEl.uslAjaxLoadSlide(settings['current'], function() {
                    if (settings['show_intermediate']) {
                        thisEl.uslAjaxLoadSlide(settings['show_intermediate'], function() {
                            settings['onAjaxStop'](settings, thisEl); // notification
                            doRefresh();
                        })
                    }
                    else {
                        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())) {
                    //alert(settings['show_intermediate']);
                    //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); 
