Lightbox = {
    iframeWidth: 1024,
    iframeHeight: 768,
    containerMinWidth: 320,
    containerMinHeight: 240,
    containerGaps: [42, 20, 48, 20],

    descriptions: [],
    items: [],
    pointer: null,
    status: 'closed',
    preloaderImages: [],
    preloaderStates: [],
    
    
    overlayElm: null,
    containerElm: null,
    nextElm: null,
    prevElm: null,
    closeElm: null,
    descriptionElm: null,
    viewElm: null,
    
    overlayTransition: null,
    containerTransition: null,
    
    initialize: function() {
        $$('a[rel]').each(function(elm){
            var rel = elm.get('rel');
            
            if(matches = /(^|\b)lightbox\[([^\]]+)\](\b|$)/i.exec(rel)) {
                elm.addEvent('click', function(ev){
                     return Lightbox.open(elm.href, elm.title, matches[2]);
                });    
            } else if(matches = /(^|\b)lightbox(\b|$)/i.exec(rel)) {
                elm.addEvent('click', function(ev){
                    return Lightbox.open(elm.href, elm.title, null);
                });   
            }
        });
        
        window.addEvent('keyup', function(ev){
            var success = false;
        
            if(ev.key == 'esc') {
                success = Lightbox.close();
            } else if(ev.key == 'right' || ev.key == 'down') {
                success = Lightbox.next();
            } else if(ev.key == 'left' || ev.key == 'up') {
                success = Lightbox.prev();
            }
            
            if(success) {
                ev.preventDefault();
                ev.stopPropagation();
            }
            
            return !success;
        });
        window.addEvent('resize', Lightbox.fixOverlay);
    },
    
    open: function(item, description, collection) { 
        if(Lightbox.status == 'closed') {
            Lightbox.containerElm = new Element('div', {'class': 'lightbox-container'});
            Lightbox.overlayElm = new Element('div', {'class': 'lightbox-overlay'});
            Lightbox.nextElm = new Element('a', {'class': 'lightbox-next'});
            Lightbox.prevElm = new Element('a', {'class': 'lightbox-prev'});
            Lightbox.closeElm = new Element('a', {'class': 'lightbox-close'});
            Lightbox.descriptionElm = new Element('div', {'class': 'lightbox-description'});
            
            Lightbox.containerElm.adopt(Lightbox.nextElm);
            Lightbox.containerElm.adopt(Lightbox.prevElm);
            Lightbox.containerElm.adopt(Lightbox.closeElm);
            Lightbox.containerElm.adopt(Lightbox.descriptionElm);
    
            
            Lightbox.overlayElm.addEvent('click', function(){
                Lightbox.close();
                return false;  
            });
            
            Lightbox.closeElm.addEvent('click', function(){
                Lightbox.close();
                return false;  
            });
            
            Lightbox.nextElm.addEvent('click', function(){
                Lightbox.next();
                return false;  
            });
            
            Lightbox.prevElm.addEvent('click', function(){
                Lightbox.prev();
                return false;  
            });
           
            
            if(collection != null) {
                Lightbox.descriptions = [];
                Lightbox.items = [];
                Lightbox.preloaderImages = [];
                Lightbox.preloaderStates = [];
                
                $$('a[rel]').each(function(elm) {
                    var rel = elm.get('rel');
                    
                    if((matches = /(^|\b)lightbox\[([^\]]+)\](\b|$)/i.exec(rel)) && matches[2] == collection) {
                        Lightbox.descriptions.push(elm.title);
                        Lightbox.items.push(elm.href);
                        Lightbox.preloaderImages.push(null);
                        Lightbox.preloaderStates.push('none');
                    }
                    
                });
            } else {
                Lightbox.descriptions = [description];
                Lightbox.items = [item];
                Lightbox.preloaderImages = [null];
                Lightbox.preloaderStates = ['none'];
            }
            
            
            Lightbox.pointer = Lightbox.items.indexOf(item);
            
            if(Lightbox.pointer == -1) {
                Lightbox.pointer = 0;
                
                Lightbox.items.unshift(item);
                Lightbox.descriptions.unshift(description);
            }
            
            
            Lightbox.status = 'opened';
            
           
            Lightbox.fixOverlay();
            Lightbox.resize(Lightbox.containerMinWidth, Lightbox.containerMinHeight);
            
            Lightbox.containerElm.inject(document.body);
            Lightbox.overlayElm.inject(document.body);
           
            Lightbox.select(Lightbox.pointer);
            
            return false;
        }
        
        return true;
    },
    
    itemType: function(item) {
        if(/\.(png|jpe?g|gif|bmp|ico)$/i.test(item)) {
            return 'image';
        } else if(Lightbox.extraceYoutubeCode(item) != null) {
            return 'youtube';
        } else {
            return 'iframe';
        }
    },
    
    extraceYoutubeCode: function(item) {
        if(item.indexOf('http://youtube.be/') == 0) {
            var start = 'http://youtube.be/'.length;
            var end = item.length;
        
            if((i = item.indexOf('?')) != -1) {
                end = i;
            }
            
            return item.substring(start, end);
        } else if(item.indexOf('http://www.youtube.com/watch') == 0) {
            var start = item.indexOf('v=')+2;
            var end = item.length;
            
            if((i = item.indexOf('&')) != -1) {
                end = i;
            } 
            
            return item.substring(start, end);
        }
        
        return null;
    },
    
    fixOverlay: function() {
        if(Lightbox.status == 'opened') {
            Lightbox.overlayElm.setStyle('display', 'none');
            
            var scrollSize = window.getScrollSize();
            Lightbox.overlayElm.setStyles({
                display: 'block',
                width: scrollSize.x,
                height: scrollSize.y
            });
        }
    },
    
    resize: function(width, height) {
        if(Lightbox.status == 'opened') {
            var gaps = Lightbox.containerGaps;
            var size = window.getSize();
            var scrollSize = window.getScrollSize();
            var scroll = window.getScroll();
            var scale = Math.min(1, Math.min((size.x-gaps[3]-gaps[1])/width, (size.y-gaps[0]-gaps[2])/height));
           
            var w = Math.max(width*scale, Lightbox.containerMinWidth);
            var h = Math.max(height*scale, Lightbox.containerMinHeight);
            var x = Math.max(gaps[3], Math.min(scroll.x + size.x/2 - w/2, scrollSize.x - (w + gaps[1])));
            var y = Math.max(gaps[0], Math.min(scroll.y + size.y/2 - h/2, scrollSize.y - (h + gaps[2])));
            
            Lightbox.containerElm.setStyles({
                width: w,
                height: h,
                left: x,
                top: y
            });
                
            return [w, h];
        }
        
        return [0, 0];
    },
    
    close: function() {
        if(Lightbox.status == 'opened') {
            Lightbox.containerElm.destroy();
            Lightbox.overlayElm.destroy();
            
            Lightbox.status = 'closed';
            Lightbox.clearHash();
            
            Lightbox.preloaderImages.each(function(img) {
                if(img) {
                    img.onload = img.onerror = img.onabort = function(){};
                }
            });
            
            return true;
        }
        
        return false;
    },
    
    next: function() {
        return Lightbox.select(Lightbox.pointer+1);
    },
    
    prev: function() {
        return Lightbox.select(Lightbox.pointer-1);
    },
    
    preload: function(i) {
        if(i >= 0 && i < Lightbox.items.length && Lightbox.preloaderStates[i] == 'none' && Lightbox.itemType(Lightbox.items[i]) == 'image') {
            Lightbox.preloaderStates[i] = 'loading';
            
            var im = new Image();
            
            im.onload = function() {
                Lightbox.preloaderStates[i] = 'ready';
                
                if(Lightbox.pointer == i) {
                    Lightbox.select(Lightbox.pointer)
                }
            };
            
            im.onerror = im.onabort = function() {
                Lightbox.preloaderStates[i] = 'error';
                
                if(Lightbox.pointer == i) {
                    Lightbox.select(Lightbox.pointer)
                }
            };
            
            Lightbox.preloaderImages[i] = im; 
            
            im.src = Lightbox.items[i];
        }
    },
    
    select: function(newPointer) {
        if(Lightbox.status == 'opened' && newPointer >= 0 && newPointer < Lightbox.items.length) {
            Lightbox.pointer = newPointer;
            
            if(Lightbox.collection) {
                Lightbox.setHash(Lightbox.collection + '/' + Lightbox.pointer);
            }
            
            if(Lightbox.viewElm && Lightbox.viewElm.parentNode) {
                Lightbox.viewElm.parentNode.removeChild(Lightbox.viewElm);
                Lightbox.viewElm = null;
            }
            
            var type = Lightbox.itemType(Lightbox.items[newPointer]);
            
            if(type == 'image') {
                if(Lightbox.preloaderStates[newPointer] == 'ready') {
                    var im = Lightbox.preloaderImages[newPointer];
                    
                    var size = Lightbox.resize(im.width, im.height);
                    Lightbox.viewElm = new Element('img', {
                        src: Lightbox.items[newPointer],
                        width: size[0],
                        height: size[1]
                    });
                    
                    Lightbox.viewElm.addEvent('click', function(){
                        Lightbox.next();
                        return false;  
                    });
                    
                } else if(Lightbox.preloaderStates[newPointer] == 'error') {
                    Lightbox.viewElm = new Element('div', {
                        'class': 'lightbox-error'
                    });
                    
                } else {
                    Lightbox.viewElm = new Element('div', {
                        'class': 'lightbox-loader'
                    });
                }
                
                Lightbox.containerElm.adopt(Lightbox.viewElm);
                
            } else if(type == 'iframe' || type == 'youtube') {
                Lightbox.resize(Lightbox.iframeWidth, Lightbox.iframeHeight);
            
                if(type == 'youtube') {
                    var src = 'http://www.youtube.com/embed/' + Lightbox.extraceYoutubeCode(Lightbox.items[newPointer]);    
                } else {
                    var src = Lightbox.items[newPointer];
                }
            
                Lightbox.viewElm = new Element('iframe', {
                    type: 'text/html',
                    frameborder: 0,
                    styles: {
                        width: '100%',
                        height: '100%'
                    },
                    src: src
                });
                
                Lightbox.containerElm.adopt(Lightbox.viewElm);
            } 
            
            Lightbox.descriptionElm.set('html', Lightbox.descriptions[newPointer]);
            
            
            if(newPointer+1 < Lightbox.items.length) {
                Lightbox.nextElm.set('href', Lightbox.items[newPointer+1]);
                Lightbox.nextElm.removeClass('disabled');
            } else {
                Lightbox.nextElm.erase('href');
                Lightbox.nextElm.addClass('disabled');
            }
            
            if(newPointer-1 >= 0){
                Lightbox.prevElm.set('href', Lightbox.items[newPointer-1]);
                Lightbox.prevElm.removeClass('disabled');
            } else {
                Lightbox.prevElm.erase('href');
                Lightbox.prevElm.addClass('disabled');
            }
            
            Lightbox.preload(newPointer-1);
            Lightbox.preload(newPointer);
            Lightbox.preload(newPointer+1);
            
            return true;
        }
        
        return false;
    },
};

$(document).addEvent('domready', Lightbox.initialize);
