package org.eclipse.nebula.widgets.nattable.core.layer.impl.composite

import java.util.ArrayList
import java.util.List
import org.eclipse.nebula.widgets.nattable.core.command.Command
import org.eclipse.nebula.widgets.nattable.core.layer.Layer
import org.eclipse.nebula.widgets.nattable.core.layer.impl.AbstractLayer

/**
 * A Layer which is composed of a number of other layers. Sublayers are arranged in rows and columns to create this larger composite layer.
 * The resulting 'rows of layers' and 'columns of layers' are called 'composite columns' and 'composite rows' to avoid confusing them with
 * columns and rows within a layer.
 * 
 * It is assumed that the sublayers are arranged in such a way that their horizontal and vertical dimensions match up. Note
 * however that this is not enforced by the implementation: it is up to the user to configure the composite layer this way.
 * 
 * The composite layer uses the horizontal axes of the sublayers in the first composite row to characterize its composite horizontal axis,
 * and it uses the vertical axes of the sublayers in the first composite column to characterize its composite vertical axis.
 */
class CompositeLayer extends AbstractLayer {
	
	val List<CompositeRow> compositeRows = new ArrayList
	
	val horizontalAxis = new CompositeAxis(
		[ | compositeRows.get(0).childLayers ],
		[ layer | layer.horizontalAxis ]
	)
	val verticalAxis = new CompositeAxis(
		[ | compositeRows.map [ childLayers.get(0) ] ],
		[ layer | layer.verticalAxis ]
	)
	
	def getRows() { compositeRows }
	
	def addRow(Layer...childLayers) {
		compositeRows += new CompositeRow => [
			for (childLayer : childLayers) {
				childLayer.addEventListener(this)
				it.childLayers += childLayer
			}
		]
	}
	
	// Layer interface
	
	override CompositeAxis getHorizontalAxis() { horizontalAxis }
	override CompositeAxis getVerticalAxis() { verticalAxis }
	
	override getCell(int columnPosition, int rowPosition) {
		val xLayoutInfo = horizontalAxis.getSubLayerLayoutPositionInfo(columnPosition)
		val yLayoutInfo = verticalAxis.getSubLayerLayoutPositionInfo(rowPosition)
		
		val layer = compositeRows.get(yLayoutInfo.layoutPosition).childLayers.get(xLayoutInfo.layoutPosition)
		
		val subCell = layer.getCell(columnPosition - xLayoutInfo.segmentOffset, rowPosition - yLayoutInfo.segmentOffset)
		new CompositeCell(this, subCell, xLayoutInfo.segmentOffset, yLayoutInfo.segmentOffset)
	}
	
	override doCommand(Command command) {
		for (row : rows)
			for (childLayer : row.childLayers)
				childLayer.doCommand(command)
	}
	
	//
	
	def private CompositeLayoutInfo getSubLayerLayoutPositionInfo(CompositeAxis compositeAxis, int segmentPosition) {
		val subLayers = compositeAxis.subLayers
		val axisAccessor = compositeAxis.axisAccessor
		
		var segmentOffset = 0
		
		for (layoutPosition : 0 ..< subLayers.size) {
			val axis = axisAccessor.getAxis(subLayers.get(layoutPosition))
			
			if (segmentPosition < segmentOffset + axis.segmentCount)
				return new CompositeLayoutInfo(layoutPosition, segmentOffset)
			
			segmentOffset = segmentOffset + axis.segmentCount
		}
	}
	
}