/**
* Cornerz 0.8 - Bullet Proof Corners
* Jonah Fox (jonah@parkerfox.co.uk) 2008
* 
* Usage: $('.myclass').curve(options)
* options is a hash with the following parameters. Bracketed is the default
*   radius (10)
*   borderWidth (read from BorderTopWidth or 0)
*   background ("white"). Note that this is not calculated from the HTML as it is expensive
*   borderColor (read from BorderTopColor)
*   corners ("tl br tr bl"). Specify which borders
*   fixIE ("padding") - attmepts to fix IE by incrementing the property by 1 if the outer width/height is odd.

CHANGELIST from  v0.4

0.5 - Now attempts to fix the odd dimension problem in IE 
0.6 - Added semicolons for packing and fixed a problem with odd border width's in IE

*/

; (function($) {

    if ($.browser.msie && document.namespaces["v"] == null) {
        document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
        var ss = document.createStyleSheet().owningElement;
        ss.styleSheet.cssText = "v\\:*{behavior:url(#default#VML);}"
    }

    $.fn.cornerz = function(options) {

        function canvasCorner(t, l, r, bw, bc, bg, inline, o) {
            var sa, ea, cw, sx, sy, x, y, p = 1.57, css = "position:absolute;";

            if (t) {
                sa = -p; sy = r; y = o ? r : 0; css += "top:-" + (o ? r : bw) + "px;";
            } else {
                sa = p; sy = 0; y = o ? 0 : r; css += "bottom:-" + (o ? r : bw) + "px;";
            }

            if (l) {
                ea = p * 2; sx = r + 0; x = o ? r : 0; css += "left:-" + bw + "px;";
            } else {
                ea = 0; sx = 0; x = o ? 0 : r;

                if (inline) {
                    css += "left:" + (inline - r - bw) + "px;";
                } else {
                    css += "right:" + (-bw) + "px;";
                }
            }

            /** improved by nida
            * var canvas = $("<canvas width=" + r + "px height=" + r + "px style='" + css + "' ></canvas>");
            */
            var canvas = $("<canvas width=" + r + " height=" + r + " style='" + css + "' ></canvas>");
            var ctx = canvas[0].getContext('2d');
            ctx.beginPath();
            ctx.lineWidth = bw * 2;

            var nr = o ? r - bw : r
            if (nr < 0) {
                nr = r;
                bg = bc;
                ctx.lineWidth = 0
            }
            ctx.arc(sx, sy, nr, sa, ea, !(t ^ l)); // fails for bw > r
            ctx.strokeStyle = bc;
            ctx.stroke();
            ctx.lineWidth = 0;
            ctx.lineTo(x, y);
            ctx.fillStyle = bg;
            ctx.fill();
            return canvas;
        };

        function canvasCorners(corners, r, bw, bc, bg, inline, outer) {
            var hh = $("<div style='display: inherit' />"); // trying out style='float:left' 
            $.each(corners.split(" "), function() {
                hh.append(canvasCorner(this[0] == "t", this[1] == "l", r, bw, bc, bg, inline, outer));
            });
            return hh;
        };

        function vmlCurve(r, b, c, m, ml, mt, rfix, fill_col) {
            var l = m - ml - rfix;
            var t = m - mt;

            var filled = fill_col ? "True" : "False"

            return "<v:arc filled='" + filled + "' fillcolor='" + fill_col + "' strokeweight='" + b + "px' strokecolor='" + c + "' startangle='0' endangle='361' style=' top:" + t + "px;left: " + l + ";width:" + r + "px; height:" + r + "px' />";
        }


        function vmlCorners(corners, r, bw, bc, w, bg, outer) {
            var h = "<div style='text-align:left; '>";

            $.each($.trim(corners).split(" "), function() {
                var css, ml = 1, mt = 1;
                var rfix = 0;

                if (this.charAt(0) == "t") {
                    css = "top:-" + (outer ? r : bw) + "px;";
                }
                else {
                    css = "bottom:-" + (outer ? r : bw) + "px;";
                    mt = r + 1;
                }
                if (this.charAt(1) == "l")
                    css += "left:-" + bw + "px;";
                else {
                    css += "right:-" + (bw) + "px; "; // odd width gives wrong margin?
                    ml = r;
                    rfix = 1;
                }

                h += "<div style='" + css + "; position: absolute; overflow:hidden; width:" + r + "px; height: " + r + "px;'>";
                h += "<v:group  style='width:1000px;height:1000px;position:absolute;' coordsize='1000,1000' >";

                if (!outer)
                    h += vmlCurve(r * 3, r + bw, bg, -r / 2, ml, mt, rfix);
                if (bw > 0 || outer)
                    h += vmlCurve(r * 2 - bw, bw, bc, Math.floor(bw / 2 + 0.5), ml, mt, rfix, outer ? bg : null);
                h += "</v:group>";
                h += "</div>";
            });
            h += "</div>";

            return h;
        };

        var alterProperty = function(elem, prop, x) {
            var y = parseInt(elem.css(prop)) || 0;

            elem.css(prop, x + y);
        }

        function fixDimensions($$) {
            var ow = $$.innerWidth();
            var oh = $$.innerHeight();

            if (ow % 2 == 1) {
                alterProperty($$, "padding-right", 0);
                alterProperty($$, "margin-right", 0);
            }

            if (oh % 2 == 1) {
                alterProperty($$, "padding-bottom", 1);
                alterProperty($$, "margin-bottom", 1);
            }
        }

        /***** OUTER CORNERZ CODE *****/

        function addTopBot($el, r, bw, bc, bg, cs) {

            var tl = cs.indexOf("tl") != -1;
            var tr = cs.indexOf("tr") != -1;
            var bl = cs.indexOf("bl") != -1;
            var br = cs.indexOf("br") != -1;

            var offsetTop = (tl || tr) ? r : 0;
            var offsetBot = (bl || br) ? r : 0;

            var borderTop = (tl || tr) ? parseInt($el.css("borderTopWidth")) : 0;

            var pt = parseInt($el.css("paddingTop"));
            var pb = parseInt($el.css("paddingTop"));
            var pl = parseInt($el.css("paddingLeft"))

            var h = $el.height() - r - r + borderTop + borderTop;

            if (h < 0)
                h = 0;

            $el.css("height", h)

            if (!bg)
                bg = $el.css("backgroundColor");
            if (!bw)
                bw = borderTop;
            if (!bc)
                bc = $el.css("borderTopColor");

            $el.css("position", "relative");

            //var cs = o.corners.split(" ");


            $el.wrapInner("<div class=_content style='position: absolute; left: " + pl + "px; top: -" + (offsetTop - borderTop) + "px'  />");

            if (tl || tr) {
                addElement($el, tl, tr, r, bw, bc, bg, "top");
                alterProperty($el, "margin-top", offsetTop);
            }

            if (bl || br) {
                addElement($el, bl, br, r, bw, bc, bg, "bottom");
                alterProperty($el, "margin-bottom", offsetBot);
            }


            //$el.after("<div style='line-height:0px; padding:0px; margin:0px'>&nbsp;</div>")
        }

        function addElement($el, tl, tr, r, bw, bc, bg, type) {
            var elemcss = {};
            elemcss["border-" + type + "-width"] = 0;

            var w = $el.outerWidth();
            var h = r - bw;


            var padding = parseInt($el.css("padding-" + type));

            var new_padding = 0;
            if (h - padding < 0) {
                new_padding = padding - h;
            }
            //elemcss["padding-" + type]  = new_padding;

            var css = { background: bg,
                "position": "absolute"
            }
            var l = 0;

            css["margin-" + type] = -h - bw;
            css[type] = 0;
            var border = bw + "px solid " + bc;
            css["border-" + type] = border;
            if (tl) {
                l += r - bw;
                w -= r + bw;
            } else {
                css["border-left"] = border;
                l -= bw;
            }
            if (tr) {
                l -= 0;
                w -= r + bw;
            } else {
                css["border-right"] = border;
            }

            if (tr && tl) {
                w += bw + bw
            }

            css.left = l;
            css.width = w;
            css.height = h;
            var div = $("<div>").css(css);

            $el.prepend(div)
           .css(elemcss);
        }

        /*************/

        var settings = {
            corners: "tl tr bl br",
            radius: 10,
            background: "white",
            borderWidth: 0,
            fixIE: true,
            outer: false
        };

        $.extend(settings, options || {});

        /********/

        return this.each(function() {
            var $$ = $(this);
            var r = settings.radius * 1.0;
            var bw = (settings.borderWidth || parseInt($$.css("borderTopWidth")) || 0) * 1.0;
            var bg = settings.background;
            var bc = settings.borderColor;
            bc = bc || (bw > 0 ? $$.css("borderTopColor") : bg);

            var cs = settings.corners;


            this.style.zoom = 1;

            if ($$.css("position") != "absolute")
                this.style.position = "relative";


            if (settings.outer) {
                bg = $$.css("backgroundColor");
                addTopBot($$, r, bw, bc, bg, cs);
            }

            if ($.browser.msie) {
                this.innerHTML = vmlCorners(cs, r, bw, bc, $(this).width(), bg, settings.outer) + this.innerHTML;

//                by mk; Setzt sonst störende margins und paddings
//                if (settings.fixIE && !settings.outer)
//                    fixDimensions($$)
            }
            else
                $$.prepend(canvasCorners(cs, r, bw, bc, bg, $$.css("display") == "inline" ? $$.outerWidth() : null, settings.outer));

        }

    );

    }
})(jQuery);

