var AjaxPane = new Class({
    
    options: {
        initial: null,
        urlbase: "/goodies/goodie/",
        onShow: Class.empty,
        onHideComplete: Class.empty
    },
    
    initialize: function(element, options) {
        
        this.setOptions(options);
        
        // Vars
        
        this.showing = false;
        this.transitioning = false;
        this.current = 0;
        
        // Elements
        
        this.element = $(element);
        this.contentDiv = this.element.getElement(".content"); // Content div
        
        // Animation objects
        
        this.oSlide = new Fx.Slide(this.element, { // Preview window slider
            duration: 500,
            wait: false,
            onComplete: function() { this.wrapper.setStyle("height", "auto") }
        }
        ).hide();
        
        this.oFade = new Fx.Style(this.element, "opacity", {duration: 500, wait: false}).set(0); // Preview window fader
        this.oContent = new Fx.Slide(this.contentDiv, {duration: 500, wait: false}).hide(); // Content div slider
        this.oContentFade = new Fx.Style(this.contentDiv, 'opacity', {duration: 500, wait: false}).set(0); // Content fader
        this.oScroller = new Fx.Scroll(window);
        
        this.indicator = $(this.element.getElement(".loading")); // Loading indicator
        this.indicator.setStyle("visibility", "hidden");
        
        // Close button event
        
        var close = this.element.getElements(".close");
        
        close.each(function(item) {
            item.addEvent("click", function(evt) {
                evt = new Event(evt).stop();
                this.hide();
            }.bind(this));
        }, this);
        
        if ($type(this.options.initial) != false) this.options.initial = this.options.initial.toInt();
        if ($type(this.options.initial) == 'number' && !isNaN(this.options.initial)) this.load(this.options.initial);
        
    },
    
    // Show preview window and load url
    
    show: function(url) {
        if (!this.transitioning) {
            this.fireEvent('onShow');
            if (this.showing) {
                this.loadRequest(url);
            } else {
                this.transitioning = true;
                this.oSlide.slideIn().chain(
                    function() {
                        this.oFade.start(1).chain(function(){
                            this.transitioning = false;
                            this.showing = true;
                            this.loadRequest(url);
                            return true;
                        }.bind(this));
                    }.bind(this)
                );
            }
        }
    },
    
    // Hide preview window
    
    hide: function() {
        if (!this.transitioning && this.showing) {
            this.transitioning = true;
            this.unload();
            this.oFade.start(0).chain(
                function() {
                    this.oSlide.slideOut().chain(function(){
                        this.transitioning = false;
                        this.showing = false;
                        this.oContent.slideIn().chain(function() {
                            this.fireEvent('onHideComplete');
                        }.bind(this));
                        return true;
                    }.bind(this));
                }.bind(this)
            );
        }
    },
    
    // Load trafficking
    
    load: function(id) {
        
        if (!this.showing || (this.showing && this.current != id)) {
            
            this.current = id;
        
            var url = this.options.urlbase + id; // Set request URL
            
            if (this.oAjax && this.oAjax.running) this.oAjax.cancel(); // Cancel AJAX call
            this.indicator.setStyle("visibility", "visible"); // Show indicator
            this.hideObjects();
            this.oScroller.toElement(this.element);
            
            this.oContentFade.start(0).chain(function() {            
                if (!this.showing) {
                    this.show(url);
                } else {
                    this.unload();
                    this.loadRequest(url);
                }
            }.bind(this));
        }
    },
    
    // AJAX request and content transitioning
    
    loadRequest: function(url) {
        var ref = this;
        this.oAjax = new Ajax(url, {
            update: this.contentDiv,
            evalScripts: true,
            onComplete: function() {
                ref.hideObjects();
                ref.indicator.setStyle("visibility", "hidden");
                ref.oContent.slideIn().chain(function() { 
                    ref.oContentFade.start(1).chain(function() {
                        ref.showObjects();
                    });
                });
            }
        }).request();
    },
    
    sendForm: function(form_id) {
        
        var ref = this;
        
        this.indicator.setStyle("visibility", "visible");
        
        this.hideObjects();
        
        this.oContentFade.start(0).chain(function() {
            ref.oAjax = new Ajax($(form_id).getProperty('action'), {
                data: $(form_id).toQueryString(),
                method: 'post',
                evalScripts: true,
                update: ref.contentDiv,
                onComplete: function() {
                    ref.indicator.setStyle("visibility", "hidden");
                    ref.oContent.slideIn().chain(function() { 
                        ref.oContentFade.start(1).chain(function() {
                            ref.showObjects();
                        });
                    });
                }
            }).request();
        });
        
    },
    
    // Cancel any running AJAX and clear out content div
    
    unload: function() {
        if (this.oAjax.running) this.oAjax.cancel(); // Cancel AJAX call
        this.contentDiv.empty();
    },
    
    // Get object sets that need to be hidden during animation (because they still display)
    
    getObjects: function() {
        var objects = [];
        objects.extend(this.contentDiv.getElementsByTagName("object"));
        objects.extend(this.contentDiv.getElementsByTagName("embed"));
        if (window.ie) objects.extend(this.contentDiv.getElementsByTagName("select"));
        return objects;
    },
    
    // Hide animation-unfriendly objects
    
    hideObjects: function() {
        var objects = this.getObjects();
        if (objects.length > 0) {
            objects.each(function(item) {
                item.style.visibility = "hidden";
            });
        }
    },
    
    // Show animation-unfriendly objects
    
    showObjects: function() {
        var objects = this.getObjects();
        if (objects.length > 0) {
            objects.each(function(item) {
                item.style.visibility = "visible";
                item.style.display = "block";
            });
        }
    }
    
});

AjaxPane.implement(new Options, new Events);