(function($) {
    
    var name='newsTicker';
    
    function runTicker(settings) {
        
        tickerData = $(settings.newsList).data('newsTicker');
        
        if(tickerData.currentItem > tickerData.newsItemCounter){
            // if we've looped to beyond the last item in the list, start over
            tickerData.currentItem = 0;
        }
        else if (tickerData.currentItem < 0) {
            // if we've looped back before the first item, move to the last one
            tickerData.currentItem = tickerData.newsItemCounter;
        }
        
        if(tickerData.currentPosition == 0) {
            if(tickerData.newsLinks[tickerData.currentItem].length > 0) {
                $(tickerData.newsList).empty().append('<li><a href="'+ tickerData.newsLinks[tickerData.currentItem] +'"></a></li>');
            }
            else {
                $(tickerData.newsList).empty().append('<li></li>');
            }
        }
        
        //only start the ticker itself if it's defined as animating: otherwise it's paused or under manual advance
        if (tickerData.animating) {
            
            if( tickerData.currentPosition % 2 == 0) {
                    var placeHolder = tickerData.placeHolder1;
            }
            else {
                var placeHolder = tickerData.placeHolder2;
            }
            
            if( tickerData.currentPosition < tickerData.newsItems[tickerData.currentItem].length) {
                // we haven't completed ticking out the current item
                
                var tickerText = tickerData.newsItems[tickerData.currentItem].substring(0,tickerData.currentPosition);
                if(tickerData.newsLinks[tickerData.currentItem].length > 0) {
                    $(tickerData.newsList + ' li a').text(tickerText + placeHolder);
                }
                else {
                    $(tickerData.newsList + ' li').text(tickerText + placeHolder);
                }
                tickerData.currentPosition ++;
                setTimeout(function(){runTicker(settings); settings = null;},tickerData.tickerRate);
            }
            
            else {
                // we're on the last letter of the current item
                
                if(tickerData.newsLinks[tickerData.currentItem].length > 0) {
                    $(tickerData.newsList + ' li a').text(tickerData.newsItems[tickerData.currentItem]);
                }
                else {
                    $(tickerData.newsList + ' li').text(tickerData.newsItems[tickerData.currentItem]);
                }
                
                setTimeout(function(){
                    if (tickerData.animating) {
                        tickerData.currentPosition = 0;
                        tickerData.currentItem ++;
                        runTicker(settings); settings = null;
                    }
                },tickerData.loopDelay);
                
            }
        }
        
        else {// settings.animating == false 
            
            // display the full text of the current item
            var tickerText = tickerData.newsItems[tickerData.currentItem];
            
            if(tickerData.newsLinks[tickerData.currentItem].length > 0) {
                $(tickerData.newsList + ' li a').text(tickerText);
            }
            else {
                $(tickerData.newsList + ' li').text(tickerText);
            }
                    
        }
        
    }

    
    // Core plugin setup and config
    jQuery.fn[name] = function(options) {
 
        // Add or overwrite options onto defaults
        var settings = jQuery.extend({}, jQuery.fn.newsTicker.defaults, options);
     
        var newsItems = new Array();
        var newsLinks = new Array();
        var newsItemCounter = 0;
        
        // Hide the static list items
        $(settings.newsList + ' li').hide();
        
        // Store the items and links in arrays for output
        $(settings.newsList + ' li').each(function(){
            if($(this).children('a').length) {
                newsItems[newsItemCounter] = $(this).children('a').text();
                newsLinks[newsItemCounter] = $(this).children('a').attr('href');
            }
            else {
                newsItems[newsItemCounter] = $(this).text();
                newsLinks[newsItemCounter] = '';
            }
            newsItemCounter ++;
        });
        
        var tickerElement = $(settings.newsList); // for quick reference below
        
        tickerElement.data(name, {
            newsList: settings.newsList,
            tickerRate: settings.tickerRate,
            startDelay: settings.startDelay,
            loopDelay: settings.loopDelay,
            placeHolder1: settings.placeHolder1,
            placeHolder2: settings.placeHolder2,
            controls: settings.controls,
            ownControls: settings.ownControls,
            stopOnHover: settings.stopOnHover,
            newsItems: newsItems,
            newsLinks: newsLinks,
            newsItemCounter: newsItemCounter - 1, // -1 because we've incremented even after the last item (above)
            currentItem: 0,
            currentPosition: 0,
            firstRun:1
        })
        .bind({
            stop: function(event) {
                // show remainder of the current item immediately
                tickerData = tickerElement.data(name);
                if (tickerData.animating) { // only stop if not already stopped
                    tickerData.animating = false;
                }
            },
            play: function(event) {
                // show 1st item with startdelay
                tickerData = tickerElement.data(name);
                if (!tickerData.animating) { // if already animating, don't start animating again
                    tickerData.animating = true;
                    setTimeout(function(){runTicker(tickerData); tickerData = null;},tickerData.startDelay);
                }
            },
            resume: function(event) {
                // start from next item, with no delay
                tickerData = tickerElement.data(name);
                if (!tickerData.animating) { // if already animating, don't start animating again
                    tickerData.animating = true;
                    // set the character position as 0 to ensure on resume we start at the right point
                    tickerData.currentPosition = 0;
                    tickerData.currentItem ++;
                    runTicker(tickerData); // no delay when resuming.
                }
            },
            next: function(event) {
                // show whole of next item
                tickerData = tickerElement.data(name);
                // stop (which sets as non-animating), and call runticker
              $(tickerData.newsList).trigger("stop");
                // set the character position as 0 to ensure on resume we start at the right point
                tickerData.currentPosition = 0;
                tickerData.currentItem ++;
                runTicker(tickerData);
            },
            previous: function(event) {
                // show whole of previous item
                tickerData = tickerElement.data(name);
                // stop (which sets as non-animating), and call runticker
             $(tickerData.newsList).trigger("stop");
                // set the character position as 0 to ensure on resume we start at the right point
                tickerData.currentPosition = 0;
                tickerData.currentItem --;
                runTicker(tickerData);
            }
        });     
        if (settings.stopOnHover) {
            tickerElement.bind({                    
                mouseover: function(event) {
                    tickerData = tickerElement.data(name);
                    if (tickerData.animating) { // stop if not already stopped
                        $(tickerData.newsList).trigger("stop");
                        if (tickerData.controls) { // ensure that the ticker can be resumed if controls are enabled
                            $('.stop').hide();
                            $('.resume').show();
                        }
                    }
                }
            });
        }
        
        tickerData = tickerElement.data(name);
        
        // set up control buttons if the option is on
        if (tickerData.controls || tickerData.ownControls) {
            if (!tickerData.ownControls) {
                $('<ul class="ticker-controls" style="display:inline;  width:600px; border:1px solid #000;"><li class="resume"><a style="margin:0; padding:0;" href="#resume">Resume</a></li><li class="stop"><a href="#resume">Stop</a></li><li class="previous"><a href="#previous">Previous</a></li><li class="next"><a href="#next">Next</a></li></ul>').insertAfter($(tickerData.newsList));
            }
            $('.play').hide();
            $('.resume').hide();
            
            $('.play').click(function(event){
                $(tickerData.newsList).trigger("play");
                $('.play').hide();
                $('.resume').hide();
                $('.stop').show();
                event.preventDefault();
            });
            $('.resume').click(function(event){
                $(tickerData.newsList).trigger("resume");
                $('.play').hide();
                $('.resume').hide();
                $('.stop').show();
                event.preventDefault();
            });
            $('.stop').click(function(event){
                $(tickerData.newsList).trigger("stop");
                $('.stop').hide();
                $('.resume').show();
                event.preventDefault();
            });
            $('.previous').click(function(event){
                $(tickerData.newsList).trigger("previous");
                $('.stop').hide();
                $('.resume').show();
                event.preventDefault();
            });
            $('.next').click(function(event){
                $(tickerData.newsList).trigger("next");
                $('.stop').hide();
                $('.resume').show();
                event.preventDefault();
            });

        };
        
        // tell it to play
        $(tickerData.newsList).trigger("play");
    };

    // News ticker defaults 
    jQuery.fn[name].defaults = {
        newsList: "#news",
        tickerRate: 80,
        startDelay: 100,
        loopDelay: 3000,
        placeHolder1: " |",
        placeHolder2: "_",
        controls: true,
        ownControls: false,
        stopOnHover: true
    }

})(jQuery);
