/**
 * gradientList by Thibaut De Muynck (ab6x.net)
 *
 * v20100209
 *
 * Creates a uniform color gradient accros text listed in li's (using canvas)
 *
 * REQUIRES
 * - mootools 1.2.4
 * - mootools more Color class
 * - fontChecker by David Walsh (http://github.com/darkwing/FontChecker)
 * - typeface.js if typeface substitution requested (http://typeface.neocracy.org/)
 * - excanvas.js for canvas compatibility in IE (http://code.google.com/p/explorercanvas/)
 *
 * PARAMETER
 * @el (string, required) - the id of the ul element
 *
 * ul element must contain the canvas areas to modify
 * only the first level li are transfomed to apply gradient
 * those li should contain text in the <span class="canvas"> area (see sample)
 *
 * OPTIONS
 * @grad_colors (array of color objects, required) - default: none - the list of colors used in the gradient (at least 2)
 * @back_color (color object, optional) - default: $RGB(255,255,255) - a color object of the background color
 * @font_family (string, optional) - default: document settings - a css font-family reference to render text
 * @typeface (boolean, optional) - default: false - use typeface.js for font substitution (requires compatible font_family to be set)
 * @ie_skip (boolean, optional) - default: true - skips execution under Internet Explorer
 *
 * SAMPLE
 *	<ul id="my_id">
 *		<li><span class="canvas">TEXT one</span>
 *			<ul>
 *				<li>not impacted</li>
 *			</ul>
 *		</li>
 *		<li><span class="canvas">TEXT two</span></li>
 *		<li><span class="canvas">TEXT three</span></li>
 *		<li><span class="canvas">TEXT four</span></li>
 *		<li><span class="canvas">TEXT five</span></li>
 *	</ul>
 *
 */

var gradientList = new Class({
	Implements: [Events, Options],

	options: {
		'grad_colors':	null,
		'back_color':	$RGB(255, 255, 255),
		'font_family':	false,
		'typeface':		false,
		'ie_skip':		true
	},

	/*-- CONSTRUCTOR --*/

	initialize: function(el, options) {
		// get first-level li's
		this.targets = document.id(el).getChildren('li');
		// set and check options
		this.setOptions(options);
		if ($type(this.options.grad_colors) !== 'array' || this.options.grad_colors.length < 2) {
			return false;
		}

		// checks ie
		if (Browser.Engine.trident) {
			return false;
		}

		// compute color steps
		var prc_colors = [];
		var Nc = this.options.grad_colors.length;
		var Np = this.targets.length;
		for (var Pi = 0; Pi <= this.targets.length; Pi++) {
			var prc = (Nc - 1) * Pi / Np;
			this.options.grad_colors.each(function(col, Ci) {
				var p_prc = prc - Ci + 1;
				if (p_prc > 1 && p_prc <= 2) {
					p_prc = 1 - (p_prc - 1);
				}
				else if (p_prc < 0 || p_prc > 2) {
					p_prc = 0;
				}
				if (!prc_colors[Pi]) {
					prc_colors[Pi] = []
				}
				prc_colors[Pi][Ci] = p_prc * 100;
			});
		}

		// apply canvas gradient
		this.targets.each(function(el, index) {
			// recover / treat text content
			var txt = el.getElement('span.canvas').get('text');
			switch (el.getStyle('text-transform')) {
				case 'capitalize':
					txt = this._capitalizeText(txt);
					break;
				case 'uppercase':
					txt = txt.toUpperCase();
					break;
				case 'lowercase':
					txt = txt.toLowerCase();
					break;
			}
			// check first available font in family
			var fonts = this.options.font_family ? this.options.font_family.split(',') : el.getStyle('font-family').split(',');
			var good_font = 'sans-serif';
			var fc = new FontChecker();
			var good = false;
			fonts.each(function(font) {
				if (!good && fc.check(font)) {
					good = true;
					good_font = font;
				}
			});
			// set context
			var txt_canvas = document.createElement("canvas");
			if (Browser.Engine.trident) { G_vmlCanvasManager.initElement(txt_canvas); }
			var ctx = txt_canvas.getContext('2d');
			ctx.font = el.getStyle('font-size') + " " + good_font;
			var c_width = ctx.measureText(txt).width;
			var c_height = el.getStyle('font-size').toInt();
			txt_canvas.set('width', c_width);
			txt_canvas.set('height', c_height);
			// compute colors
			var start_color = new Color(this.options.back_color);
			var stop_color = new Color(this.options.back_color);
			this.options.grad_colors.each(function(color, Ci) {
				start_color = start_color.mix(color, prc_colors[index][Ci]);
				stop_color = stop_color.mix(color, prc_colors[index + 1][Ci]);
			});
			// create gradient
			var gradient = ctx.createLinearGradient(0, 0, 0, c_height);
			gradient.addColorStop(0, 'rgb(' + start_color.join(',') + ')');
			gradient.addColorStop(1, 'rgb(' + stop_color.join(',') + ')');
			if (this.options.typeface) {
				// render text using typeface.js
				var rendered = _typeface_js.getRenderedText(el.getElement('span.canvas').childNodes[0], start_color, stop_color);
				rendered.replaces(el.getElement('span.canvas'));
			}
			else {
				// draw text
				ctx.fillStyle = gradient;
				ctx.font = el.getStyle('font-size') + " " + good_font;
				ctx.textBaseline = "top";
				ctx.fillText(txt, 0, 0);
				txt_canvas.replaces(el.getElement('span.canvas'));
			}
		}.bind(this));
	},

	/*-- PRIVATE METHODS --*/

	_capitalizeText: function(text) {
		return text.replace(/(^|\s)[a-z]/g, function(match) {
			return match.toUpperCase()
		});
	}
});
