/*
 *
 *  QuickBox (Another Lightbox clone)
 *
 *  Version: 1.0
 *  Documentation: AndrewPlummer.com (http://www.andrewplummer.com/code/quickbox/)
 *  Heavily inspired by: Slimbox by Christophe Beyls (http://www.digitalia.be)
 *  Written for: Mootools 1.2
 *  License: MIT-style License
 *  
 *  Copyright (c) 2008 Andrew Plummer
 *
 *
 */


var QuickBox = new Class({


    Implements: Options,

    options: {
        resizeDuration: 600,
        resizeTransition: Fx.Transitions.Circ.easeOut,
        initialWidth: 250,
        initialHeight: 250,
        padding: 10,
        animateCaption: true,
        counter: "Image {NUM} of {TOTAL}"
    },

    initialize: function(options){
    

        this.setOptions(options);
        this.anchors = $$(document.links).filter(function(el) {
            return el.rel && el.rel.test(/^lightbox/i);
        });
        this.anchors.each(function(a){
            a.store("caption", a.get("title") || a.getElement("img").get("alt"));
            a.addEvent("click", this.open.bindWithEvent(this, a));
        }, this);
        
        
        this.overlay = new Element("div", {
            id: "qbOverlay",
            events: {
                click: this.close.bindWithEvent(this)
            }
        }).inject(document.body, "top");
        
        this.quickBox = new Element("div", {
            id: "qbBox",
            styles: {
                width: this.options.initialWidth,
                height: this.options.initialHeight,
                marginLeft: -(this.options.initialWidth/2),
                position: "absolute"
            }
        }).inject(document.body, "top");
        
        this.prevLink = new Element("a", {id: "qbPrev", href: "#"}).inject(this.quickBox);      
        this.nextLink = this.prevLink.clone().setProperty("id", "qbNext").injectInside(this.quickBox);
        
        this.stage = new Element("div", {id: "qbStage"}).inject(this.quickBox);
        
        this.prevLink.addEvent("click", this.changeImage.bindWithEvent(this, -1));
        this.nextLink.addEvent("click", this.changeImage.bindWithEvent(this, 1));

        this.bottom = new Element("div", {id: "qbBottom"}).inject(this.quickBox);
        
        this.closeButton = new Element("div", {
            id: "qbClose",
            events: {
                click: this.close.bindWithEvent(this)
            }
        }).inject(this.bottom);
        
        this.caption = new Element("div", {id: "qbCaption"}).inject(this.bottom);
        this.counter = new Element("div", {id: "qbCounter"}).inject(this.bottom);
                
        var nextEffect = this.nextEffect.bind(this);
        
        this.fx = {
            overlay: new Fx.Tween(this.overlay, {
                property: "opacity"
            }),
            resize: new Fx.Morph(this.quickBox, {
                duration: this.options.resizeDuration,
                transition: this.options.resizeTransition,
                onComplete: nextEffect
            }),
            
            show: new Fx.Tween(this.stage, {
                property: "opacity",
                onComplete: nextEffect
            }),
            bottom: new Fx.Tween(this.bottom, {
                property: "top",
                duration: 400,
                onComplete: nextEffect
            })
        };

        this.active = false;
        document.addEvent("mousewheel", this.mouseWheelListener.bindWithEvent(this));
        document.addEvent("keydown", this.keyboardListener.bindWithEvent(this));
                
    },

    open: function(event, link){
    
        this.active = true;
                        
        var size = window.getSize();
        var scroll = window.getScroll();
        var scrollSize = window.getScrollSize();
        
        /* The images should be 640x480(max). They're easily clipped at 1024x768,
         * so we get them as close as possible to the top of the window. */
        var offset = Math.round((size.y < 768) ? size.y / 36 : size.y / 10);
        
        var top = scroll.y + offset;
        
        this.overlay.setStyles({
            opacity: 0,
            display: "block",
            width: scrollSize.x,
            height: scrollSize.y
        });
        this.quickBox.setStyles({
            display: "block",
            top: top
        });
        this.fx.overlay.start(0.8);
        this.startLoad(link);
        return false;
    },
    
    startLoad: function(link, preload){
    
        if(!link) return;
        var image = new Asset.image(link.get("href"), {
            onload: function(){
                if(!preload && this.currentLink == link) this.nextEffect();
            }.bind(this)
        });
        if(!preload){
            this.stage.addClass("loading");
            this.stage.setStyle("display", "block");
            this.stage.empty();
            this.bottom.setStyle("opacity", 0);
            this.prevLink.setStyle("display", "none");
            this.nextLink.setStyle("display", "none");
            this.currentLink = link;
            this.currentCaption = link.retrieve("caption");
            this.currentImage = image;
            this.currentIndex = this.anchors.indexOf(link);
            this.step = 1;
        }
    },

    keyboardListener: function(event){
        if(!this.active) return;
        if(event.key != "f5") event.preventDefault();
        switch (event.key){
            case "esc": case "x": case "q": this.close(); break;
            case "b": case "p": case "left": this.changeImage(event, -1); break;    
            case "f": case "n": case "right": this.changeImage(event, 1);
        }
    },


    mouseWheelListener: function(event){
        if(!this.active) return;
        if(event.wheel > 0) this.changeImage(event, -1);
        if(event.wheel < 0) this.changeImage(event, 1);
    },

    changeImage: function(event, step){
    
        event.preventDefault();
        var link = this.anchors[this.currentIndex+step];
        if(!link) return false;
        for(var f in this.fx) this.fx[f].cancel();
        this.startLoad(link);
    },
    
    nextEffect: function(){
    
        switch(this.step++){
        
            case 1:
                var w = this.currentImage.width + this.options.padding * 2;
                var h = this.currentImage.height + this.options.padding * 2;
                this.prevLink.setStyle("height", h);
                this.nextLink.setStyle("height", h);
                this.fx.resize.start({
                    width: w,
                    height: h,
                    marginLeft: -(this.currentImage.width/2)
                });
                break;
            case 2:
            
                this.stage.removeClass("loading");
                this.stage.setStyle("opacity", 0);
                this.currentImage.setStyle("margin", this.options.padding);
                this.currentImage.inject(this.stage);
                this.fx.show.start(1);
                break;
            case 3:
            
                this.prevLink.setStyle("display", "block");
                this.nextLink.setStyle("display", "block");
                if(this.options.animateCaption){
                    if(this.options.counter){
                        var total = this.anchors.length;
                        var num = this.currentIndex + 1;
                        var counterText = this.options.counter;
                        counterText = counterText.replace(/\{NUM\}/, num);
                        counterText = counterText.replace(/\{TOTAL\}/, total);
                        this.counter.set("text", counterText);
                    }
                    this.caption.set("text", this.currentCaption);
                    var height = this.bottom.getStyle("height").toInt();
                    this.bottom.setStyles({
                        opacity: 1,
                        top: -height
                    });
                    this.fx.bottom.start(0);
                }
                break;
            case 4:
                this.startLoad(this.anchors[this.currentIndex-1], true);
                this.startLoad(this.anchors[this.currentIndex+1], true);
                break;
        }
    },

    close: function(){
        this.quickBox.setStyle("display", "none");
        this.overlay.fade("out");
        this.active = false;
    }
});


