(function( $ ){
    
    var settings = {
        'smoothing' : 0,
        'duration' : 1250,
        'wait' : 6000,
        'init_wait' : 4000,
        'num_preload' : 2,
        'auto_play' : true,
        'stop_wait' : 60000,
        'current_class' : 'current',
        'stopped_class' : 'stopped',
        'btn_id_prefix' : 'herobtn_',
        'btn_class' : 'herobtn omniture',
        'enumerate' : false,
        'enumerate_prefix' : null,
        'enumerate_postfix' : null,
        'z_index' : 1,
        'child_image': true,
        'nofade_ie_versions': []
    };
    
    var hs_vars = {
        index: 0,
        slides: null,
        num_slides: null,
        timer: null,
        numloaded: 0,
        isfirst: true,
        state: null,
        currentBtn: null,
        buttons: {},
        noFade: false
    }
    
    $.fn.heroSlides = function( method ) {
        if ( methods[method] ) return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        else if ( typeof method === 'object' || ! method ) return methods.init.apply( this, arguments );
        return this;
    };
    
    //
    //  public methods
    //
    
    var methods = {
        init: function(options)
        {
            if (this.length <= 1) return false ;
            hs_vars.slides = this
            hs_vars.num_slides = hs_vars.slides.length;
            if ( options ) $.extend( settings, options );
            hs_vars.noFade = internal.noFade()
            num_preload = !!Number(settings.num_preload) ? Math.max(0,Math.min(hs_vars.num_slides,Number(settings.num_preload))) : hs_vars.num_slides ;
            internal.setSlides()
            return this;
        },
        togglePlay: function()
        {
            if (hs_vars.state == "playing") methods.stop()
            else methods.play()
            return this;
        },
        play: function(wait)
        {
            if (hs_vars.state != "playing"){
                hs_vars.state = "playing"
                internal.clearTimer()
                internal.toggleStates(["play","stop","togglePlay"],settings.stopped_class)
                if (!wait) wait = settings.wait;
                hs_vars.timer = setTimeout(methods.next,wait);
            }
            return this;
        },
        stop: function()
        {
            if (hs_vars.state != "stopped"){
                hs_vars.state = "stopped"
                internal.clearTimer()
                internal.toggleStates(["play","stop","togglePlay"],settings.stopped_class)
                if (settings.stop_wait) setTimeout(methods.play,Math.max(settings.stop_wait-settings.wait,0))
            }
            return this;
        },
        next: function(){
            methods.goTo(hs_vars.index + 1 < hs_vars.num_slides ? hs_vars.index + 1 : 0);
            return this;
        },
        prev: function(){
            methods.goTo(hs_vars.index - 1 >= 0 ? hs_vars.index - 1 : hs_vars.num_slides -1);
            return this;
        },
        goTo: function(idx) {
            if (idx == hs_vars.index) methods.stop()
            else {
				if ($.browser.msie) {
					$(hs_vars.slides).find('img[src$=.png]').each(function() {
						this.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=false)";
					});
				}
                if (hs_vars.timer) internal.clearTimer()
                if (!hs_vars.noFade) $(hs_vars.slides[hs_vars.index]).fadeOut(settings.duration)
                else $(hs_vars.slides[hs_vars.index]).hide()
                hs_vars.index = idx >= 0 && idx < hs_vars.num_slides ? idx : 0;
                if (!hs_vars.noFade && this.smoothing) setTimeout(internal.newIn,settings.duration * settings.smoothing )
                else internal.newIn()
				if ($.browser.msie) {
					$(hs_vars.slides).find('img[src$=.png]').each(function() {
						this.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true)";
					});
				}
            }
            return this
        },
        setTogglePlay: function(i,d) {
            hs_vars.buttons.togglePlay = internal.activeDiv(i,d,methods.togglePlay)
            return hs_vars.buttons.togglePlay
        },
        setPlay: function(i,d) {
            hs_vars.buttons.play = internal.activeDiv(i,d,methods.play)
            return hs_vars.buttons.play
        },
        setStop: function(i,d) {
            hs_vars.buttons.stop = internal.activeDiv(i,d,methods.stop)
            return hs_vars.buttons.stop
        },
        setNext: function(i,d) {
            hs_vars.buttons.next = internal.activeDiv(i,d,methods.next)
            return hs_vars.buttons.next 
        },
        setPrev: function(i,d) {
            hs_vars.buttons.prev = internal.activeDiv(i,d,methods.prev)
            return hs_vars.buttons.prev
        },
        setLinks: function(i,d,btns) {
            var container = (i || d) ? internal.activeDiv(i,d) : false;
            if (!!btns) btns = $(btns)
            else var ul = $("<ul>")
            hs_vars.slides.each(function(){
                var slide = $(this)
                var idx = Number(slide.attr("index"))
                var func = function(){
                    methods.goTo(idx)
                    methods.stop()
                }
                if (!!btns) var btn = internal.activeDiv(null,$(btns[idx]),func)
                else var btn = internal.activeDiv({"class":settings.btn_class},$("<li>"),func)
                if (!!ul && settings.btn_id_prefix) btn.attr("id",settings.btn_id_prefix+idx)
                if (idx===0) btn.addClass('first')
                else if (idx==hs_vars.num_slides-1) btn.addClass('last')
                if (settings.enumerate) {
                    if (settings.enumerate===true) btn.html(settings.enumerate_prefix+(idx+1)+settings.enumerate_postfix)
                    else btn.html(settings.enumerate_prefix+settings.enumerate+settings.enumerate_postfix)
                }  
                hs_vars.buttons["goto_"+idx] = btn
                if (!!ul) ul.append(btn)
            })
            internal.setCurrent()
            if (!!ul) container.append(ul) 
            return container
        }
    };
    
    //
    //  internal methods
    //
    
    var internal = {
        setSlides: function( )
        {
            hs_vars.slides.each(function(i) {
                var slide = $(this);
                slide.attr("index",i)
                if (slide.is('img')) simg = slide
                else if (settings.child_image === true) simg = slide.children("img")[0]
                else if (settings.child_image) simg = slide.children("img."+settings.child_image)[0]
                if (!simg || simg.complete) internal.checkLoaded(slide)
                else {
                        $(simg).load(function() {
                                internal.checkLoaded(slide)
                        });
                }
            })
        },
        checkLoaded: function(slide)
        {
            if (hs_vars.isfirst) {
                hs_vars.isfirst = false
                slide.css({'display':'block'})
            }
            hs_vars.numloaded++;
            if (hs_vars.numloaded == num_preload && settings.auto_play) methods.play(settings.init_wait);
            return this
        },
        hideSlide: function(slide) {
            slide.load(function() {
                slide.fadeOut(0)
            });
            return this
        },
        newIn: function() {
            internal.setCurrent()
            if (!hs_vars.noFade) $(hs_vars.slides[hs_vars.index]).fadeIn(settings.duration)
            else $(hs_vars.slides[hs_vars.index]).show()
            if (hs_vars.state=="playing") hs_vars.timer = setTimeout(methods.next,settings.duration + settings.wait);
            return this
        },
        clearTimer: function() {
            if (hs_vars.timer) {
                clearTimeout(hs_vars.timer)
                hs_vars.timer = null
            }
        },
        activeDiv: function (i,d,f,args) {
            if (!!i){
                if (d) {
                    if ((typeof(i))=="object") d.attr(i)
                } else {
                    if ((typeof(i))=="string") d = $("<div>").attr("id",i)
                    else if ((typeof(i))=="object") d = $("<div>").attr(i)
                }
            }
            if (!!f) $(d).click(function(){f(args)})
            return d
        },
        toggleStates: function(arr,clss) {
            $(arr).each (function(i,v){
                if (hs_vars.buttons[v]) hs_vars.buttons[v].toggleClass(clss)
            })
        },
        setCurrent: function(){
            if (hs_vars.currentBtn) hs_vars.currentBtn.removeClass(settings.current_class)
            if (hs_vars.buttons["goto_"+hs_vars.index]) {
                hs_vars.currentBtn = hs_vars.buttons["goto_"+hs_vars.index]
                hs_vars.currentBtn.addClass(settings.current_class)
            }  
        },
        noFade: function() {
            var version = parseInt($.browser.version,10)
            nofade = false
            $(settings.nofade_ie_versions).each(function(i,val){
                if (version!=val) return true
                else {
                    nofade = true
                    return false
                }     
            })
            return nofade
        }
    };

})( jQuery );
