/*********************************************************
 * WA.Effect.Expand
 * 
 * Provides ability for a dom element to vertically slide
 * in and out of view.
 * 
 * Sample usage:
 * 
 * <a id='help'>Help</a>
 * <div id='helpContent'>...help content...</div>
 * 
 * <script type='text/javascript'>
 *     window.addEvent('domready', function() {
 *         var link    = $('help');
 *         var content = $('helpContent');
 *         new WA.Effect.Expand( link, content, {open:true} );
 *     } );
 * </script>
 *********************************************************/
WA.Effect.Expand = new Class({
    Implements : [Events, Options],
    
    options : {
        open   : false,
        cookie : ''
    },
    
    initialize : function( link, content, options ) {
        this.setOptions( options ); 
        this.link       = link;
        if( !link ) return;
        this.content    = content || link.getNext();
        this.cookie     = this.options.cookie
            ? this.options.cookie
            : '';
        this.expandIcon = this.link.getElement('.expand') || this.link;
        this.effect     = new Fx.Slide(this.content, {
            duration    : 200,
            resetHeight : true,
            transition  : Fx.Transitions.Pow.easeOut,
            onStart     : this.onSlideStart.bind(this),
            onComplete  : this.onSlideComplete.delayed(1, this)
        });
        // bind a click event on the link to the toggling of the slide effect
        this.link.addEvent('click', this.onLinkClick.bind(this));
        if( this.cookie && Cookie.read(this.cookie) != null ) {
            this.options.open = Cookie.read(this.cookie) ? true : false;
        }
        // initialize the expand icon as opened or closed
        if ( this.options.open ) {
            if( this.expandIcon ) this.expandIcon.swapClass('close', 'open');
            this.updateOverflow('visible');
        } else {
            if( this.expandIcon ) this.expandIcon.swapClass('open', 'close');
            this.effect.hide();
        }
        this.content.removeClass('hide');
        // store a reference to the expand object in the link object for easy lookup from other objects
        this.link.store('expand', this);
        this.updateCookie();
    },
    
    onLinkClick : function(event) {
        if ( event ) {
            event.stop();
        }
        this.effect.toggle('vertical');
    },
    
    // handler for the start of the slide effect
    onSlideStart : function() {
        // don't show overflow as expand effect is in process
        this.updateOverflow('hidden');
    },
    // handler for the completion of the slide effect
    // fires a show/hide event and updates the expandIcon if present
    onSlideComplete : function() { 
        if ( this.isOpen() ) {
            this.fireEvent('show');
            this.updateOverflow('visible');
            if( this.expandIcon ) this.expandIcon.swapClass( 'close', 'open' );
        } else {
            this.fireEvent('hide');
            if( this.expandIcon ) this.expandIcon.swapClass( 'open', 'close' );
        }
        
        this.updateCookie();
    },
    
    show : function() {
        this.effect.show();
        this.updateOverflow('visible');
        this.updateCookie();
    },
    
    hide : function() {
        this.effect.hide();
        this.updateOverflow('hidden');
        this.updateCookie();
    },
    
    isOpen : function() {
        return this.effect.open;
    },
    
    updateOverflow : function( value ) {
        this.content.setStyle('overflow', value);
        this.content.getParent().setStyle('overflow', value);
    },
    
    updateCookie : function() {
        if ( !this.cookie ) {
            return;
        }
        Cookie.write(this.cookie, this.isOpen() ? 1 : 0, this.options.cookieOptions);
    }
});

