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
		}
	}
	
}