/*******************************************************************************
 * Copyright (c) 2012 Original authors and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Original authors and others - initial API and implementation
 ******************************************************************************/
package org.eclipse.nebula.widgets.nattable.tree;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.eclipse.nebula.widgets.nattable.command.ILayerCommand;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.hideshow.AbstractRowHideShowLayer;
import org.eclipse.nebula.widgets.nattable.hideshow.command.MultiRowHideCommand;
import org.eclipse.nebula.widgets.nattable.hideshow.command.RowHideCommand;
import org.eclipse.nebula.widgets.nattable.hideshow.event.HideRowPositionsEvent;
import org.eclipse.nebula.widgets.nattable.hideshow.event.ShowRowPositionsEvent;
import org.eclipse.nebula.widgets.nattable.layer.IUniqueIndexLayer;
import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
import org.eclipse.nebula.widgets.nattable.layer.cell.IConfigLabelAccumulator;
import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
import org.eclipse.nebula.widgets.nattable.painter.cell.BackgroundPainter;
import org.eclipse.nebula.widgets.nattable.painter.cell.ICellPainter;
import org.eclipse.nebula.widgets.nattable.painter.cell.decorator.CellPainterDecorator;
import org.eclipse.nebula.widgets.nattable.tree.command.TreeExpandCollapseCommandHandler;
import org.eclipse.nebula.widgets.nattable.tree.config.DefaultTreeLayerConfiguration;
import org.eclipse.nebula.widgets.nattable.tree.painter.IndentedTreeImagePainter;
import org.eclipse.nebula.widgets.nattable.ui.util.CellEdgeEnum;


public class TreeLayer extends AbstractRowHideShowLayer {

	public static final String TREE_COLUMN_CELL = "TREE_COLUMN_CELL"; //$NON-NLS-1$

	public static final int TREE_COLUMN_NUMBER = 0;

	private final ITreeRowModel<?> treeRowModel;

	private final Set<Integer> hiddenRowIndexes;

	private IndentedTreeImagePainter indentedTreeImagePainter;
	private ICellPainter treeImagePainter;
	
	public TreeLayer(IUniqueIndexLayer underlyingLayer, ITreeRowModel<?> treeRowModel) {
		this(underlyingLayer, treeRowModel, true);
	}
	
	public TreeLayer(IUniqueIndexLayer underlyingLayer, ITreeRowModel<?> treeRowModel, boolean useDefaultConfiguration) {
		super(underlyingLayer);
		this.treeRowModel = treeRowModel;

		this.hiddenRowIndexes = new TreeSet<Integer>();
		
		if (useDefaultConfiguration) {
			addConfiguration(new DefaultTreeLayerConfiguration(this));
		}
		
		setConfigLabelAccumulator(new IConfigLabelAccumulator() {
			@Override
			public void accumulateConfigLabels(LabelStack configLabels, int columnPosition, int rowPosition) {
				if (isTreeColumn(columnPosition)) {
					configLabels.addLabelOnTop(TREE_COLUMN_CELL);
				}
			}
		});

		indentedTreeImagePainter = new IndentedTreeImagePainter(treeRowModel);
		treeImagePainter = indentedTreeImagePainter.getTreeImagePainter();

		registerCommandHandler(new TreeExpandCollapseCommandHandler(this));
	}

	public ITreeRowModel<?> getModel() {
		return this.treeRowModel;
	}

	/**
	 * @return the treeImagePainter
	 */
	public ICellPainter getTreeImagePainter() {
		return treeImagePainter;
	}
	
	private boolean isTreeColumn(int columnPosition) {
		return columnPosition == TREE_COLUMN_NUMBER;
	}
	
	@Override
	public ICellPainter getCellPainter(int columnPosition, int rowPosition, ILayerCell cell, IConfigRegistry configRegistry) {
		ICellPainter cellPainter = super.getCellPainter(columnPosition, rowPosition, cell, configRegistry);
		
		if (cell.getConfigLabels().hasLabel(TREE_COLUMN_CELL)) {
			cellPainter = new BackgroundPainter(new CellPainterDecorator(cellPainter, CellEdgeEnum.LEFT, indentedTreeImagePainter));
		}
		
		return cellPainter;
	}

	@Override
	public boolean isRowIndexHidden(int rowIndex) {
		return this.hiddenRowIndexes.contains(Integer.valueOf(rowIndex)) || isHiddenInUnderlyingLayer(rowIndex);
	}

	@Override
	public Collection<Integer> getHiddenRowIndexes() {
		return this.hiddenRowIndexes;
	}

	/**
	 * Performs an expand/collapse action dependent on the current state of the tree node
	 * at the given row index.
	 * @param parentIndex The index of the row that shows the tree node for which the
	 * 			expand/collapse action should be performed.
	 */
	public void expandOrCollapseIndex(int parentIndex) {
		if (this.treeRowModel.isCollapsed(parentIndex)) {
			expandTreeRow(parentIndex);
		} else {
			collapseTreeRow(parentIndex);
		}
	}

	/**
	 * Collapses the tree node for the given row index.
	 * @param parentIndex The index of the row that shows the node that should be collapsed
	 */
	public void collapseTreeRow(int parentIndex) {
		List<Integer> rowIndexes = this.treeRowModel.collapse(parentIndex);
		List<Integer> rowPositions = new ArrayList<Integer>();
		for (Integer rowIndex : rowIndexes) {
			int rowPos = getRowPositionByIndex(rowIndex);
			//if the rowPos is negative, it is not visible because of hidden state in an underlying layer
			if (rowPos >= 0) {
				rowPositions.add(rowPos);
			}
		}
		this.hiddenRowIndexes.addAll(rowIndexes);
		invalidateCache();
		fireLayerEvent(new HideRowPositionsEvent(this, rowPositions));
	}

	/**
	 * Expands the tree node for the given row index.
	 * @param parentIndex The index of the row that shows the node that should be expanded
	 */
	public void expandTreeRow(int parentIndex) {
		List<Integer> rowIndexes = 	this.treeRowModel.expand(parentIndex);
		this.hiddenRowIndexes.removeAll(rowIndexes);
		invalidateCache();
		fireLayerEvent(new ShowRowPositionsEvent(this, rowIndexes));
	}
	
	/**
	 * Checks the underlying layer if the row is hidden by another layer.
	 * @param rowIndex The index of the row whose hidden state should be checked
	 * @return <code>true</code> if the row at the given index is hidden in the underlying layer
	 * 			<code>false</code> if not.
	 */
	private boolean isHiddenInUnderlyingLayer(int rowIndex) {
		IUniqueIndexLayer underlyingLayer = (IUniqueIndexLayer) getUnderlyingLayer();
		return (underlyingLayer.getRowPositionByIndex(rowIndex) == -1);
	}
	
	@Override
	public boolean doCommand(ILayerCommand command) {
		//special command transformations are needed to hide also child nodes
		if (command instanceof RowHideCommand) {
			return handleRowHideCommand((RowHideCommand)command);
		} else if (command instanceof MultiRowHideCommand) {
			return handleMultiRowHideCommand((MultiRowHideCommand)command);
		}
		return super.doCommand(command);
	}
	
	/**
	 * Checks if the given command tries to hide a row that is a node that is not collapsed and has children.
	 * In that case also the child rows need to be hidden. 
	 * @param command The {@link RowHideCommand} to process
	 * @return <code>true</code> if the command has been handled, <code>false</code> otherwise
	 */
	protected boolean handleRowHideCommand(RowHideCommand command) {
		//transform position to index
		if (command.convertToTargetLayer(this)) {
			int rowIndex = getRowIndexByPosition(command.getRowPosition());
			if (this.treeRowModel.hasChildren(rowIndex) && !this.treeRowModel.isCollapsed(rowIndex)) {
				List<Integer> childIndexes = this.treeRowModel.getChildIndexes(rowIndex);
				int[] childPositions = new int[childIndexes.size()+1];
				childPositions[0] = command.getRowPosition();
				for (int i = 1; i < childIndexes.size()+1; i++) {
					int childPos = getRowPositionByIndex(childIndexes.get(i-1));
					childPositions[i] = childPos;
				}
				return super.doCommand(new MultiRowHideCommand(this, childPositions));
			}
		}
		return super.doCommand(command);
	}
	
	/**
	 * Checks if the given command tries to hide rows that are nodes that are not collapsed and have children.
	 * In that case also the child rows need to be hidden. 
	 * @param command The {@link MultiRowHideCommand} to process
	 * @return <code>true</code> if the command has been handled, <code>false</code> otherwise
	 */
	protected boolean handleMultiRowHideCommand(MultiRowHideCommand command) {
		//transform position to index
		if (command.convertToTargetLayer(this)) {
			List<Integer> rowPositionsToHide = new ArrayList<Integer>();
			for (Integer rowPos : command.getRowPositions()) {
				rowPositionsToHide.add(rowPos);
				int rowIndex = getRowIndexByPosition(rowPos);
				if (this.treeRowModel.hasChildren(rowIndex) && !this.treeRowModel.isCollapsed(rowIndex)) {
					List<Integer> childIndexes = this.treeRowModel.getChildIndexes(rowIndex);
					for (Integer childIndex : childIndexes) {
						rowPositionsToHide.add(getRowPositionByIndex(childIndex));
					}
				}
			}
			
			int[] childPositions = new int[rowPositionsToHide.size()];
			for (int i = 0; i < rowPositionsToHide.size(); i++) {
				childPositions[i] = rowPositionsToHide.get(i);
			}
			return super.doCommand(new MultiRowHideCommand(this, childPositions));
		}
		return super.doCommand(command);
	}
}
