/*
        Shows one list item at the time and scrolls it if overflow occurs.
        jQuery object provided as input should contain positioned elements with one unordered list in each.
        These lists should be limited in either width or height so that content can be scrolled automatically.
        Note: ticker operates only on the first unordered list found. Nested lists are not supported.
        direction = "vertical", "horizontal"
        speed = "slow", "normal", "fast"
*/


/*
    static members:
        list: private list of active tickers
        processTimerEvent: timer handler moves through topics and scrolls them if required
        showNextTopic: show next topic in queue
*/
jQuery.ticker = {
    // static list of tickers
    list: [],
    
    // called on each timer tick
    processTimerEvent: function () {
        jQuery.each( jQuery.ticker.list, function ( k, news ) {
            if( news.ticker.paused ) return;
            if( ++news.ticker.counter < news.ticker.speed ) return;
            if( news.ticker.finished ) {
                jQuery.ticker.showNextTopic( news );
                return;
            }
            // scroll if requred
            var c = news.ticker.currentTopic, pos;
            if( c.ticker.scroll ) {
                if( news.ticker.direction == "vertical" ) {
                    pos = Math.max( news.offsetTop + news.ticker.speed - 4, c.ticker.minY );
                    $( news ).css( "top", pos + "px" );
                } else if( news.ticker.direction == "horizontal" ) {
                    pos = Math.max( news.offsetLeft + news.ticker.speed - 4, c.ticker.minX );
                    $( news ).css( "left", pos + "px" );
                }
                
                if( pos == c.ticker.minY || pos == c.ticker.minX ) {
                    news.ticker.finished = true;
                    news.ticker.counter = -10 * news.ticker.speed;
                } //else
                    // news.ticker.counter = 0;
            }
        } )
    },
    
    // show single news topic
    showNextTopic: function ( news ) {
        var c;
        if( news.ticker.currentTopic ) {
            news.ticker.paused = true;
            c = news.ticker.currentTopic
            news.ticker.currentTopic = news.ticker.currentTopic.ticker.nextTopic;
            $( c ).fadeOut( "slow", jQuery.ticker.showNextTopic2 );
        } else {
            news.ticker.currentTopic = $( "li", news ).get( 0 );
            jQuery.ticker.showNextTopic2( news.ticker.currentTopic );
        }
    },
    
    // second part of showNextTopic (called back when old topic dissapears)
    showNextTopic2: function( o ) {
        var news = this.parentNode ? this.parentNode : o.parentNode;
        news.ticker.paused = false;
        $( news ).css( { top: news.ticker.top+"px", left: news.ticker.left+"px" } );
        $( news.ticker.currentTopic ).fadeIn( "slow" );
        c = news.ticker.currentTopic;
        // calculate whether scrolling is required for first show of this topic
        if( c.ticker.scroll == null ) {
            if( news.ticker.direction == "horizontal" ) {
                if( c.ticker.scroll = c.offsetWidth > news.ticker.container.offsetWidth )
                    c.ticker.minX = news.ticker.innerWidth + news.ticker.left - c.offsetWidth;
            } else if( news.ticker.direction == "vertical" ) {
                if( c.ticker.scroll = c.offsetHeight > news.ticker.container.offsetHeight )
                    c.ticker.minY = news.ticker.innerHeight + news.ticker.top - c.offsetHeight;
            }
        }
        news.ticker.finished = ! c.ticker.scroll;
        // if this topic is not scrollable, then set timout to pass to next topic
        if( ! c.ticker.scroll )
            news.ticker.counter = -10 * news.ticker.speed;
        else
            news.ticker.counter = -5 * news.ticker.speed;
    }

};



( function ( $ ) {  // create closure for hiding private members

    $.fn.ticker = function ( direction, speed ) {
        var news = $( "ul", this ).get( 0 );
        if( ! news ) return;
        
        $( this )
            .css( { overflow: "hidden" } );
        
        $( news )
            .css( { position: "absolute", padding: "0px", margin: "0px" } )
            .mouseover( function () {
                this.ticker.paused = true;
            } )
            .mouseout( function () {
                this.ticker.paused = false;
            } )
        
        var s = 2;
        switch( speed.toLowerCase() ) {
            case "fast": s=1; break;
            case "slow": s=3; break;
        }
        
        news.ticker = {
            innerWidth: $( this ).innerWidth() - num( this, "paddingLeft" ) - num( this, "paddingRight" ),
            innerHeight: $( this ).innerHeight() - num( this, "paddingTop" ) - num( this, "paddingBottom" ),
            left: num( this, "paddingLeft" ),
            top: num( this, "paddingTop" ),
            "direction": direction.toLowerCase(),
            "speed": s,
            container: this.get( 0 ),
            paused: false,
            counter: 0,
            finished: false,
            currentTopic: null
        }
        
        // create linked list between topics and show only the first one
        var lastTopic = null, firstTopic = null;
        $( "li", news )
            .css( "display", "block" )
            .hide()
            .each( function () {
                this.ticker = {};
                if( firstTopic ) {
                    lastTopic.ticker.nextTopic = this;
                } else {
                    // the first topic
                    $.ticker.showNextTopic( news );
                    firstTopic = this;
                }
                lastTopic = this;
            } )
        lastTopic.ticker.nextTopic = firstTopic;
        
        $.ticker.list.push( news );
        if( $.ticker.list.length == 1 )
            setInterval( $.ticker.processTimerEvent, 55 );
        
        return this;
    }
    
    
    // borrowed from dimensions plugin
    var num = function ( el, prop ) {
	    return parseInt( $.css( el.jquery ? el[0] : el, prop ) ) || 0;
    };

} ) ( jQuery );
