var isIE6 = ($.browser.msie && $.browser.version < 7) ? true : false;

(function($) {
	$.fn.roundbox = function(options) {
		
		//build main options before element iteration
		opts = $.extend({}, $.fn.roundbox.defaults, options);
		
		//iterate and reformat each matched element
		return this.each(function() {

			$this = $(this);
			
			//apply theme background images
			var i = $.fn.roundbox.themes.length
			while (i--) {
				if ($this.hasClass($.fn.roundbox.themes[i].name)) {
					
					$this.data('rbthemedata',$.fn.roundbox.themes[i]); //for easy manipulation after reflow of content
					
					$this.css('background','transparent url(' + $.fn.roundbox.themes[i].imagePrefix + '/' + $.fn.roundbox.themes[i].name + '/bottom.png) no-repeat right bottom');	
					$this.find('.rbtitle, .rbtitle > .rbtinner, .rbtitle > span').css('background','transparent url(' + $.fn.roundbox.themes[i].imagePrefix + '/' + $.fn.roundbox.themes[i].name + '/top.png) no-repeat right top');
					
					$this.find('.rbtitle:first > .rbtinner, .rbtitle:first > span').css('backgroundPosition','-2px top');
					
					if(typeof($.fn.roundbox.themes[i].titleColor) != 'undefined') {
						$this.find('.rbtitle:first, .rbtitle:first > a').css('color','#' + $.fn.roundbox.themes[i].titleColor);
					}
					
					$this.children('.rbcontent').css('background','transparent url(' + $.fn.roundbox.themes[i].imagePrefix + '/' + $.fn.roundbox.themes[i].name + '/bottom.png) no-repeat left bottom');
					if((typeof($.fn.roundbox.themes[i].gradient) != 'undefined') && ($.fn.roundbox.themes[i].fill != 'undefined'))
						$this.find('.rbcontent:first > .rbinner').css('background','#' + $.fn.roundbox.themes[i].fill)
						
					$this.find('.rbcontent:first > .rbinner:first').css({
						background: '#'+$.fn.roundbox.themes[i].fill,
						borderLeft: '1px solid #'+$.fn.roundbox.themes[i].stroke,
						borderRight: '1px solid #'+$.fn.roundbox.themes[i].stroke
					})
					
					//apply gradient, if any
					if (typeof($.fn.roundbox.themes[i].gradient) != 'undefined') {
						applyGradient($this.find('.rbinner:first'), $.fn.roundbox.themes[i].gradient[0], $.fn.roundbox.themes[i].gradient[1], opts.bruteForceGradients);
					}

				}
				
				
			}
			
			//build element specific options and add metadata properties if any
			//var o = $this.metadata() ? $.extend({}, opts, $this.metadata()) : opts;
			
			//apply accordian
			if ($this.hasClass('rbaccordian')) {

				$this.find('.accordian:first').remove();
				
				var leftMargin = isIE6 ? parseInt($this.find('.rbtitle:first > span').css('paddingLeft')) - 44: parseInt($this.find('.rbtitle:first > span').css('paddingLeft')) - 22;
				var topMargin = ($this.find('.rbtitle:first').height()/2) - 13;
				
				$this.children('.rbtitle').css({
					cursor:'pointer'
				});
				
				$this.children('.rbtitle').prepend('<div class="accordian '+o.accordianInitState+'" style="left:'+leftMargin+'px;top:'+topMargin+'px">&nbsp;</div>');

				$this.children('.rbinner').css({
					paddingLeft: leftMargin + "px"
				});
				
				if (o.accordianInitState == "closed") {
					$this.find('.rbinner:first').css({
						paddingTop:'0',
						paddingBottom:'0',
						height:'0',
						overflow: 'hidden'
					});
					
					if (typeof($this.data('rbthemedata')) != 'undefined' && typeof($this.data('rbthemedata').gradient) != 'undefined')
						applyGradient($this.find('h3.rbtitle:first'), $this.data('rbthemedata').gradient[0], $this.data('rbthemedata').gradient[1], opts.bruteForceGradients);
					
				}
				
				//bind click action
				$this.children('.rbtitle, .accordian').unbind('click').bind('click', function(){
					$.fn.roundbox.animateAccordian($(this));
				});
				
			}

			//apply drop shadows
			//NOTE: ie6 is having problems with drop shadow positioning, also some issues with drop shadows and accordians, skip these cases for now
			if(!isIE6 && !$this.hasClass('rbaccordian')) { 

				$this.find('.rbshadow-btm:first, .rbshadow-side:first').remove();
				if ($this.hasClass('rbshadow')) {
					shadowWidth = $this.width() + 4;
					shadowHeight = $this.height() - 10;
					shadowOffset = ($this.find('.rbtitle').height() - 6)*-1;
					shadowBtmBottomPos = -5;
					shadowBtmLeftPos = 0;
					$this.children('.rbcontent').append('<div class="rbshadow-btm" style="left:'+shadowBtmLeftPos+'px;bottom:'+shadowBtmBottomPos+'px;width:'+shadowWidth+'px"><div></div></div><div class="rbshadow-side" style="height:'+shadowHeight+'px;top:'+shadowOffset+'px"></div>');	
				}
				
			}
			
		});
		
	};
	
	//
	// private functions
	//
	
	//appplies a gradient to a box object
	function applyGradient($gradientObject, gradientStart, gradientEnd) {

		if (!$gradientObject || !gradientStart || !gradientEnd)
				return;
				
		$gradientObject.css('backgroundColor','#'+gradientEnd);
		
		if(!opts.bruteForce && $.browser.msie) { //use filters for IE
			$gradientObject.css('width', $gradientObject.width());
			$gradientObject.css('filter', "progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=\"#" + gradientStart + "\",EndColorStr=\"#" + gradientEnd + "\")");
		} else {
	
			if (canvasCompatible()) { //use canvas to draw gradient
				
				if($gradientObject.find('canvas').length > 0)
					return;
					
				/*if ($gradientObject.find('.canvas-content:first').length > 0) {
					$gradientObject.find('canvas:first').remove();
					$cc = $('.canvas-content').html();
					$('.canvas-content').replaceWith($cc);
				}*/
				
				y = 0;
				h = Math.round($gradientObject.height()/2); //remove the /2 for smooth gradients
				if(!h) h = 1;
				w = $gradientObject.parent().width() + 5;
				$gradientObject.wrapInner("<div class='canvas-content' style='position:relative;z-index:10;'></div>");
				$gradientObject.append("<canvas style='position:absolute;z-index:0;top:" + y + "px;left:0' height="+h+" width="+w+" />");
				var context = $('canvas:last').get(0).getContext('2d');
				context.fillStyle = context.createLinearGradient(0, 0, 0, h);
				context.fillStyle.addColorStop(0, "#"+gradientStart);
				context.fillStyle.addColorStop(1, "#"+gradientEnd);
				context.fillRect(0, 0, w, h);
				
			} else { //brute force technique - insert an array of colored divs
			
				colorArray = createColorPath(gradientStart,gradientEnd);
				y = 0;
				h = Math.round($gradientObject.height()/colorArray.length);
				if(!h) h = 1;
				w = $gradientObject.parent().width() + 5;
				$gradientObject.wrapInner("<div style='zoom:1;position:relative;text-align:left;z-index:10;'></div>");
				var gradientHtml = "";
				
				var left = isIE6 ? "-" + $gradientObject.css('paddingLeft'):'0';
				
				for(p = 0;p < colorArray.length;p++) {
					gradientHtml += "<div class='rbgdiv' style='position:absolute;z-index:0;top:" + y + "px;left:"+ left +";height:" + h + "px;width:" + w + "px;background-color:rgb(" + colorArray[p][0] + "," + colorArray[p][1] + "," + colorArray[p][2] + ")'></div>";			
					y += h;
					if(y >=$gradientObject.height() - h) break;
				}
				$gradientObject.append(gradientHtml);

			}

		}
		
		//fix for IE6 phantom btm right corner display bug on nested boxes
		if (isIE6 && $gradientObject.find('.rounded').length > 0) {
			$gradientObject.find('.rounded').css({
				height:'10px'
			});
		}

	}
		
	function createColorPath(color1,color2) {
		colorPath = new Array();
		colorPercent = 1.0;
		do {
			colorPath[colorPath.length]=setColorHue(longHexToDec(color1),colorPercent,longHexToDec(color2));
			colorPercent -= opts.bruteForceGradientResolution; //adjust this number up to decrease resolution, adjust down to increase resolution -- default is .05
		} while(colorPercent > 0);
		return colorPath;
	}
			
	function setColorHue(originColor,opacityPercent,maskRGB) {
		returnColor=new Array();
		for(w=0;w < originColor.length;w++) returnColor[w] = Math.round(originColor[w]*opacityPercent) + Math.round(maskRGB[w]*(1.0-opacityPercent));
		return returnColor;
	}
	
	function longHexToDec(longHex) {
		return new Array(toDec(longHex.substring(0,2)),toDec(longHex.substring(2,4)),toDec(longHex.substring(4,6)));	
	}
	
	function toDec(hex) {	
		return parseInt(hex,16);
	}
	
	function canvasCompatible() {
		var canvasCompatible = false;
		try {
	        canvasCompatible = !!(document.createElement('canvas').getContext('2d'));
	    } catch(e) {
	        canvasCompatible = !!(document.createElement('canvas').getContext);
	    } 
	    return canvasCompatible;
	}

	function debug(msg) {
		if (window.console && window.console.log)
		window.console.log(msg);
	};
	
	//
	// public functions
	//
	
	$.fn.roundbox.redrawGradients = function($target) { //called when user resizes box - needed to redraw gradients
		
		var themedata = $target.parents('.rounded:first').data('rbthemedata');
		var $canvas = $target.find('canvas');

		if (canvasCompatible() && $canvas.length > 0) {
		
			$canvas.attr('height',$target.height());
			
			var h = Math.round($target.height());
			if(!h) h = 1;
			var w = $target.parent().width() + 5;
			
			var context =$canvas.get(0).getContext('2d');
				context.fillStyle = context.createLinearGradient(0, 0, 0, h);
				context.fillStyle.addColorStop(0, "#"+themedata.gradient[0]);
				context.fillStyle.addColorStop(1, "#"+themedata.gradient[1]);
				context.fillRect(0, 0, w, h);
			return;
		}
		
		if (opts.bruteForceGradients) {
			$target.find('.rbgdiv').remove();
			applyGradient($target, themedata.gradient[0], themedata.gradient[1], opts.bruteForceGradients)
		}
		
		
	}
	
	$.fn.roundbox.animateAccordian = function($target) {
		var $accordian = $target.parent('.rbouter').find('.accordian:first')
		if ($accordian.hasClass('open')) { //content is open, collapse the box
			$accordian.removeClass('open').addClass('closed');
			//$target.parent('.rbouter').find('.rbinner:first').css('overflow','hidden');
			var $rbinner = $target.parent('.rbouter').find('.rbinner:first');
			
			$rbinner.animate({
				height:'0'
	   		}, function(){	
	   			$rbinner.css('overflow','hidden');
	   			$rbinner.css({
					paddingTop:'0',
					paddingBottom:'0'
				});
	   		});
		} else { //content is closed, expand the box	
			var $rbinner = $target.parent('.rbouter').find('.rbinner:first')
			$target.parent('.rbouter').find('.accordian:first').removeClass('closed').addClass('open');
			$rbinner.css('height','auto'); //height needs to be set back to auto to retrieve the target height
			var targetHeight = $rbinner.height();
			$rbinner.css('height','0'); //set it back to 0
			//$target.parent('.rbouter').find('.rbinner:first').css('padding','5px 10px');
			$rbinner.css('overflow','visible');
			$rbinner.animate({
				height: targetHeight + "px"
	   		});
	   		
	   		//todo: support drop shadow animation in accordians

		}
	}
	
	//
	// plugin defaults
	//
	$.fn.roundbox.defaults = {
		accordianInitState: 'closed',
		gradientStart: 'ffffff',
		gradientEnd: 'eef7fa',
		bruteForceGradients: false,
		bruteForceGradientResolution: '.05' //only used for brute force gradients
	};
	
	$.fn.roundbox.themes = [];
	
})(jQuery);