/*
Script: moostick dot js
    A Mootools-powered, unobstrusive, Javascript news ticker library. /mouthful
License: 
    MIT License <http://www.opensource.org/licenses/mit-license.php>
    Copyright (c) 2007 Stephane Daury
*/

if(typeof(window['MooTools']) == 'undefined'){
    var mstkRedirect = 'http:/www.mootools.net/';

    if(confirm('Moostick requires the MooTools JavaScript framework.\n'
               + 'Be sure to include it before Moostick.\n\n'
               + 'Click OK for more info, or Cancel to load the page without it.')){
        top.location.href = redirect;
    }
}
else{
    var MstkHelpers = {
        qsVar: function(key){
            var val = false;
            if(key.length > 0){
                document.getElements('script').each(function(s){
                    if(s.src.match('moostick.js?')){
                        var uriParts = s.src.split('?');
                        if(uriParts[1]){
                            uriParts[1].split('&').each(function(keyPair){
                                var tmp = keyPair.split('=');
                                if(tmp[1] && tmp[0] == key)
                                    val = tmp[1];
                            });
                        }
                    }
                });
            }
            return val;
        },
        checkArray: function(val){
            if(!val[0])
                return [val];
            else
                return val;
        }
    
    } // end MstkHelpers


    // See: <Procedural code>
    
    if(MstkHelpers.qsVar('init') !== 'false'){
        window.addEvent('domready', function() {
            MstkInit.go(false, false);
        });
    }
    var MstkInit = {
        
        lists        : false,
        autoStart    : false,
        interval     : 5500,
        fxOptions    : {},
        trust4Speed  : false,
        trustOpacity : false,
        go: function(lists, autoStart, interval, fxOptions, trust4Speed, trustOpacity) {
            this.lists        = (!lists)
                              ? this.lists
                              : lists;
    
            this.autoStart    = (autoStart === true)
                              ? autoStart
                              : this.autoStart;
            
            this.interval     = (!interval) || (interval.toInt() < 500)
                              ? this.interval
                              : interval.toInt();
            
            this.fxOptions    = ((!fxOptions) || (typeof(fxOptions) != 'object'))
                              ? this.fxOptions
                              : fxOptions;
            
            this.trust4Speed  = (trust4Speed === true)
                              ? trust4Speed
                              : this.trust4Speed;
            
            this.trustOpacity = (trustOpacity === true)
                              ? trustOpacity
                              : this.trustOpacity;
    
            if(this.autoStart === true){
                if(this.trust4Speed === true){
                    // Kamikaze mode!
                    this._fastMode();
                }
                else{
                    // Cautious mode
                    this._safeMode();
                }
            }
        },
        _fastMode: function(){
            this.lists = MstkHelpers.checkArray(this.lists);
            this.lists.each(function(list){
                new Moostick(
                    list,
                    this.autoStart,
                    this.interval,
                    this.fxOptions,
                    this.trust4Speed,
                    this.trustOpacity
                )
            }, this);
        },
        _safeMode: function(){
            
            if(this.lists === false){
                var defaultLists = false;
                
                // Scan for a list with the recommended default id
                if($('moostick'))
                    defaultLists = [$('moostick')];
    
                // Or can for (a) list(s) with the recommended default class
                else if($$('.moostick'))
                    defaultLists = $$('.moostick');
                
                this.lists = (!defaultLists) ? false : defaultLists;
            }
     
            if(this.lists){
                this.lists = MstkHelpers.checkArray(this.lists);
                this.lists.each(function(list){
                    new Moostick(
                        list,
                        this.autoStart,
                        this.interval,
                        this.fxOptions,
                        this.trust4Speed,
                        this.trustOpacity
                    )
                }, this);
            }
        }
    
    } // end MstkInit


    var Moostick = Class({
        
  
        list         : {},
        autoStart    : false,
        interval     : 3500,
        fxOptions    : {},
        trust4Speed  : false,
        trustOpacity : false,
        _firstRun    : true,
        _elSched     : null,
        _fx: false,
        initialize: function(list, autoStart, interval, fxOptions, trust4Speed, trustOpacity) {
            this.list         = ((!list) || (typeof(list) != 'object'))
                              ? this.list
                              : list;
    
            this.autoStart    = (autoStart === true)
                              ? autoStart
                              : this.autoStart;
            
            this.interval     = (!interval) || (interval.toInt() < 500)
                              ? this.interval
                              : interval.toInt();
            
            this.fxOptions    = ((!fxOptions) || (typeof(fxOptions) != 'object'))
                              ? this.fxOptions
                              : fxOptions;
            
            this.trust4Speed  = (trust4Speed === true)
                              ? trust4Speed
                              : this.trust4Speed;
            
            this.trustOpacity = (trustOpacity === true)
                              ? trustOpacity
                              : this.trustOpacity;
            
            this.list.moostick = this;
            
            if(this.autoStart === true){
                if(this.trust4Speed === true){
                    // Kamikaze mode!
                    this._fastMode();
                }
                else{
                    // Cautious mode
                    this._safeMode();
                }
            }
        },
        startTick: function(list, interval, fxOptions, trust4Speed, trustOpacity){
            this.initialize(list, true, interval, fxOptions, trust4Speed, trustOpacity);
        },
        stopTick: function(){
            // TODO: figure out why removeEvent isn't working here
            this.list.$events.mouseenter = false;
            this.list.$events.mouseleave = false;
            this.pauseTick();
        },
        pauseTick: function(){
            this._elSched = $clear(this._elSched);
        },    
        resumeTick: function(){
            this._schedule();
        },
        _fastMode: function(){
            this._liHandler();
            this._schedule();
        },
        _safeMode: function(){
     
            if(this.list){
     
                if(this.list.getElements('li')){
                    var items = this.list.getElements('li');
                    // Assign proprietary CSS class if not already assigned
                    if(!this.list.hasClass('moostick')) this.list.addClass('moostick');
                   
                    // Test for an indication of existing style assignements,
                    var noStyle = false;
                    if( this.list.getStyle('overflow') != 'hidden'
                        || items[0].getStyle('display') != 'block'
                        || items[0].getStyle('list-style-type') != 'none'){
                        // we'll assume (!) no compatible style has been applied
                        noStyle = true;
                    }
                        
                    if(noStyle){                
                        this.list.setStyles({
                            'display' : 'block',
                            'height'  : '1.1em',
                            'margin'  : 0,
                            'padding' : '2px 0 2px 0',
                            'overflow': 'hidden'
                        });
                        
                        this._liHandler({
                            'display'        : 'block',
                            'list-style-type': 'none',
                            'margin'         : '0 auto 0 auto',
                            'padding'        : 0
                        });
                    }
                    else{
                        this._liHandler();
                    }
                    
                    // We should now have a *more* trustworthy environment
                    this._schedule();
                }
            }
        },
        _setMouseEvents: function(){  
            this.list.addEvents({
                'mouseenter': function(){
                    this.moostick.pauseTick();
                },
                'mouseleave': function(){
                    this.moostick.resumeTick();
                }
            });
        },
        _liHandler: function(styles){
            // Verify styles value and format
            if((!styles) || (typeof(styles) != 'object')) styles = false;
            
            // no need to even loop if no styles were sent and trusting opacity
            if((this.trustOpacity !== true) || (styles !== false)){
                
                this.list.getElements('li').each(function(li){
                    // Apply styles before forcing opacity
                    if(styles !== false) li.setStyles(styles);
                    
                    // Turn off all li but first
                    if(this.trustOpacity !== true)
                        li.setOpacity(0);
                });
            }
        },
        _schedule: function(){
            if(!this._elSched){
                // Define if we should fade the first item in or not.
                var firstItem = this.list.getElement('li');
                if(firstItem.getStyle('opacity') != 1)
                    this._fadeIn(firstItem);
                else if(this._firstRun === true)
                    this._fadeIn(firstItem);
                
                // Schedule <Moostick._run>
                this._elSched = this._run.periodical(
                    this.interval,
                    this,
                    this.list
                );
                
                // Set <Moostick._setMouseEvents>
                listEvents = this.list.$events;
                if(!listEvents)
                    this._setMouseEvents();
                else if((!listEvents.mouseenter) && (!listEvents.mouseleave))
                    this._setMouseEvents();
            }
        },
        _run: function(){
            var items = this.list.getElements('li');
            
            // If we have at least 2
            if(items[1]){
                // Move first to last
                items[0].injectAfter(items.getLast());
                
                // Fade new first in
                this._fadeIn(items[1]);
                
                // Set new last off, for future fade in
                this.list.getElements('li').getLast().setOpacity(0);
            }
        },
        _fadeIn: function(item){
            this._fx = new Fx.Tween(item, this.fxOptions).start('opacity',0,1);
            this._firstRun = false;
        }
    
    }); // end Moostick
    
}
