(function( $ ){
    
    var settings = {
        out_duration: 1000,
        in_duration: 1,
        num_cylces: 1,  // 'loop' = infinite num cycles!
        index_attr: "data-layer-index"
    };
    
    var lb_vars = {
        cycle_index: 0,
        triggers: null,
        disablers: [],
        layers: [],
        style_objects_a: [],
        style_objects_b: [],
        stopped: true,
        trigger_id: null,
        trigger_index: 0        
    }
    
    $.fn.layerBounce = 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)
        {
            lb_vars.triggers = this
            lb_vars.triggers.each(function(i){
                $(this).attr(settings.index_attr,i)
                lb_vars.layers[i] = new Array()
            })
            return this;
        },
        addLayer: function(layer,stylea,styleb)
        {
            lb_vars.style_objects_a[lb_vars.trigger_index] = stylea
            lb_vars.style_objects_b[lb_vars.trigger_index] = styleb
            $(layer).each(function(j){
                lb_vars.layers[j][lb_vars.trigger_index] = $(this)
            })
            lb_vars.trigger_index++
            return this;
        },
        addDisabler: function(elm,clss) {
            lb_vars.disablers.push({"elm":$(elm),"class":clss})
        },
        enable: function(lbtn,rbtn)
        {
            lb_vars.disablers = $(lb_vars.disablers)
            lb_vars.triggers.mouseover(function(){
                if (!internal.isdisabled()) {
                    lb_vars.stopped = false
                    internal.bounce($(this).attr(settings.index_attr));
                }
            })
            lb_vars.triggers.mouseout(function(){
                internal.stop();    
            })
            return this;
        }
    };
    
    
    //
    //  internal methods
    //
    
    var internal = {
        bounce: function(idx) {
            if (lb_vars.stopped) return
            var loop_func = function(){
                lb_vars.cycle_index ++
                if (settings.num_cylces != "loop" && lb_vars.cycle_index >= settings.num_cylces) internal.stop()
                else internal.bounce(idx)
            }
            $(lb_vars.layers[idx]).each(function(i){
                this.animate(lb_vars.style_objects_a[i],settings.in_duration).animate(lb_vars.style_objects_b[i],settings.out_duration,loop_func)
                loop_func = null
            })    
        },
        stop: function() {
            $(lb_vars.layers).each(function(i){
                lb_vars.stopped = true;
                lb_vars.cycle_index = 0
            })    
        },
        isdisabled: function() {
            var disabled = false
            lb_vars.disablers.each(function(){
                if (this.elm.hasClass(this["class"])) {
                    disabled = true
                    return false
                } else {
                    return true
                }
            })
            return disabled
        }
    };

})( jQuery );
