/*
*       Image Transitions Manager, version 0.1
*       (c) 2007 Ajaxorized.com
*
*       Authors:        Willem Spruijt
*                               Martijn de Kuijper
*       Website:        http://www.ajaxorized.com/
*/

Element.addMethods( {
        transBringToFront : function(p_eElement) {
            p_eElement.setStyle({zIndex:'2'});
            return p_eElement;
        },
            transSendToBack : function(p_eElement) {
            p_eElement.setStyle({zIndex:'1'});
            return p_eElement;
        },
            transGetHeight : function (p_eElement) {
            return p_eElement.offsetHeight;
        },
            transGetWidth : function (p_eElement) {
            return p_eElement.offsetWidth;
        },
            transGetCenterHeight : function(p_eElement) {
            return (p_eElement.offsetHeight/2);
        },
            transGetCenterWidth : function(p_eElement) {
            return (p_eElement.offsetWidth/2);
        },
            transIsLoaded : function (p_eElement) {
            return (p_eElement.complete);
        }
    }
);

/* The Transition Class */
var Transition = Class.create();
Transition.prototype = {
    initialize: function( p_eTarget ) {
        // get the options object
        // and set up default options
        if(arguments.length > 1) {
           this.options = Object.extend(this.options, arguments[1]);
        }
        this.m_eTarget = $( p_eTarget );
        this.preloads = [];
        this.preload_images();
        // no images!!!!!
        if(this.preloads.length == 0) {
            alert('no images in slideshow!!');
            return;
        }
        this.m_eTarget.setStyle( { position: 'relative', overflow:'hidden'} );
        this.m_eLoading = null;
        this.slideshow = true;
        this.slideshow_current_index = 0;
        this.number_of_slides = this.preloads.length;
        this.number_of_slides_to_show = this.number_of_slides * this.options.times_to_repeat;

        this.playbutton = this.m_eTarget.getElementsByClassName(this.options.play_button_class)[0];
        if(!this.playbutton) {
            this.playbutton = document.createElement( 'div' );
        }

        this.stopbutton = this.m_eTarget.getElementsByClassName(this.options.stop_button_class)[0];
        if(!this.stopbutton) {
            this.stopbutton = document.createElement( 'div' );
        }
        // clear all content of holder.
        $A(this.m_eTarget.getElementsByClassName(this.options.slide_class)).each( function(slide) {
                //this.m_eTarget.removeChild( slide );
            }.bind(this));

        /*///////////////////////////////////////////////////////////////////////////////////////////
         *       TEMPORARY WAY TO ADD FIRST IMAGE!!
         *       Should be added by the loadImage function, but this expects an anchor as parameter.
         */

        var eImage_inner = this.preloads[0].image;

        var imageWidth = parseInt(this.preloads[0].width.sub("px",""));
        var imageHeight = parseInt(this.preloads[0].height.sub("px",""));

        var imageLeft = (this.m_eTarget.transGetWidth() - imageWidth)/2;
        var imageTop = (this.m_eTarget.transGetHeight() - imageHeight)/2;

        var div_width = parseInt(this.m_eTarget.transGetWidth()) + 'px';
        var div_height = parseInt(this.m_eTarget.transGetHeight()) + 'px'

        var inner_image_top = parseInt(imageTop) + 'px';
        var inner_image_left = parseInt(imageLeft) + 'px';
        var inner_image_width = this.preloads[0].width;
        var inner_image_height = this.preloads[0].height;

        var styles = { position:'absolute',
                       top:    inner_image_top,
                       left:   inner_image_left,
                       width:  inner_image_width,
                       height: inner_image_height };

        var eImage = document.createElement( 'div' );

        $(eImage).setStyle( { position: 'absolute',
                    left: '0px',
                    top: '0px',
                    opacity: '0',
                    backgroundColor:('transparent'),
                    width:div_width,
                    height:div_height,
                    textAlign:'center' } );


        if (false && navigator.userAgent.indexOf('MSIE 6.0') > 0) {
            eImage.appendChild(eImage_inner);
            $(eImage_inner).setStyle( styles );
        } else {
            $(eImage.setStyle({background:"transparent url("+ eImage_inner.src +") no-repeat center center"}));
        }

        this.m_eTarget.appendChild( eImage );
        this.m_eCurrent = eImage;
        new Effect.Appear( this.m_eCurrent, { duration: 1.5, from: 0.0, to: 1.0 } );
        /*******************************************************************************************/
        if(this.number_of_slides > 1) {
        // start the slideshow if its enabled
          this.set_up_controls();

          if (this.options.auto_play) {
              this.toggle_control_visibility();
              if(this.slideshow) {
                  this.next_slide();
              }
          }
        } else {
          this.playbutton.hide();
          this.stopbutton.hide();
        }
    },
    options:{slide_class:"_trans_slide",
             play_button_class:"_trans_slide_play",
             stop_button_class:"_trans_slide_stop",
             times_to_repeat:2,
             auto_play:true},
    set_up_controls:function() {
        var thisinstance = this;
        this.playbutton.onclick = function(event){ thisinstance.start_slide_show(); return false;};
        this.stopbutton.onclick = function(event){ thisinstance.stop_slide_show(); return false;};
    },
    toggle_control_visibility:function() {
        if(this.slideshow){
            this.playbutton.hide();
            this.stopbutton.show();
        } else {
            this.stopbutton.hide();
            this.playbutton.show();
        }
    },
    preload_images:function(){
        var index = 0;
        $A($(this.m_eTarget).getElementsByClassName(this.options.slide_class)).each(
            function(slide_el) {
                var image = slide_el.getElementsBySelector('img')[0];
                var trans = slide_el.getElementsByClassName('transition')[0].innerHTML.strip();
                var duration = slide_el.getElementsByClassName('duration')[0].innerHTML.strip();
                this.preloads[index] = {image:new Image(),
                                        duration:parseInt(duration),
                                        transition:trans,
                                        width:image.width + "px",
                                        height:image.height + "px"};
                //this.preloads[index].image.src = this.get_background_image_url_from_slide_element(slide_el);
                this.preloads[index].image.src = image.src;
                index = index + 1;
            }.bind(this)
        );
    },
    get_background_image_url_from_slide_element: function(slide_elm) {
        return slide_elm.style.backgroundImage.sub(/url\(/,"").sub(/\)/,"");
    },
    loadImage: function( preloaded_image_obj ) {

        // Get transition type and image url.
        var sTransition = preloaded_image_obj.transition;

        var eImage_inner = preloaded_image_obj.image;

        var imageWidth = parseInt(preloaded_image_obj.width.sub("px",""));
        var imageHeight = parseInt(preloaded_image_obj.height.sub("px",""));

        var imageLeft = (this.m_eTarget.transGetWidth() - imageWidth)/2;
        var imageTop = (this.m_eTarget.transGetHeight() - imageHeight)/2;

        var div_width = parseInt(this.m_eTarget.transGetWidth()) + 'px';
        var div_height = parseInt(this.m_eTarget.transGetHeight()) + 'px';

        //

        var eImage = document.createElement( 'div' );
        $(eImage).setStyle( { position: 'absolute',
                              left: '0px',
                              top: '0px',
                              opacity: '0',
                              backgroundColor:('transparent'),
                              width:div_width,
                              height:div_height,
                              textAlign:'center' } );

        if (false && navigator.userAgent.indexOf('MSIE 6.0') > 0) {
            eImage.appendChild(eImage_inner);
            $(eImage_inner).setStyle( { position:'absolute',
                                        top: (parseInt(imageTop) + 'px'),
                                        left: (parseInt(imageLeft) + 'px'),
                                        width:(parseInt(imageWidth) + 'px'),
                                        height:(parseInt(imageHeight) + 'px') } );
        } else {
            $(eImage.setStyle({background:"transparent url("+ eImage_inner.src +") no-repeat center center"}));
        }

        this.m_eTarget.appendChild( eImage );
        if(!eImage_inner.complete) {
            /* The image is not yet loaded, so fix the loading div */
            this.m_eLoading = document.createElement( 'div' );
            $( this.m_eLoading ).setStyle( { position: 'absolute', left: '5px',  bottom: '5px', color: '#F00' } );
            this.m_eLoading.appendChild( document.createTextNode( 'loading...' ) );
            this.m_eTarget.appendChild( this.m_eLoading );
            Event.observe( eImage_inner, 'load', this._onLoad.bindAsEventListener( null, this, eImage, sTransition ) );
        } else {
            /* The image is already loaded*/
            this.m_eLoading = null;

            this._transImage(eImage, sTransition);
        }
    },

    _onLoad: function( p_eEvent, p_oRef, p_eImage, p_sTransition ) {
        p_oRef._transImage( p_eImage, p_sTransition );
    },

    _transImage : function(eImage, sTransition) {
        if(this.m_eLoading != null) this.m_eLoading.remove();
        /* ADDED: switch on different transitions, use the naming conventions of scriptaculous (appear, fade, etc).?) */
        switch(sTransition) {
        case 'appear':
            new Effect.Appear( eImage, { duration: 1.5, from: 0.0, to: 1.0 } );
            new Effect.Appear( this.m_eCurrent, { duration: 1.5, from: 1.0, to: 0.0, afterFinish: this._removeImage } );
            break;
        case 'switch':
            new Effect.Appear( eImage, { duration: 0, from: 0.0, to: 1.0 } );
            new Effect.Appear( this.m_eCurrent, { duration: 0, from: 1.0, to: 0.0, afterFinish: this._removeImage } );
            break;
        case 'blinddown':
            $(this.m_eCurrent).setStyle({display:'block', opacity:'1'}).transSendToBack();
            l_oTargetDim = {left:0,top:0, width:($(eImage).offsetWidth), height:($(eImage).offsetHeight)};
            $(eImage).setStyle({display:'block',
                                opacity:'1',
                                height:'1px',
                                width:($(eImage).offsetWidth-1)+'px'}).transBringToFront(); // this is a must for the blinddown effect
            g_eOldImage = $(this.m_eCurrent);
            $(eImage).morph('height:'+l_oTargetDim.height+'px;width:'+l_oTargetDim.width+'px;top:'+l_oTargetDim.top+'px;left:'+l_oTargetDim.left+'px', {duration:1, afterFinish : function() { g_eOldImage.remove()}});
            break;
        case 'grow':
            $(eImage).setStyle({display:'none', opacity:'1'}).transBringToFront();
            $(this.m_eCurrent).transSendToBack();
            new Effect.Grow( eImage, { duration: 1, direction:'center' } );
            new Effect.Appear( this.m_eCurrent, { duration: 1, afterFinish: this._removeImage } );
            break;
        case 'shrink':
            $(this.m_eCurrent).transBringToFront();
            $(eImage).transSendToBack();
            $(eImage).setStyle({display:'block', opacity:'1'});
            g_eOldImage = $(this.m_eCurrent);
            new Effect.Shrink( this.m_eCurrent, { duration: 1, afterFinish : function() { g_eOldImage.remove(); }} ); // bug in scriptaculous? When called _removedImage on callback the element is not passed
            break;
        case 'switchoff':
            $(this.m_eCurrent).setStyle({display:'block', opacity:'1'}).transBringToFront();
            $(eImage).setStyle({display:'block', opacity:'1'}).transSendToBack();
            l_oTargetDim = {left:0,top:$(eImage).transGetCenterHeight(), width:($(eImage).offsetWidth-1), height:0};
            $(this.m_eCurrent).morph('height:'+l_oTargetDim.height+'px;width:'+l_oTargetDim.width+'px;top:'+l_oTargetDim.top+'px;left:'+l_oTargetDim.left+'px', {duration:1, afterFinish:this._removeImage});
            break;
        case 'slidedown':
            $(this.m_eCurrent).setStyle({display:'block', opacity:'1'}).transBringToFront();
            $(eImage).setStyle({top:'-'+eImage.transGetHeight()+'px', display:'block', opacity:'1'});
            $(eImage).morph('top:0px', {duration:1});
            $(this.m_eCurrent).morph('top:'+eImage.transGetHeight()+'px', {duration:1, afterFinish : this._removeImage});
            break;
        case 'slideright':
            $(this.m_eCurrent).setStyle({display:'block', opacity:'1'}).transBringToFront();
            $(eImage).setStyle({left:'-'+eImage.transGetWidth()+'px', display:'block', opacity:'1'});
            $(eImage).morph('left:0px', {duration:1});
            $(this.m_eCurrent).morph('left:'+eImage.transGetWidth()+'px', {duration:1, afterFinish : this._removeImage});
            break;
        }
        this.m_eCurrent = eImage;
        this.next_slide();
    },

    _removeImage: function( p_oObj ) {
        p_oObj.element.remove();
    },
    stop_slide_show:function() {
        this.slideshow = false;
        this.toggle_control_visibility();
        this.stop_all_executions();
    },
    start_slide_show:function() {
        this.slideshow = true;
        if ($$('.edit_mode').length > 0) {
            this.preload_images();
        }
        this.toggle_control_visibility();
        this.render_next_slide();
    },
    pe_queue:$A([]),
    stop_all_executions:function () {
        this.pe_queue.each(function(pe) { pe.stop(); });
        this.pe_queue.clear();
    },
    next_slide:function() {
        if (!this.slideshow) return;
        if (this.slideshow_current_index >= (this.number_of_slides_to_show - 1)) {
            this.slideshow_current_index = -1;
            this.stop_slide_show();
            return;
        }
        var cur_image = this.current_slide_image_obj();
        var duration = cur_image.duration;
        var thisinstance = this;

        var pe = new PeriodicalExecuter(function(pe) {
                thisinstance.render_next_slide();
                pe.stop();
        }, duration);
        this.pe_queue.push(pe);
    },
    render_next_slide:function() {
        if (!this.slideshow) return;
        this.update_slideshow_index();
        this.loadImage(this.current_slide_image_obj());
    },
    current_slide_image_obj:function() {
        return this.preloads[this.slideshow_current_index % this.number_of_slides];
    },
    update_slideshow_index:function() {
        this.slideshow_current_index = this.slideshow_current_index + 1;
    }


}

