/*
Created By: Chris Campbell
Website: http://particletree.com
Date: 2/1/2006

Inspired by the lightbox implementation found at http://www.huddletogether.com/projects/lightbox/
*/

/*
 * Functionality has been extended and code modified quite a bit to be fit for purpose. KGK Jan 2008
 */

var LightboxBase =
{
    yPos : 0,
    xPos : 0,
    cache : [],
    contentElementId : null,

    initialize : function (activatorElement) {
        this.activatorElement = activatorElement;
        this.contentUri = activatorElement.href;
        
        Event.observe(activatorElement, 'click', function (event) {
                this.activate(); event.stop();
            }.bindAsEventListener(this)
        );
    },

    init : function () {
       this.initMarkup();
        lboxElements = $$('.lbOn');
        lboxElements.each(function(el) {
                var lbox = new Lightbox(el);
                
                if (lbox && el.hasClassName('lbOnAutoLoad')) {
                    lbox.activate();
                }
            }, LightboxBase
        );
    },

    // Add in markup necessary to make this work. Basically two divs:
    // Overlay holds the shadow
    // Lightbox is the centered square that the content is put into.
    initMarkup : function () {
        var bodyElement = Element.select(document, 'body').first();
        var lb = document.createElement('div');
        lb.id = 'lightbox';
        lb.className = 'loading';
        this.setLoadingMessage(lb);
        
        var overlay = document.createElement('div');
        overlay.id = 'overlay';
        
        bodyElement.appendChild(lb);
        bodyElement.appendChild(overlay);
    },
    
    // Turn everything on - mainly the IE fixes
    activate : function () {
        // @todo Prototype.Browser is not an officially exposed property of Prototype
        if (Prototype.Browser.IE) {
            this.getScroll();
            this.prepareIE('100%', 'hidden');
            this.setScroll(0,0);
            this.hideSelects('hidden');
        }
        this.displayLightbox('block');
    },
    
    // Ie requires height to 100% and overflow hidden or else you can scroll down past the lightbox
    prepareIE : function (height, overflow) {
        bod = document.getElementsByTagName('body')[0];
        bod.style.height = height;
        bod.style.overflow = overflow;
  
        htm = document.getElementsByTagName('html')[0];
        htm.style.height = height;
        htm.style.overflow = overflow; 
    },
    
    // In IE, select elements hover on top of the lightbox
    hideSelects: function (visibility) {
        selects = $$('select');
        selects.each(function (select) {
                select.style.visibility = visibility;
            }
        );
    },
    
    // Taken from lightbox implementation found at http://www.huddletogether.com/projects/lightbox/
    getScroll : function () {
        if (self.pageYOffset) {
            this.yPos = self.pageYOffset;
        } else if (document.documentElement && document.documentElement.scrollTop) {
            this.yPos = document.documentElement.scrollTop; 
        } else if (document.body) {
            this.yPos = document.body.scrollTop;
        }
    },
    
    setScroll : function (x, y) {
        window.scrollTo(x, y); 
    },
    
    displayLightbox : function (display) {
        var overlay = $('overlay');
        var lightbox = $('lightbox');
        
        overlay.style.display = display;
        lightbox.style.display = display;
        
        // Close the lightbox if the user clicks outside it or hits the ESC key.
        Event.observe('overlay', 'click', this.deactivate.bindAsEventListener(this));
        Event.observe(document, 'keydown', this.escKeyClose.bindAsEventListener(this));
        
        if ('none' == display) { return; }
        
       // @todo This fails if the lightbox activator element is clicked again after the lightbox has just been closed.
       // Commented out for now until clarified.
       // this.setLoadingMessage(lightbox);
        
        if (! this.activatorElement || ! this.activatorElement.hasClassName('lbStatic')) {
            this.loadInfo();
            return;
        }
        
        var className = this.activatorElement.classNames().grep(/^lbContent_\w+/).first();
        if (className) {
            this.contentElementId = className.gsub(/^[^_]+_/, '');
            this.insertStatic($(this.contentElementId));
        }
    },
    
    setLoadingMessage : function(lightboxElement)
    {
        var innerHtml = '<div style="color: #fff;" id="lbLoadMessage">Loading...</div>';
        messageContainer = $('lbPageLoadingMessageContainer');
        if (messageContainer) {
            innerHtml = '<div id="lbLoadMessage">'
                      +     messageContainer.innerHTML +
                      + '</div>';
        }

        lightboxElement.innerHTML = innerHtml;
    },

    // Begin Ajax request based off of the href of the clicked linked
    loadInfo : function () {
        var myAjax = new Ajax.Request(
        this.contentUri,
        {method: 'post', parameters: '', onComplete: this.processInfo.bindAsEventListener(this)}
        );
    },
    
    // Display Ajax response
    processInfo : function (response) {
        if ($('lbContent')) {
           Element.remove($('lbContent'));
        }
    
        // Evaluates responseText if the X-EvalJS header is set
        if (response.getHeader('X-EvalJS') == 'run') {
            eval(response.responseText);
            return;
        }
     
        info = '<div id="lbContent">' + response.responseText + "</div>";
        // @todo implement caching
        // this.cache.push(info);
        $('lbLoadMessage').insert({before : info});
        $('lightbox').className = 'done';
        this.actions();
        
        lightboxPostActions.registerBehaviours();
    },
    
    // Search through new links within the lightbox, and attach click event
    actions : function () {
        var lbActions =  $('lightbox').select('.lbAction');

        // @todo Sort out context binding and use the commented-out version instead.
        /*lbActions.each(function (action) {
                Event.observe(action, 'click', function(event) { event.stop(); Lightbox[action.rel]; }); 
            }
        );*/
        
        for(i = 0; i < lbActions.length; i++) {
            Event.observe(lbActions[i], 'click', this[lbActions[i].rel].bindAsEventListener(this), false);
            lbActions[i].onclick = function(){return false;};
        }
    },
    
    // Example of creating your own functionality once lightbox is initiated
    insert : function (e) {
       link = Event.element(e);
       // The link may contain a <span> tag, so we might need to get the parent node
       if (typeof(link.href) == 'undefined') {
           link = Event.element(e).parentNode;
       }
       
       // Do NOT attempt to fetch new content if no URI is found
       if (typeof(link.href) == 'undefined') {
           return;
       }
       
       var myAjax = new Ajax.Request(
              link.href,
              {method: 'post', parameters: '', onComplete: this.processInfo.bindAsEventListener(this)}
       );
    },
    
    insertStatic : function (contentElement) {
        var lbContent = $('lbContent');
        if (! lbContent) {
            lbContent = document.createElement('div');
            lbContent.id = 'lbContent';
        }
        
        Element.update(lbContent, contentElement);
        
        // @todo implement caching
        // this.cache.push(lbContent);
        $('lbLoadMessage').insert({before : lbContent});
        
        $(contentElement.id).show();
        $('lightbox').className = 'done';
        this.actions();
    },
    
    // Expects a link (URL) and json-encoded object
    insertWithParameters : function (link, parameters) {
       //Element.remove($('lbContent'));
     
       var myAjax = new Ajax.Request(
              link,
              {method: 'post', 'parameters': parameters, onComplete: this.processInfo.bindAsEventListener(this)}
       );
       
    },
    
    // Example of creating your own functionality once lightbox is initiated
    deactivate : function () {
        var lbContent = $('lbContent');
    
        if ((this.activatorElement && ! this.activatorElement.hasClassName('lbStatic')) && lbContent) {
            Element.remove(lbContent);
        }
        // @todo Prototype.Browser is not an officially exposed property of Prototype
        if (Prototype.Browser.IE) {
            this.setScroll(0,this.yPos);
            this.prepareIE('auto', 'auto');
            this.hideSelects('visible');
        }
        
        this.displayLightbox('none');
    },
    
    reload : function () {
        // Moves hidden DIV inside the lightbox
        $('lbPageReloadMessageContainer').style.display = 'block';
        Element.insert($('lbLoadMessage'), {before: $('lbPageReloadMessageContainer')});
        $('lightbox').className = 'done';
        
        // Refreshes the page, after stripping off certain parameters
        winLocation = new String(window.location);
        params = $H(winLocation.toQueryParams());
        params.unset('show-comments');
        
        qs = params.toQueryString();
        winLocation = winLocation.sub(/\?.*$/,'');
        if (qs != '') {
            winLocation + '?' + qs;
        }
        window.location = winLocation;
    },
    
    escKeyClose : function (event) {
        var keyCode = event.which;
        if (! keyCode) { keyCode = event.keyCode; }
        if (keyCode === Event.KEY_ESC) {
            this.deactivate(); 
        }
    }
}
var Lightbox = Class.create(LightboxBase);

// Onload, make all links that need to trigger a lightbox active
Event.observe(window, 'load', LightboxBase.init.bindAsEventListener(LightboxBase));

