
/* A utility class for rendering <tr> rows.
----------------------------------------------------------------------------------------------------------------------*/
// It leverages methods of the subclass and the View to determine custom rendering behavior for each row "type"
// (such as highlight rows, day rows, helper rows, etc).

var RowRenderer = Class.extend({

	view: null, // a View object
	isRTL: null, // shortcut to the view's isRTL option
	cellHtml: '<td/>', // plain default HTML used for a cell when no other is available


	constructor: function(view) {
		this.view = view;
		this.isRTL = view.opt('isRTL');
	},


	// Renders the HTML for a row, leveraging custom cell-HTML-renderers based on the `rowType`.
	// Also applies the "intro" and "outro" cells, which are specified by the subclass and views.
	// `row` is an optional row number.
	rowHtml: function(rowType, row) {
		var renderCell = this.getHtmlRenderer('cell', rowType);
		var rowCellHtml = '';
		var col;
		var cell;

		row = row || 0;

		for (col = 0; col < this.colCnt; col++) {
			cell = this.getCell(row, col);
			rowCellHtml += renderCell(cell);
		}

		rowCellHtml = this.bookendCells(rowCellHtml, rowType, row); // apply intro and outro

		return '<tr>' + rowCellHtml + '</tr>';
	},


	// Applies the "intro" and "outro" HTML to the given cells.
	// Intro means the leftmost cell when the calendar is LTR and the rightmost cell when RTL. Vice-versa for outro.
	// `cells` can be an HTML string of <td>'s or a jQuery <tr> element
	// `row` is an optional row number.
	bookendCells: function(cells, rowType, row) {
		var intro = this.getHtmlRenderer('intro', rowType)(row || 0);
		var outro = this.getHtmlRenderer('outro', rowType)(row || 0);
		var prependHtml = this.isRTL ? outro : intro;
		var appendHtml = this.isRTL ? intro : outro;

		if (typeof cells === 'string') {
			return prependHtml + cells + appendHtml;
		}
		else { // a jQuery <tr> element
			return cells.prepend(prependHtml).append(appendHtml);
		}
	},


	// Returns an HTML-rendering function given a specific `rendererName` (like cell, intro, or outro) and a specific
	// `rowType` (like day, eventSkeleton, helperSkeleton), which is optional.
	// If a renderer for the specific rowType doesn't exist, it will fall back to a generic renderer.
	// We will query the View object first for any custom rendering functions, then the methods of the subclass.
	getHtmlRenderer: function(rendererName, rowType) {
		var view = this.view;
		var generalName; // like "cellHtml"
		var specificName; // like "dayCellHtml". based on rowType
		var provider; // either the View or the RowRenderer subclass, whichever provided the method
		var renderer;

		generalName = rendererName + 'Html';
		if (rowType) {
			specificName = rowType + capitaliseFirstLetter(rendererName) + 'Html';
		}

		if (specificName && (renderer = view[specificName])) {
			provider = view;
		}
		else if (specificName && (renderer = this[specificName])) {
			provider = this;
		}
		else if ((renderer = view[generalName])) {
			provider = view;
		}
		else if ((renderer = this[generalName])) {
			provider = this;
		}

		if (typeof renderer === 'function') {
			return function() {
				return renderer.apply(provider, arguments) || ''; // use correct `this` and always return a string
			};
		}

		// the rendered can be a plain string as well. if not specified, always an empty string.
		return function() {
			return renderer || '';
		};
	}

});
