(function($)
{
	$.fn.textReplace = function(options)
	{
		options = options ? options : { };
		options.scriptParameters = $.extend({ }, $.fn.textReplace.defaults.scriptParameters, options.scriptParameters);
		options = $.extend({ }, $.fn.textReplace.defaults, options);
		return this.each(function()
		{
			var $this = $(this);
			$this.html('<div class="text-replace-container">' + $this.html() + '</div>');
			var container = $this.find('.text-replace-container');
			container.height($this.height());
			
			// Analyze text styles.
			var parameters =
			{
				text: container.text(),
				width: container.width(),
				height: container.height(),
				size: getPixelCount($this.css('font-size')),
				colour: getColour($this.css('color')),
				transform: getTransform($this.css('text-transform')),
				alignment: $this.css('text-align')
			};
			
			var textAlign = $this.css('text-align');
			var backgroundPosition;
			switch (textAlign)
			{
				case 'right':
					backgroundPosition = 'right top';
					break;
				case 'center':
					backgroundPosition = 'center top';
					break;
				default:
					backgroundPosition = 'left top';
					break;
			}
			
			// Construct target URI.
			parameters = $.extend({ }, parameters, options.scriptParameters);
			var imageUri = options.scriptUrl + '?';
			for (var key in parameters)
			{
				imageUri += key + '=' + encodeURIComponent(parameters[key]) + '&';
			}
			
			// Escape any quotation marks in the URI and add the CSS.
			if (!$.browser['msie'])
			{
				imageUri = imageUri.replace('\'', '\\000027').replace('"', '\\000022');
			}
			container.css(
			{
				height: parameters.height,
				backgroundImage: 'url(' + imageUri + ')',
				backgroundPosition: backgroundPosition,
				backgroundRepeat: 'no-repeat',
				textAlign: 'left',
				textIndent: '-10000em'
			});
			
			// Perform an AJAX request to the script to retrieve the height of the image.
			$.get(imageUri + 'sample', function(data)
			{
				var height = parseInt(data, 10);
				var extension = height - container.height();
				if (extension > 0)
				{
					// Extend the container downards to allow the full image to be visible.
					container.css(
					{
						marginBottom: -extension,
						paddingBottom: extension 
					});
				}
			});
		});
	};
	
	$.fn.textReplace.defaults =
	{
		scriptUrl: 'text-replace.php',
		scriptParameters: { }
	};
	
	function getPixelCount(string)
	{
		return parseInt(string.match(/(\d+(\.\d+)?)px/i)[1]);
	}
	
	function getColour(cssColor)
	{
		var rgbMatches = cssColor.match(/^rgb\((\d{0,3}), *(\d{0,3}), *(\d{0,3})\)$/i);
		var hexMatches = cssColor.match(/^#?(([a-f0-9]{3})|([a-f0-9]{6}))$/i);
		
		// Generate hex string.
		var hex;
		if (rgbMatches)
		{
			var decimal = (parseInt(rgbMatches[1], 10) << 16) +
						  (parseInt(rgbMatches[2], 10) << 8) +
						  (parseInt(rgbMatches[3], 10));
			hex = decimal.toString(16);
			
			// Pad it out with zeros.
			var startLength = hex.length;
			for (var i = 0; i < 6 - startLength; i++)
			{
				hex = '0' + hex;
			}
		}
		else if (hexMatches)
		{
			if (hexMatches[2])
			{
				var shortHex = hexMatches[2];
				hex = shortHex.charAt(0) + shortHex.charAt(0) +
				      shortHex.charAt(1) + shortHex.charAt(1) +
				      shortHex.charAt(2) + shortHex.charAt(2);
			}
			else if (hexMatches[3])
			{
				hex = hexMatches[3];
			}
			else
			{
				return false;
			}
		}
		else
		{
			return false;
		}
		
		return hex;
	}
	
	function getTransform(transform)
	{
		switch (transform)
		{
			case 'uppercase':
			case 'lowercase':
			case 'capitalize':
				return transform;
			default:
				return 'none';
		}
	}
})(jQuery);