import getRoleType from '../aria/get-role-type';
import isFocusable from '../dom/is-focusable';
import findUp from '../dom/find-up';
import getElementCoordinates from '../dom/get-element-coordinates';
import getViewportSize from '../dom/get-viewport-size';

/**
 * Determines whether a table is a data table
 * @method isDataTable
 * @memberof axe.commons.table
 * @instance
 * @param  {HTMLTableElement} node The table to test
 * @return {Boolean}
 * @see http://asurkov.blogspot.co.uk/2011/10/data-vs-layout-table.html
 */
function isDataTable(node) {
	var role = (node.getAttribute('role') || '').toLowerCase();

	// The element is not focusable and has role=presentation
	if ((role === 'presentation' || role === 'none') && !isFocusable(node)) {
		return false;
	}

	// Table inside editable area is data table always since the table structure is crucial for table editing
	if (
		node.getAttribute('contenteditable') === 'true' ||
		findUp(node, '[contenteditable="true"]')
	) {
		return true;
	}

	// Table having ARIA table related role is data table
	if (role === 'grid' || role === 'treegrid' || role === 'table') {
		return true;
	}

	// Table having ARIA landmark role is data table
	if (getRoleType(role) === 'landmark') {
		return true;
	}

	// Table having datatable="0" attribute is layout table
	if (node.getAttribute('datatable') === '0') {
		return false;
	}

	// Table having summary attribute is data table
	if (node.getAttribute('summary')) {
		return true;
	}

	// Table having legitimate data table structures is data table
	if (node.tHead || node.tFoot || node.caption) {
		return true;
	}
	// colgroup / col - colgroup is magically generated
	for (
		var childIndex = 0, childLength = node.children.length;
		childIndex < childLength;
		childIndex++
	) {
		if (node.children[childIndex].nodeName.toUpperCase() === 'COLGROUP') {
			return true;
		}
	}

	var cells = 0;
	var rowLength = node.rows.length;
	var row, cell;
	var hasBorder = false;
	for (var rowIndex = 0; rowIndex < rowLength; rowIndex++) {
		row = node.rows[rowIndex];
		for (
			var cellIndex = 0, cellLength = row.cells.length;
			cellIndex < cellLength;
			cellIndex++
		) {
			cell = row.cells[cellIndex];
			if (cell.nodeName.toUpperCase() === 'TH') {
				return true;
			}
			if (
				!hasBorder &&
				(cell.offsetWidth !== cell.clientWidth ||
					cell.offsetHeight !== cell.clientHeight)
			) {
				hasBorder = true;
			}
			if (
				cell.getAttribute('scope') ||
				cell.getAttribute('headers') ||
				cell.getAttribute('abbr')
			) {
				return true;
			}
			if (
				['columnheader', 'rowheader'].includes(
					(cell.getAttribute('role') || '').toLowerCase()
				)
			) {
				return true;
			}
			// abbr element as a single child element of table cell
			if (
				cell.children.length === 1 &&
				cell.children[0].nodeName.toUpperCase() === 'ABBR'
			) {
				return true;
			}
			cells++;
		}
	}

	// Table having nested table is layout table
	if (node.getElementsByTagName('table').length) {
		return false;
	}

	// Table having only one row or column is layout table (row)
	if (rowLength < 2) {
		return false;
	}

	// Table having only one row or column is layout table (column)
	var sampleRow = node.rows[Math.ceil(rowLength / 2)];
	if (sampleRow.cells.length === 1 && sampleRow.cells[0].colSpan === 1) {
		return false;
	}

	// Table having many columns (>= 5) is data table
	if (sampleRow.cells.length >= 5) {
		return true;
	}

	// Table having borders around cells is data table
	if (hasBorder) {
		return true;
	}

	// Table having differently colored rows is data table
	var bgColor, bgImage;
	for (rowIndex = 0; rowIndex < rowLength; rowIndex++) {
		row = node.rows[rowIndex];
		if (
			bgColor &&
			bgColor !==
				window.getComputedStyle(row).getPropertyValue('background-color')
		) {
			return true;
		} else {
			bgColor = window
				.getComputedStyle(row)
				.getPropertyValue('background-color');
		}
		if (
			bgImage &&
			bgImage !==
				window.getComputedStyle(row).getPropertyValue('background-image')
		) {
			return true;
		} else {
			bgImage = window
				.getComputedStyle(row)
				.getPropertyValue('background-image');
		}
	}

	// Table having many rows (>= 20) is data table
	if (rowLength >= 20) {
		return true;
	}

	// Wide table (more than 95% of the document width) is layout table
	if (
		getElementCoordinates(node).width >
		getViewportSize(window).width * 0.95
	) {
		return false;
	}

	// Table having small amount of cells (<= 10) is layout table
	if (cells < 10) {
		return false;
	}

	// Table containing embed, object, applet of iframe elements (typical advertisements elements) is layout table
	if (node.querySelector('object, embed, iframe, applet')) {
		return false;
	}

	// Otherwise it's data table
	return true;
}

export default isDataTable;