(function( $ ){
    
    var settings = {
        'duration' : 400,
        'init_width': 0,
        'init_height': 0,
        'opacity_in': 1,
        'close_button' : '.close_flyout',
        'current_class' : 'current',
        'default_left' : 100,
        'default_top' : 400,
        'default_left_offset' : 100,
        'default_top_offset' : -200,
        'fade_all_selector' : null,
        'all_out_opacity' : .1,
        'multi_open' : false
    };
    
    $.fn.flyOut = 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 fv_vars = {
        swappers: [],
        flyoutOpen: false,
        buttons: null,
        flyouts: null
    }
    var methods = {
        init: function(options)
        {
            if (this.length <= 1) return false ;
            fv_vars.buttons = this
            return this;
        },
        setFlyOuts: function(flys)
        {
            fv_vars.flyouts = $(flys)
            fv_vars.flyouts.each(function(i) { 
                obj = $(this)
                obj.find(settings.close_button).click(function(){
                    internal.objOut($(fv_vars.flyouts[i]))
                })
                obj.attr("data-width",obj.css("width"))
                obj.attr("data-height",obj.css("height"))
                obj.css(internal.outjson(obj))
            })
            internal.activate()
            return this;
        },
        addSwapper: function(selector,clss)
        {
            fv_vars.swappers.push({"selector":selector,"class":clss})
            return this;
        }
    };
    
    var tweening = false;
    
    //
    //  internal methods
    //
    
    var internal = {
        activate: function( )
        {
            fv_vars.buttons.each(function(i) {
                $(this).click(function(e){
                    e.preventDefault()
                    if (settings.multi_open || !fv_vars.flyoutOpen) internal.objIn($(fv_vars.flyouts[i]))
                })
            })
        },
        objIn: function(obj) {
            fv_vars.flyoutOpen = true
            obj.addClass(settings.current_class)
            var animateTo = {
                'opacity':settings.opacity_in,
                'width':obj.attr("data-width"),
                'height':obj.attr("data-height"),
                'left':obj.attr("data-left") ? obj.attr("data-left")  : settings.default_left,
                'top':obj.attr("data-top") ? obj.attr("data-top")  : settings.default_top                
            }
            obj.animate(animateTo,{'duration':settings.duration,'queue':false})
            if (settings.fade_all_selector) $(settings.fade_all_selector).fadeTo(settings.duration,settings.all_out_opacity)
            $(fv_vars.swappers).each(function(i,obj){
                $(obj.selector).addClass(obj["class"])
            })
        },
        objOut: function(obj) {
            obj.animate(internal.outjson(obj),{'duration':settings.duration,'queue':false})
            if (settings.fade_all_selector) $(settings.fade_all_selector).fadeTo(settings.duration,1)
            $(fv_vars.swappers).each(function(i,obj){
                $(obj.selector).removeClass(obj["class"])
            })
            fv_vars.flyoutOpen = false
        },
        outjson: function (obj) {
            var l = obj.attr("data-left") ? Number(obj.attr("data-left")) : settings.default_left
            var t = obj.attr("data-top") ? Number(obj.attr("data-top")) : settings.default_top
            var l_off = obj.attr("data-left-offset") ? Number(obj.attr("data-left-offset")) : settings.default_left_offset
            var t_off = obj.attr("data-top-offset") ? Number(obj.attr("data-top-offset")) : settings.default_top_offset
            var jobj = {
                'opacity':0,
                'width':settings.init_width,
                'height':settings.init_height,
                'left':l-l_off,
                'top':t-t_off             
            }
            return jobj
        }
    };

})( jQuery );
