/**
 *  Lightbox Script
 *
 *  required files:
 *      lightbox.css
 *
 *
 * v0.5 - added onShow and onHide event functions
 * v0.6 - new get and setDefaults global methods
 *      - hideReload config option
 *      - resizeToContent config
 * v0.61 - fix - resizeToContent now works with remote content
 * v0.7  - close and reload tool styles moved to stylesheet
 *       - tool layout change
 *       - 'hideClose' conf added to hide the close tool
 *       - 'animation' conf added to turn off animation
 * v0.8  - contentEl is now returned to its original location and hidden, rather than removed
 *       - Escape key now closes the lightbox
 *
 *
 * @version 0.8
 * @author Kevin Hamilton (kevin@3wi.se)
 * @copyright 2010 3wise Internet Solutions
 *
 */
var Lightbox = Class.create({
    initialize: function(conf) {
        Object.extend(this, conf || {});
        if(this.id && $(this.id)) {
            this.element = $(this.id);
        }

        var ua = navigator.userAgent.toLowerCase(),
        check = function(r){
            return r.test(ua);
        };

        this.isOpera =    check(/opera/);
        this.isIE =      !this.isOpera && check(/msie/);
        this.isTrident =  this.isIE && check(/trident\//);
        this.isIE8asIE7 = this.isIE && this.isTrident  && check(/msie 7/);
        this.isIE7 =      this.isIE && !this.isTrident && check(/msie 7/);
        this.isIE6 =      this.isIE && check(/msie 6/);

        if(this.resizeToContent) {
            this.height = this.height || 100;
            this.width = this.width || 100;
        }
        else {
            this.height = this.height || 400;
            this.width = this.width || 400;
        }

        if(!this.url) {
            this.hideReload = true;
        }

        Lightbox.register(this);


    },
    id:'',
    width: null,
    height: null,
    cb: Prototype.emptyFunction,
    onShow: Prototype.emptyFunction,
    onHide: Prototype.emptyFunction,
    maskColour:'#000000',
    maskOpacity: 0.5,
    fadeDuration: 0.5,
    url: null,
    resizeToContent: false,
    hideReload: false,
    hideClose: false,
    reloadImage:'/Scripts/Lightbox/refresh-button.png',
    closeImage:'/Scripts/Lightbox/cross-button.png',
    closeImageStyles:{},

    /**
     * Use Animation?
     * values can be:
     *  - all, hide, show, none
     *
     *  defaults to all
     */
    animation: 'all',

    show: function() {
        if(this.url) {
            this.showUrl(this.url);
        }
        else if($(this.contentEl)) {
            if(!this.element) {
                this.contentEl = $(this.contentEl);
                this.render();

                //- save where we got the el from
                this.contentElNext = this.contentEl.next();
                this.contentElParent = this.contentEl.up();
                this.elementInner.insert( this.contentEl );
                this.contentEl.show();
            }

            this.setPosition();
            this.activate();
        }
    },

    /**
     *
     *  @example lightbox.showUrl('/site_includes/newsletter-signup.php');
     *  @param    url    The URL to load into the lightbox
     */
    showUrl: function(url) {
        if(!this.element) {
            this.render();
        }
        this.setPosition();
        this.load(url, this.activate);
    },
    load: function(url, callback, scope) {
        this.lastUrl = url;
//        new Ajax.Updater(this.elementInner, url, {
//            evalScripts: true,
//            method: 'GET',
//            onComplete: typeof callback == "function" ? callback.bind(scope || this) : Prototype.emptyFunction
//        });
        new Ajax.Request(url, {
            evalScripts: true,
            method: 'GET',
            onComplete: function(t) {
                t.responseText.evalScripts();
                this.elementInner.update(t.responseText);
                if(this.resizeToContent) {
                    var l = this.elementInner.childElements().length;
                    if(l == 1) {
                        this.contentEl = this.elementInner.down();
                    }
                    else {
                        alert('resizeToContent feature can only resize to 1 parent element. '+l+' were found');
                    }
                }
                if(typeof callback == "function") {
                    callback.call(scope || this);
                }
            }.bind(this)
        });
    },
    reload: function() {
        if(this.lastUrl) {
            this.load(this.lastUrl, function() {
                this.cb();
                if(this.resizeToContent) {
                    this.doResizeToContent();
                }
            });
        }
    },
    activate: function() {
        this.maskPage(function() {
            if(this.contentEl && this.resizeToContent) {
                if(!this.isIE) {
                    this.contentEl.setOpacity(0);
                }
                else {
                    this.contentEl.setStyle({visibility:'hidden'});
                }
            }

            var afterFinish = function() {
                    this.cb();
                    this.onShow();
                    if(this.resizeToContent) {
                        this.doResizeToContent();
                    }
                    else {
                        //- but not real IE7 - shadow slows it down badly
                        if(this.isTrident || this.isIE8 || this.isIE8asIE7 ) {
                            this.renderShadow();
                            if(this.elementShadow) {
                                this.elementShadow.show();
                                this.setPosition();
                            }
                        }
                    }

                    document.observe("keypress", this.onEsc.bindAsEventListener(this));

//                    Event.observe(window, 'scroll', function(){
//                        this.setPosition();
//                    }.bind(this));
            }


            if(['all','show'].indexOf(this.animation) >= 0) {
                this.element.appear({
                    duration: this.fadeDuration,
                    afterFinish: afterFinish.bind(this)
            });
            }
            else {
                this.element.show();
                afterFinish.call(this);
            }


        }.bind(this));
    },
    hide: function(){
        document.stopObserving("keypress");
        if(this.element) {
//            this.elementInner.setStyle({
//                overflow:'auto'
//            });

            var afterFinish = function() {
                    this.onHide();
                    this.removeMask();

                    //- return any content el to its original position
                    if(this.contentEl && this.contentElParent) {
                        this.contentEl.hide();
                        if(this.contentElNext) {
                            this.contentElNext.insert({
                                before: this.contentEl
                            });
                        }
                        else {
                            this.contentElParent.insert(this.contentEl);
                        }
                        delete this.contentElParent;
                        delete this.contentElNext;
                    }

                    if(this.elementClose) this.elementClose.remove();
                    if(this.elementReload) this.elementReload.remove();
                    if(this.elementShadow) this.elementShadow.remove();
                    if(this.element) this.element.remove();
                    this.element = this.elementShadow = this.elementInner = this.elementClose = this.elementReload = null;
            }

            if(['all','hide'].indexOf(this.animation) >= 0) {
                this.element.fade({
                    duration: this.fadeDuration,
                    afterFinish: afterFinish.bind(this)
            });
            }
            else {
                afterFinish.call(this);
            }
            if(this.elementShadow) {
                this.elementShadow.hide();
            }
        }
        else {
            this.removeMask();
        }

//        Event.stopObserving(window, 'scroll');

    },
    visible: function() {
        return this.element && this.element.visible();
    },
    maskPage: function(callback) {

        var mask = $(this.id + '-mask');

        if (!mask) {
            var tmp = $(window.opera && parseFloat(window.opera.version()) < 9.5 ? document.documentElement : document.body);

            var padding = parseInt(tmp.getStyle('padding-bottom')) + parseInt(tmp.getStyle('padding-top'));

            mask = new Element('DIV');
            mask.id = this.id + '-mask';
            mask.hide();
            mask.addClassName('page-mask');
            mask.setStyle({
                width:  tmp.clientWidth + 'px',
                height: (tmp.clientHeight+padding) + 'px',
                backgroundColor:this.maskColour
            });

            $(document.body).insert(mask);

        }

        if(['all','show'].indexOf(this.animation) >= 0) {
        mask.appear({
            from:0,
            duration: this.fadeDuration,
            to:this.maskOpacity,
            afterFinish: callback || Prototype.emptyFunction
        });
        }
        else {
            mask.show();
            mask.setOpacity(this.maskOpacity);
            (callback || Prototype.emptyFunction)();
        }


    },
    removeMask: function() {
        var mask = $(this.id + '-mask');
        if (mask) {
            if(['all','hide'].indexOf(this.animation) >= 0) {
            mask.fade({
                from: this.maskOpacity,
                duration: 0.5,
                to: 0,
                afterFinish: function() {
                    mask.remove();
                }
            });
        }
            else {
                mask.remove();
            }
        }
    },
    setPosition: function() {
//        var viewport_width = document.viewport.getWidth();
        var viewport_height = document.viewport.getHeight();
        var vpscroll_top = this.element.getStyle('position') == 'fixed' ? 0 : document.viewport.getScrollOffsets()['top'];
        var new_top = ((viewport_height - this.height) / 2) + vpscroll_top;

        this.element.setStyle({
            marginLeft: '-' + Math.round(this.width / 2) + 'px',
            left: '50%',
            top: new_top + 'px'
        });


        if(this.elementShadow) {

//            this.elementShadow.addClassName('x-shadow');
            var width = Math.round(this.element.clientWidth);//+(this.shadowWidth*2);
            var height = Math.round(this.element.clientHeight);//+(this.shadowWidth*2);
//            width += parseInt(this.elementInner.getStyle('padding-left')) + parseInt(this.elementInner.getStyle('padding-right'))

//            width += this.shadowWidth;

//            alert(width);

//            if(this.isIE8) {
//                width += 8;
//            }

            this.elementShadow.select('.xstc, .xsmc, .xsbc').invoke('setStyle', {width: (width)+'px'});
            this.elementShadow.select('.xsc').invoke('setStyle', {height: (height)+'px'});

            this.elementShadow.setStyle({
                marginLeft: '-' + (Math.round((width)/2)-(this.shadowWidth+4)) + 'px',
                left: '50%',
//                width: 'auto',
                top: Math.round(new_top-(4)) + 'px'
            });
        }

    },
    render: function() {

        this.element = new Element('DIV',{
            id: this.id || ''
        });
        this.id = this.element.identify();

        this.element.addClassName('lightbox');

        this.element.setStyle({
            position: this.isIE6 ? 'absolute' : 'fixed',
            display: 'none'
//            height: this.height + 'px',
//            width: this.width + 'px'
        });

        this.elementInner = new Element('DIV', {
            id: this.id+'-inner'
        });
        this.elementInner.setStyle({
            position:'relative',
            overflow: 'hidden', //Prototype.Browser.Opera ? 'hidden' : 'auto',
            width: (this.width || 100) + 'px',
            height: (this.height || 100) + 'px'
        });
        this.elementInner.addClassName('lightbox-inner');

        this.element.insert(this.elementInner);


        this.elementTools = new Element('DIV', {
            id: this.id + '-tools'
        });
        this.elementTools.addClassName('lightbox-tools');



        if(!this.hideClose) {
        this.elementClose = new Element('DIV', {
            id: this.id + '-close',
            title: 'Close'
        });
            this.elementClose.addClassName('lightbox-close');
            var closeStyles = {};
            if(this.closeImage) {
                closeStyles.backgroundImage='url('+this.closeImage+')';
        }
        Object.extend(closeStyles, this.closeImageStyles);
        this.elementClose.setStyle(closeStyles);
        this.elementClose.observe('click', function() {
            this.hide();
        }.bind(this));

        this.elementClose.update('&nbsp;');
            this.elementTools.insert(this.elementClose);
        }
        if(!this.hideReload) {
            this.elementReload = new Element('DIV', {
                id: this.id + '-reload',
                title: 'Reload'
            });
            this.elementReload.addClassName('lightbox-reload');
            var reloadStyles = {}
            if(this.reloadImage) {
                reloadStyles.backgroundImage='url('+this.reloadImage+')';
            }
            Object.extend(reloadStyles, this.closeImageStyles);

            this.elementReload.setStyle(reloadStyles);
            this.elementReload.observe('click', function() {
                this.reload();
            }.bind(this));

            this.elementReload.update('&nbsp;');
            this.elementTools.insert(this.elementReload);

        }

        this.element.insert(this.elementTools);

        $(document.body).insert(this.element);
    },
    shadowWidth: 6,
    renderShadow: function() {
        if(this.elementShadow) return;
        return; //- too buggy to use;
        //<div class="x-shadow" id="'+this.id+'-shadow" style="">

        var w = this.width + 1;
        var h = this.height + 1;

        var width = w + (this.shadowWidth * 2);
        var height = h + (this.shadowWidth * 2);

        this.elementShadow = new Element('div', {
            id: this.id + '-shadow'
        });
        this.elementShadow.addClassName('x-shadow');


        this.elementShadow.setStyle({
            position: this.isIE6 ? 'absolute' : 'fixed',
            zIndex: '1000',
            left: '10px',
            top: '10px',
//            width: width+'px',
//            height: height+'px',
            display: 'none'
        });

        var html = '<div class="xst">'
                 + '    <div class="xstl"></div><div class="xstc" style=""></div><div class="xstr"></div>'
                 + '</div>'
                 + '<div class="xsc">'
                 + '    <div class="xsml"></div><div class="xsmc" style=""></div><div class="xsmr"></div>'
                 + '</div>'
                 + '<div class="xsb">'
                 + '    <div class="xsbl"></div><div class="xsbc" style=""></div><div class="xsbr"></div>'
                 + '</div>';

         this.elementShadow.update(html);

//         alert(this instanceof Lightbox);

         $(document.body).insert(this.elementShadow);
    },

    doResizeToContent: function() {
        var contentHeight = this.contentEl.clientHeight;
        var contentWidth = this.contentEl.clientWidth;
        var innerHeight = this.elementInner.clientHeight;
        var innerWidth = this.elementInner.clientWidth;

        var padding = (parseInt(this.elementInner.getStyle('padding-top')) + parseInt(this.elementInner.getStyle('padding-top')));
        var margins = (parseInt(this.contentEl.getStyle('margin-top')) + parseInt(this.contentEl.getStyle('margin-top')));

        var outerHeight = contentHeight + padding;// + margins;

        var outerTop = parseInt(this.element.getStyle('top'));
        var newTop = outerTop - ((outerHeight - innerHeight) / 2);
        var newMarginLeft = -parseInt( contentWidth/2 );
//                        console.log(newMarginLeft);

//                        this.element.morph();

        this.elementInner.morph('height:' + contentHeight + 'px; width:' + contentWidth + 'px', {
            duration: 0.5
        });
        this.element.morph('height:'+outerHeight + 'px; top:' + newTop + 'px; margin-left:' + newMarginLeft + 'px', {
            duration: 0.5,
            afterFinish: function() {

                if(!this.isIE) {
                    this.contentEl.appear({duration:0.3});
                }
                else {
                    this.contentEl.setStyle({visibility:'visible'});
                }
                if(this.isTrident || this.isIE8 || this.isIE8asIE7 ) {
//                    this.renderShadow();
//                    if(this.elementShadow) {
//                        this.elementShadow.show();
//                        this.setPosition();
//                    }
                }
            }.bind(this)
        });
    },

    onEsc: function(e) {
        if(e.keyCode == Event.KEY_ESC) {
            this.hide();
        }
    }
});


Object.extend(Lightbox, {
    boxes: [],
    register: function(lb) {
        Lightbox.boxes.push(lb);
    },
    close: function() {
        Lightbox.boxes.each(function(lb) {
            if(lb.visible()) {
                lb.hide();
            }
        });
    },
    get: function(id) {
        var lb;
        Lightbox.boxes.each(function(o) {
            if(o.id == id) {
                lb = o;
                throw $break;
            }
        });
        return lb;
    },
    setDefaults: function(o) {
        Object.extend(Lightbox.prototype, o || {});
    }
});
