/*
    Slimbox (Extended Version 1.3.1, 2007-02-21)
    by Yukio Arita (http://homepage.mac.com/yukikun/software/slimbox_ex/)
    -   Support to show external content using iframe.
    -   Support to set content size. You can add width/height parameters 
        in rev attribute of the anchor url.
        ex1) <a href="image.jpg" rev="width=50%, height=50%" rel="lightbox">
                <img src="image_thumb.jpg" alt="image"></a>
        ex2) <a href="text.html" rev="width=500, height=300" rel="lightbox">
                some text here</a>
    -   Some rendering problem with IE6 is fixed. Now you can use Slimbox in 
        valid XHTML document with XML prolog.
    - Of course, license is same as original.

    Based on:
    Slimbox v1.3 - The ultimate lightweight Lightbox clone
    by Christophe Beyls (http://www.digitalia.be) - MIT-style license.
    Inspired by the original Lightbox v2 by Lokesh Dhakar.
*/

var Lightbox = {
    init: function(options){
        this.options = Object.extend({
            resizeDuration: 350,
            resizeTransition: Fx.Transitions.sineInOut,
            initialWidth: 250,
            initialHeight: 250,
            animateCaption: true,
            defaultIframeWidth : 500, 
            defaultIframeHeight: 300,
            scrollingIFrame: "auto",
            clickOutside: false,
            onClose: null,
            onSave: null,
            waitForLoad: false
        }, options || {});

        // IE 6 - XML prolog problem
        if(window.ie6 && document.compatMode=="BackCompat"){
            this.options.animateCaption = false;
        }

        this.anchors = [];
        $each(document.links, function(el){
            if (el.rel && el.rel.test(/^lightbox/i)){
                el.onclick = this.click.pass(el, this);
                this.anchors.push(el);
            }
        }, this);
        this.eventKeyDown = this.keyboardListener.bindAsEventListener(this);
        this.eventPosition = this.position.bind(this);

        /*  Build float panel
            <div id="lbOverlay"></div>
            <div id="lbCenter">
                <div id="lbCanvas">
                    <!-- img or iframe element is inserted here -->
                </div>
            </div>
            <div id="lbBottomContainer">
                <div id="lbBottom">
                    <a id="lbCloseLink"></a>
                    <div id="lbCaption"></div>
                    <div id="lbNumber"></div>
                    <div style="clear:both;"></div>
                </div>
            </div>
        */

        this.overlay = new Element('div').setProperty('id', 'lbOverlay').injectInside(document.body);

        this.center = new Element('div').setProperty('id', 'lbCenter').setStyles({width: this.options.initialWidth+'px', height: this.options.initialHeight+'px', marginLeft: '-'+(this.options.initialWidth/2)+'px', display: 'none'}).injectInside(document.body);
        this.canvas = new Element('div').setProperty('id', 'lbCanvas').injectInside(this.center);

        this.bottomContainer = new Element('div').setProperty('id', 'lbBottomContainer').setStyle('display', 'none').injectInside(document.body);
        this.bottom = new Element('div').setProperty('id', 'lbBottom').injectInside(this.bottomContainer);
        this.buttons = [];
        new Element('div').setProperties({id: 'lbCloseLink'}).injectInside(this.bottom).onclick = this.close.bind(this);
        if( this.options.onSave )
        {
            this.setButton('Save', this.options.onSave );
        }
        if( this.options.clickOutside ) 
        { 
            this.overlay.onclick = this.close.bind(this); 
        }
        else
        {
            this.overlay.setStyle('cursor', 'default');
        }
        this.caption = new Element('div').setProperty('id', 'lbCaption').injectInside(this.bottom);
        this.number = new Element('div').setProperty('id', 'lbNumber').injectInside(this.bottom);
        new Element('div').setStyle('clear', 'both').injectInside(this.bottom);

        /* Build effects */
        var nextEffect = this.nextEffect.bind(this);
        this.fx = {
            overlay: this.overlay.effect('opacity', {duration: 500}).hide(),
            resizeCenter: this.center.effects({duration: this.options.resizeDuration, transition: this.options.resizeTransition, onComplete: nextEffect}),
            image: this.canvas.effect('opacity', {duration: 500, onComplete: nextEffect}),
            bottom: this.bottomContainer.effect('height', {duration: 400, onComplete: nextEffect})
        };

        this.preloadPrev = new Image();
        this.preloadNext = new Image();
    },

    click: function(link){
        if (link.rel.length == 8) return this.show(link.href, link.title, link.rev);

        var j, itemNumber, items = [];
        this.anchors.each(function(el){
            if (el.rel == link.rel){
                for (j = 0; j < items.length; j++) if(items[j][0] == el.href && items[j][2] == el.rev) break;
                if (j == items.length){
                    items.push([el.href, el.title, el.rev]);
                    if (el.href == link.href && el.rev == link.rev) itemNumber = j;
                }
            }
        }, this);
        return this.open(items, itemNumber);
    },

    show: function(url, title, rev){
        return this.open([[url, title, rev]], 0);
    },

    setOnSave: function( in_onSave ){
        this.options.onSave = in_onSave;
        this.setButton('Save', this.options.onSave );
    },

    setButton: function( in_buttonName, in_buttonAction ) {
        var buttonID = 'lb'+in_buttonName+'Link';
        if( in_buttonAction )
        {
            if( $(buttonID) === null )
            {
                new Element('div').setProperties({id: buttonID}).injectAfter($('lbCloseLink')).onclick = in_buttonAction.bind(this);
            }
            else
            {
                $(buttonID).onclick = in_buttonAction.bind(this);
            }
            this.buttons.include( in_buttonName );
        }
        else if( $(buttonID) !== null )
        {
            $(buttonID).onclick = null;
            $(buttonID).remove();
            this.buttons.remove( in_buttonName );
        }
    },

    open: function(items, itemNumber){
        if( this.options.onSave ) { this.setButton( 'Save', this.options.onSave ); }
        this.items = items;
        this.position();
        this.setup(true);
        var wh = (window.getHeight() == 0) ? window.getScrollHeight() : window.getHeight();
        var st = document.body.scrollTop  || document.documentElement.scrollTop;
        this.top = st;//st + (wh / 15);
        this.center.setStyles({top: this.top+'px', display: ''});
        this.fx.overlay.start(0.8);
        return this.changeItem(itemNumber);
    },

    position: function(){
        //IE6 - XML prolog problem.
        var ww = (window.getWidth() == 0) ? window.getScrollWidth()-22 : window.getWidth();
        var wh = (window.getHeight() == 0) ? window.getScrollHeight() : window.getHeight();
        var st = document.body.scrollTop  || document.documentElement.scrollTop;
        var sl = document.body.scrollLeft || document.documentElement.scrollLeft;
        this.overlay.setStyles({top: st+'px', left:'0px', height: wh+'px', width:window.getScrollWidth()+'px'});

        var newPosX = (ww/2) + sl;
        this.center.setStyles({top: st+'px', left: newPosX+'px'});

        var newBottomPosY = this.center.clientHeight + st;
        this.bottomContainer.setStyles({top: newBottomPosY+'px', left: newPosX+'px'});
    },

    setup: function(open){
        var elements = $A(document.getElementsByTagName('object'));
        if (window.ie) elements.extend(document.getElementsByTagName('select'));
        elements.each(function(el){ el.style.visibility = open ? 'hidden' : ''; });
        var fn = open ? 'addEvent' : 'removeEvent';
        window[fn]('scroll', this.eventPosition)[fn]('resize', this.eventPosition);
        document[fn]('keydown', this.eventKeyDown);
        this.step = 0;
    },

    keyboardListener: function(event){
        switch (event.keyCode){
            case 27: case 88: case 67: this.close(); break;
            case 37: case 80: this.previous(); break;   
            case 39: case 78: this.next();
        }
    },

    changeItem: function(itemNumber){
        if (this.step || (itemNumber < 0) || (itemNumber >= this.items.length)) return false;
        this.step = 1;
        this.activeItem = itemNumber;

        this.bottomContainer.style.display = 'none';
        this.fx.image.hide();
        this.center.className = 'lbLoading';

        // discard previous content by clicking
        this.removeCurrentItem();
        
        // check item type
        var url = this.items[this.activeItem][0];
        var rev = this.items[this.activeItem][2];
        
        var re_imageURL = /\.(jpe?g|png|gif|bmp)/i;
        if( url.match(re_imageURL) ) {
            this.preload = new Image(); // JavaScript native Object
            this.preload.datatype = 'image';
            this.preload.w = this.matchOrDefault(rev, new RegExp("width=(\\d+%?)", "i"), -1); //-1 if use original size.
            this.preload.h = this.matchOrDefault(rev, new RegExp("height=(\\d+%?)", "i"), -1);
            this.preload.onload = this.nextEffect.bind(this);
            this.preload.src = url;
        }else{
            this.preload = new Object ();   // JavaScript native Object
            this.preload.datatype = 'iframe';
            this.preload.w =  this.matchOrDefault(rev, new RegExp("width=(\\d+)", "i"), this.options.defaultIframeWidth);
            this.preload.h = this.matchOrDefault(rev, new RegExp("height=(\\d+)", "i"), this.options.defaultIframeHeight);
            this.preload.src = url;
            this.options.waitForLoad =  this.matchOrDefault(rev, new RegExp("waitForLoad=(\\w+)", "i"), "false").toLowerCase() === "true";
            this.nextEffect(); //asynchronous loading
        }

        return false;
    },

    nextEffect: function(){
        switch (this.step++){
        case 1:
            this.center.className = '';

            // create HTML element
            if( this.preload.datatype == 'image' ) {
                var ws = (this.preload.w == -1) ? this.preload.width.toString() : this.preload.w.toString();
                var hs = (this.preload.h == -1) ? this.preload.height.toString() : this.preload.h.toString();
                this.p_width = ( q = ws.match(/(\d+)%/) ) ? q[1] * this.preload.width * 0.01 : ws;
                this.p_height = ( q = hs.match(/(\d+)%/) ) ? q[1] * this.preload.height * 0.01 : hs;
                new Element('img').setProperties({id: 'lbImage', src:this.preload.src, width:this.p_width, height:this.p_height}).injectInside(this.canvas);
            }else{
                this.p_width = this.preload.w;
                this.p_height = this.preload.h;
                // Safari would not update iframe content that has static id.
                this.iframeId = "lbFrame_"+new Date().getTime();
                new Element('iframe').setProperties({id: this.iframeId, width: this.p_width, height: this.p_height, frameBorder:0, scrolling:this.options.scrollingIFrame, src:this.preload.src}).injectInside(this.canvas);
            }
            this.canvas.style.width = this.bottom.style.width = this.p_width+'px';
            this.canvas.style.height = this.p_height+'px';

            this.caption.setHTML(this.items[this.activeItem][1] || '');
            this.number.setHTML( (this.items.length == 1) ? '' : 'Page ' + (this.activeItem+1) + ' of ' + this.items.length );

            if (this.activeItem) this.preloadPrev.src = this.items[this.activeItem-1][0];
            if (this.activeItem != (this.items.length - 1)) this.preloadNext.src = this.items[this.activeItem+1][0];

            if ( this.options.waitForLoad ) break;
            this.step++;

        case 2:
            var resizeParams = new Object();
            var doResize = false;
            if (this.center.clientHeight != this.canvas.offsetHeight){
                var oh = /*(this.p_height == this.canvas.clientHeight) ?*/ this.canvas.offsetHeight;// : eval(this.p_height)+18; // fix for ie
                resizeParams.height = oh;
                doResize = true;
            }

            if (this.center.clientWidth != this.canvas.offsetWidth){
                var ow = /*(this.p_width == this.canvas.clientWidth) ?*/ this.canvas.offsetWidth;// : eval(this.p_width)+18; // fix for ie
                resizeParams.width = ow;
                resizeParams.marginLeft = -ow/2;
                doResize = true;
            }
            
            if( doResize )
            {
                this.fx.resizeCenter.start(resizeParams);
                break;
            }
            
            this.step++;
        case 3:
            this.bottomContainer.setStyles({top: (this.top + this.center.clientHeight)+'px', height:'0px', marginLeft: this.center.style.marginLeft, width:this.center.style.width, display: ''});
            this.fx.image.start(1);
            break;
        case 4:
            if (this.options.animateCaption){
                // This is not smooth animation in IE 6 with XML prolog.
                // If your site is XHTML strict with XML prolog, disable this option.
                this.fx.bottom.start(0,this.bottom.offsetHeight+10);
                break;
            }
            this.bottomContainer.style.height = (this.bottom.offsetHeight+10)+'px';
        case 5:
            if(this.options.waitForLoad) this.options.waitForLoad = false;
            this.step = 0;
        }
    },

    fitContents: function(){
        var targetEl = null;
        var newHeight = this.p_height;
        var st = document.body.scrollTop  || document.documentElement.scrollTop;

        if( this.preload.datatype == 'image' ) {
            targetEl = $('lbImage');
            newHeight = targetEl.height;
        }else{
            targetEl = $(this.iframeId);
            if( targetEl.contentWindow ) {
                targetEl = targetEl.contentWindow.document;
            } else if( targetEl.contentDocument ) {
                targetEl = targetEl.contentDocument;
            }
            newHeight = targetEl.body.scrollHeight;
        }
        newHeight += 10; //fudge factor
        this.setSize( this.p_width, newHeight );
    },
    
    setSize: function( newWidth, newHeight ){
        if( newWidth === null )  newWidth  = this.p_width;
        if( newHeight === null ) newHeight = this.p_height;

        if( newWidth > window.getWidth() )
        {
            newWidth = window.getWidth() - 36;
        }

        if( newHeight > window.getHeight() )
        {
            newHeight = window.getHeight() - 36;
        }

        if( this.step == 1 && this.options.waitForLoad )
        {
            // we're mid-load, set the desitnation sizes
            this.p_width  = newWidth;
            this.p_height = newHeight;
            
            $(this.iframeId).setStyle('width', (newWidth)+"px");
            $(this.iframeId).setStyle('height',(newHeight)+"px");
        }
        else
        {
            if( newWidth != this.p_width )
            {
                this.center.setStyle('marginLeft', -((newWidth+36)/2)+"px");
                this.center.setStyle('width', (newWidth+36)+"px");
        
                this.canvas.setStyle('width', (newWidth+18)+"px");
                var iframeEl = $(this.iframeId);
                iframeEl.setStyle('width', (newWidth+18)+"px");
        
                this.bottomContainer.setStyle('marginLeft', -((newWidth+36)/2)+"px");
                this.bottomContainer.setStyle('width', (newWidth+36)+"px");
        
                this.bottom.setStyle('width', (newWidth+18)+"px");
            }

            // height
            if( newHeight != this.p_height)
            {
                var st = document.body.scrollTop  || document.documentElement.scrollTop;
                this.center.setStyle('height', (newHeight+18)+"px");
                this.canvas.setStyle('height', newHeight+"px");
                $(this.iframeId).setStyle('height', newHeight+"px");
                this.bottomContainer.setStyle('top', (st+newHeight+18)+"px");
            }
        }
    },

    clearButtons: function(){
/*
        var deleteList = this.buttons.slice();
        for( var buttonName in deleteList)
            this.setButton(buttonName,null);
*/
        this.setOnSave( null );
        this.setButton('Delete',null);
        this.setButton('Yes',null);
        this.setButton('No',null);
        this.setButton('Continue',null);
    },

    close: function(){
        this.clearButtons();        
        if (this.step < 0) return;
        this.step = -1;
        if( this.options.onClose != null) { this.options.onClose(); }
        this.removeCurrentItem();   // discard content
        for (var f in this.fx) this.fx[f].stop();
        this.center.style.display = this.bottomContainer.style.display = 'none';
        this.fx.overlay.chain(this.setup.pass(false, this)).start(0);
        return false;
    },

    removeCurrentItem: function(){
        if (this.preload){
            if( this.preload.datatype == 'image' ) {
                $('lbImage').remove();
                this.preload.onload = Class.empty;
            }else{
                $(this.iframeId).remove();
            }
            this.preload = null;
        }       
    },

    matchOrDefault: function(str, re, val){
        var hasQuery = str.match(re);
        return hasQuery ? hasQuery[1] : val;
    }
 };

window.addEvent('domready', Lightbox.init.bind(Lightbox));

