// Datagraf jQuery imgBorder plugin
// Author: Hans Staugaard
//
// TODO:
//   * Add resize support

jQuery.extend({
    imgBorder: {
        ImageLoader: function(baseImg, callback, parts) {
            this.baseImg = baseImg;
            this.callback = callback;
            this.parts = parts || ['topleft', 'top', 'topright', 'left', 'right', 'bottomleft', 'bottom', 'bottomright'];
            this.processed = 0;
            this.images = [];
            this.load();
        }
    },
    isNotIE8: function() {
        return navigator.appName == 'Microsoft Internet Explorer' && (!document.documentMode || document.documentMode < 8);
    },
    isIE6: function() {
        return /MSIE 6\./.test(navigator.userAgent);
    }
});

jQuery.extend(jQuery.imgBorder.ImageLoader.prototype, {
    load: function() {
        var match = /^(.*)\.(.*)$/.exec(this.baseImg);
        for (var i = 0; i < this.parts.length; i++) {
            var image = new Image();
            var struct = {loaded: false, image: image};
            this.images[this.parts[i]] = struct;
            $(image).bind('load', {self: this, struct: struct}, this.imageLoaded);
            $(image).bind('error', {self: this, struct: struct}, this.imageError);
            image.src = match[1] + '.' + this.parts[i] + '.' + match[2];
        }
    },
    imageLoaded: function(event) {
        event.data.struct.loaded = true;
        event.data.self.imageError(event);
    },
    imageError: function(event) {
        var self = event.data.self;
        self.processed++;
        if (self.processed == self.parts.length) self.callback(self);
    },
    isLoaded: function(part) {
        if (jQuery.inArray(part, this.parts) == -1) return false;
        return this.images[part].loaded;
    },
    getImage: function(part) {
        return this.images[part].image;
    },
    getHeight: function(part) {
        return this.isLoaded(part) ? this.getImage(part).height : 0;
    },
    getWidth: function(part) {
        return this.isLoaded(part) ? this.getImage(part).width : 0;
    },
    isPng: function(part) {
        return /\.png$/.test(this.getImage(part).src)
    },
    getTopHeight: function() {
        return Math.max(this.getHeight('topleft'), this.getHeight('top'), this.getHeight('topright'));
    },
    getBottomHeight: function() {
        return Math.max(this.getHeight('bottomleft'), this.getHeight('bottom'), this.getHeight('bottomright'));
    },
    getLeftWidth: function() {
        return Math.max(this.getWidth('topleft'), this.getWidth('left'), this.getWidth('bottomleft'));
    },
    getRightWidth: function() {
        return Math.max(this.getWidth('topright'), this.getWidth('right'), this.getWidth('bottomright'));
    },
    createEdgeDiv: function(part, dontScale) {
        var div = jQuery('<div class="imgBorderPart"></div>').css('position', 'absolute');
        if (this.isPng(part) && jQuery.isIE6()) {
            div.css('filter', "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.getImage(part).src + "'" + (dontScale ? '' : ",sizingMethod='scale'") + ")");
        } else {
            div.css('background-image', 'url(' + this.getImage(part).src + ')');
        }
        return div;
    },
    createCornerDiv: function(part) {
        return this.createEdgeDiv(part, true).css({
            'width': this.getWidth(part),
            'height': this.getHeight(part)
        });
    }
});

jQuery.fn.extend({
    addSibling: function(where, element) {
        if (where == 'before') {
            return this.before(element);
        } else {
            return this.after(element);
        }
    },
    imgBorder: function(baseImg, options) {
        var elements = this;
        var overflowTop = (options && options.overflowTop) || 0;
        var overflowBottom = (options && options.overflowBottom) || 0;
        var overflowRight = (options && options.overflowRight) || 0;
        var overflowLeft = (options && options.overflowLeft) || 0;
        var insertPosition = (options && options.insertPosition) || 'after';
        var fixCenter = (options && options.fixCenter) || false;
        var parts = (options && options.parts);
        var extraCss = {};
        if (options && options.extraCss) {
            if (options.extraCssIE && jQuery.isNotIE8()) options.extraCss += ';' + options.extraCssIE;
            var rules = options.extraCss.split(/\s*;\s*/);
            for (var i = 0; i < rules.length; i++) {
                var rule = rules[i].split(/\s*:\s*/);
                extraCss[rule[0]] = rule[1];
            }
        }
        new jQuery.imgBorder.ImageLoader(baseImg, function(imageLoader) {
            jQuery(elements).each(function() {
                var width = jQuery(this).outerWidth();
                var height = jQuery(this).outerHeight();
                var wrapper = jQuery('<div class="imgBorderWrapper"></div>').css({
                    'position': jQuery(this).css('position') == 'absolute' ? 'absolute' : 'relative',
                    'width': width,
                    'height': height
                });
                var element = this;
                jQuery.each(['top', 'left', 'right', 'bottom', 'margin-top', 'margin-bottom', 'margin-right', 'margin-left'], function() {
                    var property = this.toString();
                    if (jQuery(element).css(property) && jQuery(element).css(property) != 'auto') {
                        jQuery(wrapper).css(property, jQuery(element).css(property));
                        jQuery(element).css(property, 0);
                    }
                });
                if (jQuery(this).css('float') != 'none')  jQuery(wrapper).css('float', jQuery(this).css('float'));
                if (jQuery(this).css('display') == 'inline-block') {
                    if (jQuery.isNotIE8()) {
                        jQuery(wrapper).css({
                            'display': 'inline',
                            'zoom': 1
                        });
                    } else {
                        jQuery(wrapper).css('display', 'inline-block');
                    }
                }
                jQuery(wrapper).css(extraCss);
                jQuery(this).css('position', 'relative');
                jQuery(this).wrap(wrapper);
                // topleft
                if (imageLoader.isLoaded('topleft')) {
                    jQuery(this).addSibling(insertPosition, imageLoader.createCornerDiv('topleft').css({
                        'top': -overflowTop,
                        'left': -overflowLeft
                    }));
                };
                // topright
                if (imageLoader.isLoaded('topright')) {
                    jQuery(this).addSibling(insertPosition, imageLoader.createCornerDiv('topright').css({
                        'top': -overflowTop,
                        'left': width + overflowRight - imageLoader.getWidth('topright')
                    }));
                };
                // bottomleft
                if (imageLoader.isLoaded('bottomleft')) {
                    jQuery(this).addSibling(insertPosition, imageLoader.createCornerDiv('bottomleft').css({
                        'top': height + overflowBottom - imageLoader.getHeight('bottomleft'),
                        'left': -overflowLeft
                    }));
                };
                // bottomright
                if (imageLoader.isLoaded('bottomright')) {
                    jQuery(this).addSibling(insertPosition, imageLoader.createCornerDiv('bottomright').css({
                        'top': height + overflowBottom - imageLoader.getHeight('bottomright'),
                        'left': width + overflowRight - imageLoader.getWidth('bottomright')
                    }));
                };
                // top
                if (imageLoader.isLoaded('top')) {
                    jQuery(this).addSibling(insertPosition, imageLoader.createEdgeDiv('top').css({
                        'top': -overflowTop,
                        'left': imageLoader.getWidth('topleft') - overflowLeft,
                        'width': width - imageLoader.getWidth('topleft') - imageLoader.getWidth('topright') + overflowLeft + overflowRight,
                        'height': imageLoader.getHeight('top')
                    }));
                };
                // left
                if (imageLoader.isLoaded('left')) {
                    jQuery(this).addSibling(insertPosition, imageLoader.createEdgeDiv('left').css({
                        'top': imageLoader.getHeight('topleft') - overflowTop,
                        'left': -overflowLeft,
                        'width': imageLoader.getWidth('left'),
                        'height': height - imageLoader.getHeight('topleft') - imageLoader.getHeight('bottomleft') + overflowTop + overflowBottom
                    }));
                };
                // bottom
                if (imageLoader.isLoaded('bottom')) {
                    jQuery(this).addSibling(insertPosition, imageLoader.createEdgeDiv('bottom').css({
                        'top': height + overflowBottom - imageLoader.getHeight('bottom'),
                        'left': imageLoader.getWidth('bottomleft') - overflowLeft,
                        'width': width - imageLoader.getWidth('bottomleft') - imageLoader.getWidth('bottomright') + overflowLeft + overflowRight,
                        'height': imageLoader.getHeight('bottom')
                    }));
                };
                // right
                if (imageLoader.isLoaded('right')) {
                    jQuery(this).addSibling(insertPosition, imageLoader.createEdgeDiv('right').css({
                        'top': imageLoader.getHeight('topright') - overflowTop,
                        'left': width + overflowRight - imageLoader.getWidth('right'),
                        'width': imageLoader.getWidth('right'),
                        'height': height - imageLoader.getHeight('topright') - imageLoader.getHeight('bottomright') + overflowTop + overflowBottom
                    }));
                };
                // Fix center
                if (fixCenter) {
                    jQuery(this).css({
                        'top': imageLoader.getTopHeight() - overflowTop,
                        'left': imageLoader.getLeftWidth() - overflowLeft,
                        'padding-top': parseInt(jQuery(this).css('padding-top')) - imageLoader.getTopHeight() + overflowTop,
                        'padding-left': parseInt(jQuery(this).css('padding-left')) - imageLoader.getLeftWidth() + overflowLeft,
                        'padding-bottom': parseInt(jQuery(this).css('padding-bottom')) - imageLoader.getBottomHeight() + overflowBottom,
                        'padding-right': parseInt(jQuery(this).css('padding-right')) - imageLoader.getRightWidth() + overflowRight
                    });
                }
            })
        }, parts);
        return jQuery(elements);
    }
});
