﻿String.format = function(text){
    if ( arguments.length <= 1 ) return text;
    var tokenCount = arguments.length - 2;
    var token = 0;
    while(token <= tokenCount) text = text.replace( new RegExp( "\\{" + token + "\\}", "gi" ), arguments[ ++token ] );
    return text;
};

var GenClick = {
    getClasses: function(className){
        var klasses = [];
        (className||"").split(" ").each( function(cls){
            if(cls) klasses.push(cls);
        });
        return klasses;
    },
    addClass: function(el, cls){
        if(this.hasClass(el, cls)) return;
        var classes = this.getClasses(el.className);
        classes.push(cls);
        el.className = classes.join(" ");
    },
    removeClass: function(el, cls){
        var endCls = [];
        this.getClasses(el.className).each(function(c){
            if(c == cls) return;
            endCls.push(c);
        });
        el.className = endCls.join(" ");
    },
    hasClass: function(el, cls){
        var classes = this.getClasses(el.className);
        for(var i = 0, l = classes.length; i < l; i++)
            if(classes[i] == cls) return true;
        return false;
    },
    toggleClass: function(el, cls){
        if(this.hasClass(el, cls)) this.removeClass(el, cls);
        else this.addClass(el, cls);
    }
}

Class.Binds = new Class({
    bindMethods: function() {
        var binders = arguments.length > 0 ? arguments : this.binds;
        Array.flatten(binders).each(function(method){
            var original = this[method];
            this[method] = function(){
                return original.apply(this, arguments);
            }.bind(this);
            this[method].parent = original.parent
        }, this);
        return this;
    }
});
if (window.Options){
    var Options = new Class({
        Extends: Options,
        setOptions: function(){
            this.parent.apply(this, arguments);
            return this.bindMethods ? this.bindMethods() : this;
        }
    });
}
var Modalizer = new Class({
    defaultModalStyle: {
        display: 'block',
        position: 'fixed',
        top: 0,
        left: 0,
        'z-index': 5000,
        'background-color': '#333',
        opacity: 0.8
    },
    setModalOptions: function(options) {
        this.modalOptions = $merge({
            width: (window.getScrollSize().x + 300),
            height: (window.getScrollSize().y + 300),
            elementsToHide: 'select',
            hideOnClick: true,
            modalStyle: {},
            updateOnResize: true,
            layerId: 'modalOverlay',
            onModalHide: $empty,
            onModalShow: $empty
        },
        this.modalOptions, options);
        return this
    },
    layer: function() {
        if (!this.modalOptions.layerId) this.setModalOptions();
        return $(this.modalOptions.layerId) || new Element('div', {
            id: this.modalOptions.layerId
        }).inject(document.body)
    },
    resize: function() {
        if (this.layer()) {
            this.layer().setStyles({
                width: (window.getScrollSize().x + 300),
                height: (window.getScrollSize().y + 300)
            })
        }
    },
    setModalStyle: function(styleObject) {
        this.modalOptions.modalStyle = styleObject;
        this.modalStyle = $merge(this.defaultModalStyle, {
            width: this.modalOptions.width,
            height: this.modalOptions.height
        },
        styleObject);
        if (this.layer()) this.layer().setStyles(this.modalStyle);
        return (this.modalStyle)
    },
    modalShow: function(options) {
        this.setModalOptions(options);
        this.layer().setStyles(this.setModalStyle(this.modalOptions.modalStyle));
        if (Browser.Engine.trident4) this.layer().setStyle('position', 'absolute');
        this.layer().removeEvents('click').addEvent('click',
        function() {
            this.modalHide(this.modalOptions.hideOnClick)
        }.bind(this));
        this.bound = this.bound || {};
        if (!this.bound.resize && this.modalOptions.updateOnResize) {
            this.bound.resize = this.resize.bind(this);
            window.addEvent('resize', this.bound.resize)
        }
        if ($type(this.modalOptions.onModalShow) == "function") this.modalOptions.onModalShow();
        this.togglePopThroughElements(0);
        this.layer().setStyle('display', 'block');
        return this
    },
    modalHide: function(override, force) {
        if (override === false) return false;
        this.togglePopThroughElements(1);
        if ($type(this.modalOptions.onModalHide) == "function") this.modalOptions.onModalHide();
        this.layer().setStyle('display', 'none');
        if (this.modalOptions.updateOnResize) {
            this.bound = this.bound || {};
            if (!this.bound.resize) this.bound.resize = this.resize.bind(this);
            window.removeEvent('resize', this.bound.resize)
        }
        return this
    },
    togglePopThroughElements: function(opacity) {
        if (Browser.Engine.trident4 || (Browser.Engine.gecko && Browser.Platform.mac)) {
            $$(this.modalOptions.elementsToHide).each(function(sel) {
                sel.setStyle('opacity', opacity)
            })
        }
    }
});


Imagebox = new Class({
    Implements: [Options, Events, Class.Binds, Modalizer],
    binds: ['click', 'keyboardListener', 'addHtmlElements'],
    options: {
        resizeDuration: 400,
        initialWidth: 250,
        initialHeight: 250,
        zIndex: 5000,
        animateCaption: true,
        showCounter: true,
        counterText: 'Image {0} of {1}',
        autoScanLinks: true,
        relString: 'imagebox',
        useDefaultCss: true,
        assetBaseUrl: '/imagebox/',
        cssFile: "imagebox.css",
        overlayStyles: {
            opacity: 0.8
        },
        imgUrl: "href",
        prevText: "previous",
        nextText: "next",
        closeText: "close",
        closeImage: "closelabel.gif"
        //captionText: "title"
    },
    initialize: function() {
        var args = Array.link(arguments, {
            options: Object.type,
            links: Array.type
        });
        this.setOptions(args.options);
        var anchors = args.links || this.options.anchors;
        if (this.options.autoScanLinks && !anchors) anchors = $$('a[rel^=' + this.options.relString + ']');
        if (!$$(anchors).length) return;
        this.addAnchors(anchors);
        if (this.options.useDefaultCss) this.addCss();
        window.addEvent('domready', this.addHtmlElements.bind(this))
    },
    anchors: [],
    addAnchors: function(anchors) {
        $$(anchors).each(function(el) {
            if (!el.retrieve('imagebox')) {
                el.store('imagebox', this);
                this.attach(el)
            }
        }.bind(this))
    },
    attach: function(el) {
        el.addEvent('click', this.click.pass(el, this));
        this.anchors.include(el);
    },
    addHtmlElements: function() {
        this.setModalOptions({
            elementsToHide: ''
        });
        this.overlay = this.layer().addClass('ibOverlay');
        this.setModalStyle(this.options.overlayStyles);
        this.container = new Element('div', {
            'class': 'ibContainer'
        }).inject(document.body);
        
        this.center = new Element('div', {
            styles: {
                width: this.options.initialWidth,
                height: this.options.initialHeight,
                marginLeft: ( - (this.options.initialWidth / 2)),
                display: 'none',
                zIndex: this.options.zIndex + 1
            }
        }).inject(this.container).addClass('ibCenter');
        this.overlay.inject(this.container).setStyles(this.options.overlayStyles);
        
        this.title = new Element('h1', {
            'class': 'ibTitle'
        }).inject(this.center);
        
        this.image = new Element('img', {
            'class': 'ibImage'
        }).inject(this.center);
        
        this.hoverNav = new Element('div', {
            styles: {
                zIndex: this.options.zIndex + 2
            }
        }).inject(this.center).addClass("ibHoverNav");
        
        
        this.prevLink = new Element('a', {
            'class': 'ibPrevLink',
            href: 'javascript:void(0);',
            html: this.options.prevText,
            styles: {
                'display': 'none'
            }
        }).inject(this.hoverNav);
        this.nextLink = this.prevLink.clone().removeClass('ibPrevLink').addClass('ibNextLink').inject(this.hoverNav);
        //this.nextLink.set("title",this.options.nextText);
        this.nextLink.set("html", this.options.nextText);
        this.prevLink.addEvent('click', this.previous.bind(this));
        this.nextLink.addEvent('click', this.next.bind(this));
        
        var onfocus = function(){ GenClick.addClass( this, this.get("class").split(" ")[0] + "Focus" ); };
        var onblur = function(){ GenClick.removeClass( this, this.get("class").split(" ")[0] + "Focus" ); };
        this.nextLink.addEvent('focus', onfocus);
        this.nextLink.addEvent('blur', onblur);
        this.prevLink.addEvent('focus', onfocus);
        this.prevLink.addEvent('blur', onblur);
        
        if(Browser.Engine.trident){
            GenClick.addClass(this.hoverNav, "ibIE");
        }
        //console.log(window.location.pathname);
        //var path = (window.location.pathname+'').substr(1).split('/')[0];
        this.closeLink = new Element('img', {
            'class': 'ibCloseImage',
            src: this.options.assetBaseUrl + this.options.closeImage, //'/'+path+'/closelabel.gif',
            alt: this.options.closeText
        }).inject( new Element('a', {
                'class': 'ibCloseLink',
                href: 'javascript:void(0);'
            }).inject(this.hoverNav).addEvent('click', this.close.bind(this))
        );
        this.overlay.addEvent('click', this.close.bind(this));
        
        
        this.bottomContainer = new Element('div', {
            'class': 'ibBottomContainer',
            styles: {
                display: 'none',
                zIndex: this.options.zIndex + 1
            }
        }).inject(this.container);
        this.bottom = new Element('div', {
            'class': 'ibBottom'
        }).inject(this.bottomContainer);
        this.caption = new Element('p', {
            'class': 'ibCaption'
        }).inject(this.bottom);
        this.number = new Element('p', {
            'class': 'ibNumber'
        }).inject(this.bottom);
        
        var nextEffect = this.nextEffect.bind(this);
        this.fx = {
            overlay: new Fx.Tween(this.overlay, {
                property: 'opacity',
                duration: 500
            }).set(0),
            resize: new Fx.Morph(
                this.center, 
                $extend({
                        duration: this.options.resizeDuration,
                        onComplete: nextEffect
                    },
                    this.options.resizeTransition ? { transition: this.options.resizeTransition }: {}
                )
            ),
            image: new Fx.Tween(this.image, {
                property: 'opacity',
                duration: 500,
                onComplete: nextEffect
            }),
            bottom: new Fx.Tween(this.bottom, {
                property: 'margin-top',
                duration: 400,
                onComplete: nextEffect
            })
        };
        this.preloadPrev = new Element('img');
        this.preloadNext = new Element('img');
    },
    addCss: function() {
        window.addEvent('domready', function() {
            if ($('ImageboxCss')) return;
            new Element('link', {
                rel: 'stylesheet',
                media: 'screen',
                type: 'text/css',
                href: this.options.assetBaseUrl + this.options.cssFile,
                id: 'ImageboxCss'
            }).inject(document.head)
        }.bind(this))
    },
    click: function(el) {
        var link = $(el);
        var rel = link.get('rel') || this.options.relString;
        if (rel == this.options.relString) return this.show(link.get( this.options.imgUrl ), link.get('title'));
        var j, imageNum, images = [];
        /*
        this.anchors.each(function(el) {
            if (el.get('rel') == link.get('rel')) {
                var elImageData = this.options.imageData[this.anchors.indexOf(el) + this.options.offset];
                var linkImageData = this.options.imageData[this.anchors.indexOf(link) + this.options.offset];
                for (j = 0; j < images.length; j++){
                    if (images[j][0] == elImageData[ this.options.imgUrl ]){
                        break;
                    }
                }
                if (j == images.length) {
                    images.push( [
                        elImageData[this.options.imgUrl],
                        $(el.firstChild).get( "alt" ),
                        elImageData['data-caption']
                    ] ); //]);
                    if (elImageData[ this.options.imgUrl ] == linkImageData[ this.options.imgUrl ])
                        imageNum = j
                }
            }
        },
        this);
         */
        var linkImageData = this.options.imageData[this.anchors.indexOf(link) + this.options.offset];
        this.options.imageData.each(function(data, i){
            images.push([
                data[this.options.imgUrl],
                data['data-title'],
                data['data-caption'],
            ]);
            if( data[ this.options.imgUrl ] == linkImageData[ this.options.imgUrl ])
                imageNum = i;
        }, this);
        return this.open(images, imageNum)
    },
    show: function(url, title) {
        return this.open([[url, title]], 0)
    },
    open: function(images, imageNum) {
        this.closing = false;
        this.fireEvent('onDisplay');
        this.images = images;
        this.setup(true);
        this.top = (window.getScroll().y + (window.getSize().y / 15)).toInt();
        this.center.setStyles({
            top: this.top,
            display: ''
        });
        this.fx.overlay.start(this.options.overlayStyles.opacity);
        return this.changeImage(imageNum)
    },
    setup: function(open) {
        var elements = $$('object, iframe');
        elements.extend($$(Browser.Engine.trident ? 'select': 'embed'));
        elements.each(function(el) {
            if (open) el.store('ibBackupStyle', el.getStyle('visibility'));
            var vis = (open ? 'hidden': el.retrieve('ibBackupStyle'));
            el.setStyle('visibility', vis)
        });
        var fn = open ? 'addEvent': 'removeEvent';
        document[fn]('keydown', this.keyboardListener);
        this.step = 0
    },
    keyboardListener: function(event) {
        switch (event.code) {
        case 27:
        case 88:
        case 67:
            this.close();
            break;
        case 37:
        case 80:
            this.previous();
            break;
        case 39:
        case 78:
            this.next()
        }
    },
    previous: function() {
        if(arguments[0]){
            var ev = arguments[0],
                a = ev.target;
            if(a && a.nodeType && a.tagName.toLowerCase() == "a"){
                a.fireEvent("blur");
            }
        }
        return this.changeImage(this.activeImage - 1)
    },
    next: function() {
        if(arguments[0]){
            var ev = arguments[0],
                a = ev.target;
            if(a && a.nodeType && a.tagName.toLowerCase() == "a"){
                a.fireEvent("blur");
            }
        }
        return this.changeImage(this.activeImage + 1)
    },
    changeImage: function(imageNum) {
        this.fireEvent('onImageShow', [imageNum, this.images[imageNum]]);
        if (this.step || (imageNum < 0) || (imageNum >= this.images.length)) return false;
        this.step = 1;
        this.activeImage = imageNum;
        this.center.setStyle('backgroundColor', '');
        this.bottomContainer.setStyle('display', 'none');
        this.prevLink.setStyle('display', 'none');
        this.nextLink.setStyle('display', 'none');
        this.fx.image.set(0);
        GenClick.addClass(this.center, 'ibLoading');
        this.preload = new Element('img', {
            events: {
                load: function() {
                    this.nextEffect.delay(100, this)
                }.bind(this)
            }
        });
        this.preload.set('src', this.images[imageNum][0]);
        return false
    },
    nextEffect: function() {
        switch (this.step++) {
        case 1:
            this.image.setAttribute("src", this.images[this.activeImage][0]);
            var title = this.images[this.activeImage][1] || '';
            //this.image.setAttribute('alt', title);
            this.title.set('text', title);
            if(title){
                this.prevLink.set("html", String.format(this.options.prevText, title));
                this.nextLink.set("html", String.format(this.options.nextText, title));
            }
            
            this.image.setStyle('display', '');
            this.bottom.setStyle('width', this.preload.width);
            this.caption.set('html', this.images[this.activeImage][2] || '');
            this.number.set('html', (!this.options.showCounter || (this.images.length == 1)) ? '': String.format(this.options.counterText, (this.activeImage + 1), this.images.length));
            if (this.activeImage)
                $(this.preloadPrev).set('src', this.images[this.activeImage - 1][0]);
            if (this.activeImage != (this.images.length - 1))
                $(this.preloadNext).set('src', this.images[this.activeImage + 1][0]);
            if (this.center.clientHeight != this.image.offsetHeight) {
                this.fx.resize.start({
                    height: this.image.offsetHeight
                });
                break
            }
            this.step++;
        case 2:
            if (this.center.clientWidth != this.image.offsetWidth) {
                this.fx.resize.start({
                    width: this.image.offsetWidth,
                    marginLeft: -this.image.offsetWidth / 2
                });
                break
            }
            this.step++;
        case 3:
            this.bottomContainer.setStyles({
                top: (this.top + this.center.getSize().y),
                height: 0,
                marginLeft: this.center.getStyle('margin-left'),
                display: ''
            }); 
            this.fx.image.start(1);
            break;
        case 4:
            if (this.options.animateCaption) {
                this.fx.bottom.set( - this.bottom.offsetHeight);
                this.bottomContainer.setStyle('height', '');
                this.fx.bottom.start(0);
                break
            }
            this.bottomContainer.style.height = '';
        case 5:
            this.step = 0;
            if (this.activeImage) this.prevLink.setStyle('display', '');
            if (this.activeImage != (this.images.length - 1)) this.nextLink.setStyle('display', '');
        }
    },
    close: function() {
        this.closing = true;
        this.fireEvent('onHide');
        if (this.step < 0) return;
        this.step = -1;
        if (this.preload) this.preload.destroy();
        for (var f in this.fx) this.fx[f].cancel();
        this.center.setStyle('display', 'none');
        this.bottomContainer.setStyle('display', 'none');
        this.fx.overlay.chain(this.setup.pass(false, this)).start(0);
        return
    }
});
