/**
 *                                                                            
 * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
 *                                                                            
 * All rights reserved. This program and the accompanying materials           
 * are made available under the terms of the Eclipse Public License 2.0        
 * which accompanies this distribution, and is available at                  
 * https://www.eclipse.org/legal/epl-2.0/                                 
 *                                 
 * SPDX-License-Identifier: EPL-2.0                                 
 *                                                                            
 * Contributors:   
 * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation 
 */
package org.eclipse.osbp.xtext.reportdsl.common.item;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import org.eclipse.birt.report.model.api.CellHandle;
import org.eclipse.birt.report.model.api.DataSetHandle;
import org.eclipse.birt.report.model.api.GridHandle;
import org.eclipse.birt.report.model.api.ReportItemHandle;
import org.eclipse.birt.report.model.api.RowHandle;
import org.eclipse.birt.report.model.api.SlotHandle;
import org.eclipse.birt.report.model.api.activity.SemanticException;
import org.eclipse.birt.report.model.api.elements.structures.ComputedColumn;
import org.eclipse.birt.report.model.elements.TableColumn;
import org.eclipse.birt.report.model.elements.interfaces.IGridItemModel;
import org.eclipse.birt.report.model.elements.interfaces.IReportItemModel;
import org.eclipse.birt.report.model.util.CssPropertyConstants;
import org.eclipse.osbp.xtext.datamartdsl.DatamartAttribute;
import org.eclipse.osbp.xtext.datamartdsl.util.DatamartAttributeUtil;
import org.eclipse.osbp.xtext.reportdsl.DatamartTableAttribute;
import org.eclipse.osbp.xtext.reportdsl.Element;
import org.eclipse.osbp.xtext.reportdsl.Grid;
import org.eclipse.osbp.xtext.reportdsl.GridCell;
import org.eclipse.osbp.xtext.reportdsl.GridRow;
import org.eclipse.osbp.xtext.reportdsl.StringBinder;
import org.eclipse.osbp.xtext.reportdsl.StringBinderValue;
import org.eclipse.osbp.xtext.reportdsl.Style;
import org.eclipse.osbp.xtext.reportdsl.TableAggregation;
import org.eclipse.osbp.xtext.reportdsl.TableAttribute;
import org.eclipse.osbp.xtext.reportdsl.TableValueElement;
import org.eclipse.osbp.xtext.reportdsl.jvmmodel.ReportGeneratorWorkSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GridItem extends AContainerItem {

	private static final Logger LOGGER = LoggerFactory.getLogger(GridItem.class);
	private final GridHandle fItem;

	public GridItem(ReportGeneratorWorkSet workset, DataSetHandle dataSet, List<ComputedColumn> boundColumns, Grid grid) throws SemanticException {
		super(workset);
		int rowCount = grid.getRows().size();
		int columnCount = 0;
		int colspan = 0;
		for	(GridRow row : grid.getRows()) {
			int rowCellSpan = 0;
			int cellSize = row.getCells().size();
			for (GridCell cell : row.getCells()) {
				// "cell.getColumnspan() -1" is required cause without a colspan definition as minimum 1 column has to exist. 
				// Therefore columnCount is used as minimum size of column to be created.
				rowCellSpan = rowCellSpan + (cell.getColumnspan() -1);
			}
			colspan = Math.max(colspan, rowCellSpan);
			columnCount = Math.max(columnCount, cellSize);
		}
		// 'columnCount' times a column and a cell is created in newGridItem(String, int, int) ...
		fItem = workset.getFactory().newGridItem(null, columnCount, rowCount);
		// So the creation of the additional required columns without corresponding cells due to columnspan ... 
		for (int i = 0; i < colspan; i++) {
			TableColumn column = new TableColumn();
			fItem.getElement().add( column, IGridItemModel.COLUMN_SLOT );
		}
		List<Object> tableProperties = new ArrayList<>();
		HashSet<String> tableAttributeNameSet = new HashSet<String>();
		for (GridRow gridRow : grid.getRows()) {
			for (GridCell gridCell : gridRow.getCells()) {
				for (Element gridElement : gridCell.getElements()) {
					if (gridElement instanceof DatamartTableAttribute){
						TableValueElement tableValueElement = ((DatamartTableAttribute) gridElement).getColumn();
						if (tableValueElement instanceof TableAttribute){
							String attributeName = DatamartAttributeUtil.getAliasedAttributeName(((TableAttribute) tableValueElement).getValueRef());
							if (!tableAttributeNameSet.contains(attributeName)){
								tableProperties.add(tableValueElement);
								tableAttributeNameSet.add(attributeName);
							}
						} else {
							tableProperties.add(tableValueElement);
						}
					} else if (gridElement instanceof StringBinder){
						for (StringBinderValue element : ((StringBinder) gridElement).getElements()){
							if (element instanceof TableAttribute){
								String attributeName = DatamartAttributeUtil.getAliasedAttributeName(((TableAttribute) element).getValueRef());
								if (!tableAttributeNameSet.contains(attributeName)){
									tableProperties.add(element);
									tableAttributeNameSet.add(attributeName);
								}
							}
						}
					}
				}
			} 
		} 
		if (!tableProperties.isEmpty()){
			setDataSet(dataSet);
			List<ComputedColumn> requiredBoundColumns = new ArrayList<>();
			for (Object tableProperty : tableProperties) {
				TableAttribute tableAttribute = null;
				if (tableProperty instanceof TableAttribute){
					tableAttribute = (TableAttribute)tableProperty;
					addToRequiredBoundColumns(tableAttribute, boundColumns, requiredBoundColumns);
				}
			}
			setBoundColumns(requiredBoundColumns, tableProperties);
		}
	}

	public GridItem(ReportGeneratorWorkSet workset, String gridName, int columnCount, int rowCount) {
		super(workset);
		fItem = workset.getFactory().newGridItem(gridName, columnCount, rowCount);
	}

	private void addToRequiredBoundColumns(TableAttribute tableAttribute, List<ComputedColumn> boundColumns, List<ComputedColumn> requiredBoundColumns) {
		try {
			String tableAttributeName = DatamartAttributeUtil.getAliasedAttributeName(tableAttribute.getValueRef());
			for (ComputedColumn computedColumn : boundColumns) {
				if (computedColumn.getName().equalsIgnoreCase(tableAttributeName)){
					requiredBoundColumns.add(computedColumn);
					break;
				}
			}
		} catch (NullPointerException npe){
			LOGGER.error("NullPointerException on getting DatamartAttribute name!");
		}
	}

	@Override
	public ReportItemHandle getHandle() {
		return fItem;
	}

	@Override
	SlotHandle getSlotHandle() {
		return null;
	}

	public void applyRowStyle(int rowNo, Style style) {
		applyStyle(fWorkset.getDesign(), fItem.getRows().get(rowNo), style);
	}
	
	public void applyCellStyle(RowHandle rowHandle, int colNo, Style style) {
		applyStyle(fWorkset.getDesign(), rowHandle.getCells().get(colNo), style);
	}
	
	public void setRowHeight(int rowNo, double heightValue) throws SemanticException {
			String propValue = fWorkset.getLocalizedDoubleValue(fItem, heightValue);
			fItem.getRows().get(rowNo).setStringProperty(CssPropertyConstants.HEIGHT, propValue);
	}
	
	public CellItem getCell(int columnNo, int rowNo) throws SemanticException {
		RowHandle row = null;
		CellHandle cell = null;
		try {
			row = (RowHandle) fItem.getRows().get(rowNo);
			if	(row == null) {
				throw new SemanticException(fItem.getElement(), "can't resolve rowNo "+rowNo);
			}
		}
		catch (Exception e) {
			throw new SemanticException(fItem.getElement(), "can't resolve rowNo "+rowNo, e);
		}
		try {
			cell = (CellHandle)row.getCells().get(columnNo);
			if	(cell == null) {
				throw new SemanticException(fItem.getElement(), "can't resolve columnNo "+columnNo);
			}
		}
		catch (Exception e) {
			throw new SemanticException(fItem.getElement(), "can't resolve columnNo "+columnNo, e);
		}
		return new CellItem(fWorkset, cell);
	}
	
	public void setDataSet(DataSetHandle dataSet) {
		try {
			fItem.setDataSet(dataSet);
		} catch (SemanticException e) {
			LOGGER.error("{}", e);
		}
	}

	public void setBoundColumns(List<ComputedColumn> boundColumns, List<Object> tableProperties) {	// NOSONAR
		if	((boundColumns != null) && !boundColumns.isEmpty()) {
			List<ComputedColumn> shownColumns;

			// --- table details information: shown columns and maximum columns ---
			if	(tableProperties.size() == 0) {
				shownColumns = boundColumns;
			} else {
				shownColumns = new ArrayList<>();
				for	(Object tableProperty : tableProperties) {
					if	(tableProperty instanceof TableAggregation) {
						shownColumns.add(DataUtils.createComputedColumn((TableAggregation) tableProperty));
					} else if	(tableProperty instanceof TableAttribute) {
						addToShowColumns((TableAttribute)tableProperty, boundColumns, shownColumns);
					} else if (tableProperty instanceof StringBinder) {
						for (StringBinderValue binderValue : ((StringBinder)tableProperty).getElements()) {
							if (binderValue instanceof TableAttribute) {
								addToShowColumns((TableAttribute) binderValue, boundColumns, shownColumns);
							}
						}
					}
				}
			}
			// --- set all bound elements ---
			fItem.getElement().setProperty(IReportItemModel.BOUND_DATA_COLUMNS_PROP, shownColumns);
		}
	}

	private void addToShowColumns(TableAttribute tableAttribute, List<ComputedColumn> boundColumns, List<ComputedColumn> shownColumns) {
		for	(int columnNo=0; columnNo < boundColumns.size(); columnNo++) {
			DatamartAttribute datamartAttribute = tableAttribute.getValueRef();
			// attribute name modification as in org.eclipse.osbp.xtext.reportdsl.jvmmodel.ReportModelGenerator.addDatamartAttribute(...)
			// see also DatamartDSLJvmInferrer
			if	(boundColumns.get(columnNo).getName().equalsIgnoreCase(DatamartAttributeUtil.getAliasedAttributeName(datamartAttribute))) {
				shownColumns.add(boundColumns.get(columnNo));
				break;
			}
		}
	}
	

}
