/**
 * Box v1
 * PB/Graphico October 2008;
 *
 * Overlay jQuery plug-in.
 * Consumes images (jpg and png), html snippets and flash. Height and width must be provided for flash. 
 * Uses the href attr of the target anchor to provide source content;
 *
 * Requires:
 * jQuery (1.2.6);
 * swfObject [http://blog.deconcept.com/swfobject/] for flash inclusion;
 *
 * Supported browsers Firefox 2 & 3(mac & PC), IE6 & 7, Safari 2(Mac), Opera 9.5 (mac & PC).
 *
 * Example use;
 * var options = {
 *		width: 400,
 *		preload: true,
 *		animation: false;
 * }
 * $('.gallery').box(options);
 *
 *	Supported options;
 *	width:		Number, default 400;
 *	height:		Number, default null;
 *	preload:	Boolean, show preloader, default true;
 *	navigation: Boolean, show navigation , default true;
 *	margin:		Number, margin between frame and content, default 10;
 *	animate:	Boolean, anmiate box into position, default true;
 *
 * To do;
 * All marked with **HACK**;
 */
(function(jq) {

    jq.fn.box = function(options) {
        var defaults = jq.fn.box.defaults;
        var box = new Box();
        var self = this;
        jQuery.extend(defaults, options);
        jq('a', this).each(function(i) {
            defaults.thumbs.push(this.href);
            // store reference to position in named store 'index';
            jq.data(this, 'index', i);
        });

        return this.each(function() {
            jQuery("a", this).bind("click", function(e) {
                box.trigger.call(box, e, jq.data(this, 'index'));
                return false;
            });
        });
    };

    jq.fn.box.defaults = {
        width: 400,
        height: null,
        preload: true,
        navigation: true,
        margin: 10,
        thumbs: [],
        index: null,
        type: null,
        speed: 400,
        transition: function(o, obj, callback) {
            // could do with a tidy!!;
            jq(".ui-box").animate({ "top": o.top, "height": o.height }, this.speed,
                function() {
                    jq(".ui-box").animate({ "left": o.left, "width": o.width }, this.speed,
                        function() {
                            callback.call(obj);
                        });
                });
        },
        animate: true
    };

    // Box class;
    function Box() {
        var self = this;
        
        if(jQuery.browser.msie && jQuery.browser.version == "6.0")
            this.addIframe();

        jq(this.OVERLAY).css(this.css.overlay)
			.appendTo("body").hide()
			.bind("click", function(e) {
				self.setIsOpen.call(self, false);
			    self.hide.call(self, e);
			});

        jq(this.WRAP).css(this.css.box)
			.appendTo("body").hide();

        this.addPreloader();

        jq(window).resize(function() {
            self.adjust.call(self);
        });
        jq(window).scroll(function() {
            self.adjust.call(self);
        });
        
    }

    // Box props & methods;
    Box.prototype = {
        OVERLAY: "<div class=\"ui-overlay\"></div>",
        WRAP: "<div class=\"ui-box\" style=\"background: #fff;\">\n" +
	                "<div class=\"clear\" id=\"ui-media\" style='position: relative; margin: " +
	                    jq.fn.box.defaults.margin +
	                    "px; background: #dedede;'>\n" +
	                "</div>\n" +
	            "</div>",

        PRELOADER: "<div id='ui-preloader' style='color: #fff; font-size: 1.4em; position: absolute; top: 10px; right: 10px;'>Loading...</div>",

        defaults: jq.fn.box.defaults,
        isFirstPass: true,

        addPreloader: function() {
            if (!this.defaults.preload) return false;
            jq(this.PRELOADER)
				.appendTo("body").hide();
        },

        trigger: function(e, i) {
            var url = this.defaults.thumbs[i];
            this.defaults.index = i;
            this.setIsOpen(true);
            if (url.match(/\.jpg$|\.png$/)) {
                this.defaults.type = "image";
            } else if (url.match(/\.swf$/)) {
                this.defaults.type = "flash";
            } else if (url.match(/\.html$|\.htm$|\.aspx$/)) {
                this.defaults.type = "file";
            } else {
                return false;
            }
            this.loadType(url);
        },

        loadType: function(url) {
            var type = this.defaults.type.replace(/\w/,
                        function(char) { return char.toUpperCase(); });
            this["load" + type](url);
        },

        loadImage: function(url) {
            var self = this;
            if (arguments.length > 1) {
                var m = this.defaults.margin * 2;
                var w = this.defaults.width - this.defaults.margin * 2;
                var h = this.defaults.height - this.defaults.margin * 2;
                var i = this.createImage(url, w, h);
                this.addContent(i);
                return this;
            }
            var image = new Image();
            image.onload = function() {
                self.loadImage.call(self, url, [image.width, image.height]);
            };
            image.src = url;
        },

        addContent: function(asset, w, h) {
            var box = jq("#ui-media");
            box.empty().hide();
            asset.appendTo(box);
            this.addNav();
            this.show();
            return this;
        },

        createImage: function(url, w, h) {
            var img = "<img src='" + url + "'";
            img += w > 0 ? " width ='" + w + "'" : '';
            img += h > 0 ? " height ='" + h + "'" : '';
            img += " />";
            return jq(img);
        },

        // flash include requires a default width and height to be set;
        loadFlash: function(url) {
            var m = this.defaults.margin * 2;
            var w = this.defaults.width;
            var h = this.defaults.height;
            var div = this.doSFWObject(url, w - m, h - m);
            var copy = div.clone().show();
            this.addContent(copy, w, h);
            div.remove();
            return this;
        },

        doSFWObject: function(url, w, h) {
            var body = jq("body")[0];
            var div = jq("<div id=\"ui-flash\"></div>").appendTo(body).hide();
            var so = new SWFObject(url, "ui-asset", w, h, "8", "transparent");
            so.addParam("wmode", "transparent");
            so.addParam("quality", "high");
            so.addParam("allowScriptAccess", "sameDomain");
            so.addParam("allowFullScreen", "false");
            so.addParam("align", "middle");
            so.addParam("name", "asset");
            so.addParam("pluginspage", "http://www.macromedia.com/go/getflashplayer");
            so.write("ui-flash");
            return div;
        },

        loadFile: function(url) {
            var self = this;
            if (arguments.length > 1) {
                this.addContent(jq(arguments[1]));
                return this;
            }
            if (typeof url == "object") {
                url = url.href;
            }
            jq.get(url, function(data) {
                return self.loadFile.call(self, url, data);
            });
        },

        addNav: function() {
           
            this.addClose();
        },

        addClose: function() {
            if (!jq("#close")) return false;
            var self = this;
            var css = this.css.close;
            jq('<a href="#" id="close">Close</a>')
			        .css(css).bind("click", function() {
			            self.hide.call(self);
			        }).appendTo(jq("#ui-media"));
        },

        next: function() {
            var thumbs = this.defaults.thumbs;
            var index = this.defaults.index;
            if (index + 1 === thumbs.length) return false;
            if (index + 2 === thumbs.length){
				// dim next link;
				jq('.next', jq('.ui-box')).css({color: "#333"});
            }
            var url = thumbs[index + 1];
            this.defaults.index += 1;
            this.loadType(url);
        },

        prev: function() {
            var thumbs = this.defaults.thumbs;
            var index = this.defaults.index;
            if (index === 0) return false;
            if (index - 1 < 1 ){
				// dim prev link;
				jq('.prev', jq('.ui-box')).css({color: "#333"});
            }
            var url = thumbs[index - 1];
            this.defaults.index -= 1;
            this.loadType(url);
        },

        show: function() {
            var self = this;
            this.setOverlay();
            this.setPreloader();
            setTimeout(function() {
                jq(".ui-box").show();
                self.adjust.call(self);
            }, 1000);
        },
        
        // sets a varible that prevents adjust() showing the   
        // gallery if the overlay background has been clicked;
        setIsOpen: function(bool){
			this.isOpen = bool;
        },
        
        // Allow box to be positioned 
        // over select inputs in IE6
        addIframe: function(){
            var body = document.getElementsByTagName("body")[0];
            body.insertAdjacentHTML("beforeEnd", '<IFRAME style="display: none; width: 0; height: 0;" src="" frameBorder="0" scrolling="no" id="iShim" />'); 
	    },
    	
        hideIframe: function(){
             jq("#iShim").css({display: "none"});
        },
        
        showIframe: function(obj){
            if(obj == undefined) return false;
            // alert("showIframe() " + obj.top+", "+obj.left+", "/*+obj.height+", "+obj.width+", "*/);
            jq("#iShim").css({
                display: "block",
                position: "absolute",
                top: obj.top,
                left: obj.left,  
                width: obj.width, 
                height: obj.height
            });
        },

        setPreloader: function() {
            if (!this.defaults.preload) return false;
            jq("#ui-preloader").show();
        },

        hide: function() {
            this.hideIframe();
            jq(".ui-overlay").hide();
            jq(".ui-box").stop().hide();
        },

        adjust: function() {
			if(! this.isOpen){
				this.hide();
				return false;
			}
                
            var size = this.getSize();

            if (this.defaults.preload)
                jq("#ui-preloader").hide();

            if (this.isFirstPass)
                jq(".ui-box").css(this.getDefaultDims());

            var xy = this.getXY(size[0], size[1]);
            
            if(jQuery.browser.msie && jQuery.browser.version == "6.0")
                this.showIframe({ top: xy[1], left: xy[0], height: size[1], width: size[0] });

            if (jq(".ui-overlay").css("display") === "block") {
                this.move({ top: xy[1], left: xy[0], height: size[1], width: size[0] });
                this.setOverlay();
            }
            this.isFirstPass = false;
        },

        setOverlay: function() {
            var docSize = this.docSize();
            jq(".ui-overlay").show()
				.css({ width: docSize[0], height: docSize[1] })
        },

        getSize: function() {

            var w, h, old = {};
            jq.each(["display", "visibility", "position", "height", "width"],
        		function(i, val) {
        		    old[val] = jq(".ui-box").css(val);
        		});
            jq(".ui-box").css(this.css.reset);
            // untidy!!;
            jq('#ui-media').css({ display: "block" });

            if (this.defaults.width) {
                jq(".ui-box").css({ width: this.defaults.width });
                w = this.defaults.width;
                h = jq(".ui-box").height();
            }

            if (this.defaults.height) {
                jq(".ui-box").css({ height: this.defaults.height });
                h = this.defaults.height;
                w = jq(".ui-box").width();
            }

            if (this.defaults.height && this.defaults.width) {
                w = this.defaults.width;
                h = this.defaults.height;
            }

            jq('#ui-media').css({ display: "none" });
            jq('.ui-box').css(old);

            return [w, h];
        },

        getXY: function(bw, bh) {
            var ws = this.windowSize();
            var sc = this.scroll();
            return [sc[1] + (ws[0] / 2) - (bw / 2), sc[0] + (ws[1] / 2) - (bh / 2)];
        },

        getDefaultDims: function() {
            return {
                top: this.windowSize()[1] / 2,
                left: this.windowSize()[0] / 2,
                width: "1px",
                height: "1px"
            };
        },

        setNavigation: function() {
            var defaults = this.defaults;
            jq.each(["next", "prev"], function(i, val) {
                var height = jq("#" + val).css("height");
                jq("#" + val).css({ marginTop: parseInt(height) });
            });
        },

        move: function(o) {
            if (this.defaults.animate) {
                this.defaults.transition(o, this, this.fade);
            } else {
                jq(".ui-box").css(o);
                this.fade();
            };
            this.setNavigation();
        },

        fade: function() {
			// **HACK** remove overflow hidden added by jQuery.animate();
			jq('.ui-box').css({overflow: 'visible'});
            jq("#ui-media").fadeIn(600);
        },

        docSize: function() {
            // see windowSize() for explaination;
            var height = jq.browser.opera && jq.browser.version > "9.5" &&
				jq.fn.jquery <= "1.2.6" ?
				Math.max(document.body.scrollHeight, document.body.offsetHeight) :
				jq(document).height();
            return [jq(document).width(), Math.max(height, this.windowSize()[1])];
        },

        windowSize: function() {
            // fix jQuery/Opera bug with the window height, courtesy 
            // of http://www.ericmmartin.com/jquery-browser-issues/
            var height = jq.browser.opera && jq.browser.version > "9.5" &&
				jq.fn.jquery <= "1.2.6" ?
				document.documentElement["clientHeight"] :
				jq(window).height();
            return [jq(window).width(), height];
        },

        scroll: function() {
            return [jq(window).scrollTop(), jq(window).scrollLeft()];
        },

        css: {
            overlay: {
                position: "absolute",
                background: "#000",
                opacity: 0.9,
                top: "0",
                left: "0",
                zIndex: 100000
            },
            box: {
                position: "absolute",
                color: "#333",
                textAlign: "left",
                zIndex: 100001
            },
            nav: {
                fontSize: "1.2em",
                display: "block",
                color: "#ccc",
                position: "absolute",
                textDecoration: "none",
                width: "40px",
                fontWeight: "bold",
                height: "15px",
                textAlign: "center",
                outline: "none",
                bottom: jq.browser.opera ? "" : "-30px", // Opera positional fix;
                marginTop: jq.browser.opera ? "13px" : ""
            },
            close: {
				fontSize: "1.2em",
                top: "-30px",
                right: "0",
                position: "absolute",
                fontWeight: "bold",
                color: "#ccc",
                display: "block",
                textDecoration: "none"
            },
            reset: {
                display: '',
                visibility: 'hidden',
                position: 'absolute',
                height: '',
                width: ''
            }
        }
    };
})(jQuery);