/**
* 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;";	  
	      }
	  	}
		
	    var canvas=$("<canvas width="+r+"px height="+ r +"px 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", 1);
        alterProperty($$, "margin-right", 1);
      }

      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;        
          
          if(settings.fixIE && !settings.outer)
            fixDimensions($$)
        }
        else
          $$.prepend(canvasCorners(cs,r,bw,bc,bg, $$.css("display") == "inline" ? $$.outerWidth() : null, settings.outer));
        
       
      }
      
    );
 
  }
})(jQuery);


