define([
	'./GridFromHtml',
	'./ColumnSet',
	'dojo/_base/declare'
], function (GridFromHtml, ColumnSet, declare) {
	// summary:
	//		This module augments GridFromHtml with additional support for interpreting
	//		ColumnSets from colgroups in table markup.

	function getColumnSetsFromDom(domNode) {
		// summary:
		//		Generates ColumnSets from DOM.

		var columnsets = [], // to be pushed upon / returned
			cgspans = [], // stores info on columnset sizes (colgroup span)
			rowspans = [], // will store info on any "unexhausted" rowspans
			colgroups = domNode.getElementsByTagName('colgroup'),
			cglen = colgroups.length,
			trs = domNode.getElementsByTagName('tr'),
			trslen = trs.length,
			getNum = GridFromHtml.utils.getNumFromAttr,
			getCol = GridFromHtml.utils.getColumnFromCell,
			// used in loops:
			currcol, // keeps track of what column we're at
			currcg, // and which colgroup
			groupColumns,
			tr,
			ths,
			thslen,
			i,
			j,
			tmp;

		function incCurrcol(amount) {
			// Check whether we've passed into the next colgroup within current row.
			// (Used within th loop)
			currcol += amount;
			tmp = cgspans[currcg];
			if (currcol >= tmp) {
				// First, push info for the set we just finished:
				// (i is still the active row index from the for loop)
				columnsets[currcg][i] = groupColumns;

				// Now, time to move on to the next columnset for this row.
				currcol -= tmp;
				currcg++;
				groupColumns = [];
			}
		}

		// no need for ColumnSet unless there's >1 colgroup
		if (cglen < 2) {
			return false;
		}

		// read span from each colgroup (defaults to 1)
		for (i = 0; i < cglen; i++) {
			// store number of cells this column spans
			tmp = getNum(colgroups[i], 'span') || 1;
			cgspans[i] = tmp;
			// add nested array to return value to be populated for this set
			columnsets[i] = [];
			// initialize inner rowspan-tracking array for each
			rowspans[i] = [];
			for (j = 0; j < tmp; j++) {
				rowspans[i][j] = 0;
			}
		}

		for (i = 0; i < trslen; i++) {
			currcol = currcg = 0;
			groupColumns = [];
			tr = trs[i];
			ths = tr.getElementsByTagName('th');
			thslen = ths.length;
			for (j = 0; j < thslen; j++) {
				// account for space occupied by previous rowSpans
				while (rowspans[currcg][currcol]) {
					// decrement rowspan "leftover" for next iteration
					rowspans[currcg][currcol]--;
					// skip past this cell for now, and try again w/ updated currcg/col
					incCurrcol(1);
				}

				// store cell info
				tmp = getCol(ths[j]);
				groupColumns.push(tmp);

				// if this cell has rowspan, keep that in mind for future iterations
				rowspans[currcg][currcol] = tmp.rowSpan ? tmp.rowSpan - 1 : 0;

				// increment currcol/currcg appropriately, accounting for cell colSpan
				incCurrcol(tmp.colSpan || 1);
			}
			// At the end of processing each row, there is a chance that the last
			// column set didn't get pushed yet (specifically if there are trailing
			// rowspans - since rowspan "debt" gets iterated at the beginning of each
			// iteration, not the end).  In that case, push the last one now.
			if (groupColumns.length) {
				columnsets[currcg][i] = groupColumns;
			}
		}
		if (tr) {
			domNode.removeChild(tr.parentNode);
		}
		return columnsets;
	}
	return declare([GridFromHtml, ColumnSet], {
		configStructure: function () {
			// summary:
			//		Configure subRows based on HTML originally in srcNodeRef

			var tmp;
			if (!this._checkedTrs) {
				tmp = getColumnSetsFromDom(this.srcNodeRef);
				if (tmp) {
					this.columnSets = tmp;
					this._checkedTrs = true;
				}
				else {
					// no reason to worry about ColumnSets, let GridFromHtml do the job
					return this.inherited(arguments);
				}
			}
			return this.inherited(arguments);
		}
	});
});