/**
* Overlay Gallery plugin, version: 1.0.0
* 
* Copyright (c) 2009 Tero Piirainen
* http://flowplayer.org/tools/overlay.html#gallery
*
* Dual licensed under MIT and GPL 2+ licenses
* http://www.opensource.org/licenses
*
* Since  : July 2009
* Date: ${date}
* Revision: ${revision} 
*/
(function ($) {

    // TODO: next(), prev(), getIndex(), onChange event

    // version number
    var t = $.tools.overlay;
    t.plugins = t.plugins || {};

    t.plugins.gallery = {
        version: '1.0.0',
        conf: {
            imgId: 'img',
            next: '.next',
            prev: '.prev',
            info: '.info',
            progress: '.progress',
            disabledClass: 'disabled',
            activeClass: 'active',
            opacity: 0.8,
            speed: 'slow',
            template: '<strong>${title}</strong> <span>Image ${index} of ${total}</span>',
            autohide: true,
            preload: true,
            api: false,
            //new settings
            autoResize: true,
            viewFullSizeImg: true
        }
    };

    $.fn.gallery = function (opts) {

        var conf = $.extend({}, t.plugins.gallery.conf), api;
        $.extend(conf, opts);

        // common variables for all gallery images
        api = this.overlay();

        var links = this,
			 overlay = api.getOverlay(),
			 next = overlay.find(conf.next),
			 prev = overlay.find(conf.prev),
			 info = overlay.find(conf.info),
			 progress = overlay.find(conf.progress),
			 els = prev.add(next).add(info).css({ opacity: conf.opacity }),
			 close = api.getClosers(),
			 index,
        //new common variables
			 trigger,
			 opened = false,
		   lastResize = null,
		   waitingResize = false,
		   firstResize = true,
		   timeoutResize = 0;

        //function update timer when resizing viewport
        function updateResizeTime() {
            if (firstResize) {
                firstResize = false;
                return;
            }

            lastResize = new Date();
            if (!waitingResize && timeoutResize == 0) {
                waitingResize = true;
                timeoutResize = setInterval(checkForResizeEnd, 300);
            }
        }

        //call load function when detect end of resize viewport
        function checkForResizeEnd() {
            if (!((new Date()).getTime() - lastResize.getTime() >= 300))
                return;

            waitingResize = false;
            clearInterval(timeoutResize);
            timeoutResize = 0;

            load(links.getTrigger());
        }

        //calculate new image size
        function resizeImg(img, width, height, maxw, maxh) {
            var maxRatio = maxw / maxh;
            var ratio = width / height;
            var ratio2 = height / width;

            if (ratio > maxRatio) {
                //width is the problem
                if (width > maxw) {
                    img.width = maxw - parseInt(maxw / 10, 10);
                    img.height = (width > height) ? parseInt(img.width / ratio, 10) : parseInt(img.width * ratio2, 10);
                }
            } else {
                //width is the problem
                if (height > maxh) {
                    img.height = maxh - parseInt(maxh / 10, 10);
                    img.width = (width > height) ? parseInt(img.height * ratio, 10) : parseInt(img.height / ratio2, 10);
                }
            }

        };

        //open image in new window
        function openImg() {
            window.open(links.getTrigger().attr('href'), '');
        }

        //{{{ load 

        function load(el) {

            //trigger and opened 
            trigger = el;
            opened = true;

            progress.fadeIn();
            els.hide(); close.hide();

            var url = el.attr("href");

            // download the image 
            var image = new Image();

            image.onload = function () {

                progress.fadeOut();

                // find image inside overlay
                var img = $("#" + conf.imgId, overlay);

                // or append it to the overlay 
                if (!img.length) {
                    img = $("<img/>").attr("id", conf.imgId).css("visibility", "hidden");
                    overlay.prepend(img);

                    //function to add click handlers to open image in new window
                    if (conf.viewFullSizeImg) {
                        img.click(openImg);
                    }
                }

                // make initially invisible to get it's dimensions
                img.attr("src", url).css("visibility", "hidden");

                //size of image and viewport 
                var width = image.width;
                var height = image.height;
                var windowWidth = $(window).width();
                var windowHeight = $(window).height();

                //autoResize is anabled
                if (conf.autoResize) {

                    if ((width > windowWidth) || (height > windowHeight)) {
                        resizeImg(img[0], width, height, windowWidth, windowHeight);
                        width = img.width();
                        height = img.height();
                    } else {
                        img.removeAttr('width').removeAttr('height');
                    }

                }

                // animate overlay to fit the image dimensions
                var left = (windowWidth - width) / 2;
                left = (left < 0) ? 0 : left;
                //var top = $("body").scrollTop() + ((windowHeight - height) / 2);
                var top = window.pageYOffset + ((windowHeight - height) / 2);

                //settings for overlay 
                var overlayConf = (conf.autoResize) ? { width: width, height: height, left: left, top: top} : { width: width, height: height, left: left };

                // calculate index number
                index = links.index(links.filter("[href=" + url + "]"));

                // activate trigger
                links.removeClass(conf.activeClass).eq(index).addClass(conf.activeClass);

                // enable/disable next/prev links
                var cls = conf.disabledClass;
                els.removeClass(cls);

                if (index === 0) { prev.addClass(cls); }
                if (index == links.length - 1) { next.addClass(cls); }

                // set info text & width
                var text = conf.template
					.replace("${title}", el.attr("title") || el.data("title") || "")
					.replace("${index}", index + 1)
					.replace("${total}", links.length);

                var padd = parseInt(info.css("paddingLeft"), 10) + parseInt(info.css("paddingRight"), 10);
                info.html(text).css({ width: width - padd });

                overlay.animate(overlayConf, conf.speed, function () {

                    // gradually show the image
                    img.hide().css("visibility", "visible").fadeIn(function () {
                        if (!conf.autohide) {
                            els.fadeIn(); close.show();
                        }
                    });

                });
            };

            image.onerror = function () {
                overlay.fadeIn().html("Cannot find image " + url);
            };

            image.src = url;

            if (conf.preload) {
                links.filter(":eq(" + (index - 1) + "), :eq(" + (index + 1) + ")").each(function () {
                    var img = new Image();
                    img.src = $(this).attr("href");
                });
            }

        }

        //}}}


        // function to add click handlers to next/prev links	 
        function addClick(el, isNext) {

            el.click(function () {

                if (el.hasClass(conf.disabledClass)) { return; }

                // find the triggering link
                var trigger = links.eq(i = index + (isNext ? 1 : -1));

                // if found load it's href
                if (trigger.length) { load(trigger); }

            });
        }

        // assign next/prev click handlers
        addClick(next, true);
        addClick(prev);

        // arrow keys
        $(document).keydown(function (evt) {

            if (!overlay.is(":visible") || evt.altKey || evt.ctrlKey) { return; }

            if (evt.keyCode == 37 || evt.keyCode == 39) {
                var btn = evt.keyCode == 37 ? prev : next;
                btn.click();
                return evt.preventDefault();
            }
            return true;
        });

        function showEls() {
            if (!overlay.is(":animated")) {
                els.show(); close.show();
            }
        }

        // autohide functionality
        if (conf.autohide) {
            overlay.hover(showEls, function () { els.fadeOut(); close.hide(); }).mousemove(showEls);
        }

        //function to add resize handler
        if (conf.autoResize) {
            jQuery(window).resize(function () {
                if (links.isOpened()) {
                    updateResizeTime()
                }
            });
        }

        // load a proper gallery image when overlay trigger is clicked
        var ret;

        this.each(function () {

            var el = $(this), api = $(this).overlay(), ret = api;

            api.onBeforeLoad(function () {
                load(el);
            });

            api.onClose(function () {
                opened = false;
                links.removeClass(conf.activeClass);
            });
        });

        //API methods
        $.extend(links, {
            getTrigger: function () {
                return trigger;
            },
            isOpened: function () {
                return opened;
            }
        })

        return conf.api ? ret : this;

    };

})(jQuery);		

