/*******************************************************************************
 * Copyright (c) 2011, 2013 Formal Mind GmbH and University of Dusseldorf.
 * 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:
 *     Michael Jastram - initial API and implementation
 ******************************************************************************/
package org.eclipse.rmf.reqif10.pror.editor.agilegrid;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.agilemore.agilegrid.AbstractContentProvider;
import org.agilemore.agilegrid.AgileGrid;
import org.agilemore.agilegrid.IContentProvider;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.util.EContentAdapter;
import org.eclipse.rmf.reqif10.AttributeValue;
import org.eclipse.rmf.reqif10.Identifiable;
import org.eclipse.rmf.reqif10.ReqIF;
import org.eclipse.rmf.reqif10.SpecElementWithAttributes;
import org.eclipse.rmf.reqif10.SpecHierarchy;
import org.eclipse.rmf.reqif10.SpecObject;
import org.eclipse.rmf.reqif10.SpecRelation;
import org.eclipse.rmf.reqif10.Specification;
import org.eclipse.rmf.reqif10.XhtmlContent;
import org.eclipse.rmf.reqif10.common.util.ProrXhtmlSimplifiedHelper;
import org.eclipse.rmf.reqif10.common.util.ReqIF10Util;
import org.eclipse.rmf.reqif10.pror.configuration.Column;
import org.eclipse.rmf.reqif10.pror.configuration.ProrSpecViewConfiguration;
import org.eclipse.rmf.reqif10.pror.configuration.UnifiedColumn;
import org.eclipse.rmf.reqif10.pror.editor.agilegrid.ProrRow.ProrRowSpecHierarchy;
import org.eclipse.rmf.reqif10.pror.editor.agilegrid.ProrRow.ProrRowSpecRelation;
import org.eclipse.rmf.reqif10.pror.filter.ReqifFilter;

/**
 * This ContentProvider manages a {@link Specification}, to be displayed in an
 * {@link AgileGrid}.
 */
public class ProrAgileGridContentProvider extends AbstractContentProvider {

	private final Specification root;
	final ProrSpecViewConfiguration specViewConfig;
	private ArrayList<ProrRow> cache = null;
	private Map<Identifiable, ProrRow> rowMap = new HashMap<Identifiable, ProrRow>();

	private boolean showSpecRelations;
	private ReqifFilter filter;

	public ProrAgileGridContentProvider(Specification specification,
			ProrSpecViewConfiguration specViewConfig) {
		this.root = specification;
		this.specViewConfig = specViewConfig;

		// TODO We want to be more nuanced.
		specification.eAdapters().add(new EContentAdapter() {
			@Override
			public void notifyChanged(Notification notification) {
				super.notifyChanged(notification);
				if (notification.getEventType() == Notification.ADD
						|| notification.getEventType() == Notification.ADD_MANY
						|| notification.getEventType() == Notification.MOVE
						|| notification.getEventType() == Notification.REMOVE
						|| notification.getEventType() == Notification.REMOVE_MANY
						|| notification.getEventType() == Notification.SET
						|| notification.getEventType() == Notification.UNSET) {
					flushCache();
				}
			}
		});
	}

	/**
	 * Sets a filter. The null argument resets filtering.
	 */
	public void setFilter(ReqifFilter filter) {
		if (filter != this.filter) {
			this.filter = filter;
			flushCache();
		}
	}

	/**
	 * Returns the {@link AttributeValue} for the given column for the element
	 * associated with the row. May return null.
	 */
	@Override
	public Object doGetContentAt(int row, int col)
			throws IndexOutOfBoundsException {
		if (row >= getCache().size()) {
			throw new IndexOutOfBoundsException("Row does not exist: " + row);
		}

		ProrRow prorRow = getCache().get(row);
		if (!prorRow.isVisible()) {
			return null;
		}

		SpecElementWithAttributes element = prorRow.getSpecElement();

		if (col == specViewConfig.getColumns().size()) {
			// For the Link column, we return the linked element.
			return element instanceof SpecElementWithAttributes ? element
					: null;
		} else if (col <= specViewConfig.getColumns().size()) {
			// we return the AttributeValue.
			return getValueForColumn(element, row, col);
		} else {
			throw new IndexOutOfBoundsException("Column does not exist: " + col);
		}
	}

	/**
	 * Changes the Value through the editing domain if it has changed.
	 * <p>
	 * 
	 * We don't need to change anything here, as changing the
	 * {@link AttributeValue} automagically updates the model.
	 */
	@Override
	public void doSetContentAt(int row, int col, Object newValue) {
	}

	/**
	 * Whether to show {@link SpecRelation}s as part of the Content.
	 * 
	 * @param status
	 */
	public void setShowSpecRelations(boolean status) {
		this.showSpecRelations = status;
		for (ProrRow row : getCache()) {
			if (row instanceof ProrRowSpecHierarchy)
				((ProrRowSpecHierarchy) row).setShowSpecRelation(status);
		}
		flushCache();
	}

	/**
	 * Whether to show {@link SpecRelation}s as part of the Content.
	 */
	public boolean getShowSpecRelations() {
		return this.showSpecRelations;
	}

	/**
	 * Finds the Object for the given row, which may be a SpecHierarchy or
	 * SpecRelation.
	 */
	ProrRow getProrRow(int row) {
		if (row >= 0) {
			return getCache().get(row);
		}
		return null;
	}

	public void flushCache() {
		cache = null;
	}

	/**
	 * Uses a Job to provider feedback to the user.
	 * 
	 * @return
	 */
	private ArrayList<ProrRow> getCache() {
		if (cache == null) {
			ArrayList<ProrRow> tmpCache = new ArrayList<ProrRow>();
			recurseSpecHierarchyForRow(0, 0, root.getChildren(), tmpCache);
			cache = tmpCache;
		}
		return cache;
	}

	private ProrRow getProrRowForSpecElement(Identifiable e, int row, int level) {
		ProrRow prorRow = rowMap.get(e);
		if (prorRow == null) {
			prorRow = ProrRow.createProrRow(e, row, level);
			rowMap.put(e, prorRow);
		} else {
			prorRow.setLevel(row);
			prorRow.setLevel(level);
		}
		return prorRow;
	}

	/**
	 * 
	 * @param current
	 *            The current counter
	 * @param elements
	 *            The {@link SpecHierarchy}s to traverse, Can be SpecHierarchies
	 *            or SpecRelations
	 * @param tmpCache
	 * @return either the {@link ProrRow} with the given row, or the new current
	 *         row
	 */
	private int recurseSpecHierarchyForRow(int current, int depth,
			List<SpecHierarchy> elements, ArrayList<ProrRow> tmpCache) {
		for (SpecHierarchy element : elements) {
			ProrRowSpecHierarchy prorRowSH = (ProrRowSpecHierarchy) getProrRowForSpecElement(
					element, current, depth);
			if (filter != null && !filter.match(element.getObject())) {
				prorRowSH.setVisible(false);
			} else {
				prorRowSH.setVisible(true);
			}
			tmpCache.add(current, prorRowSH);
			if (prorRowSH.isShowSpecRelation()) {
				for (SpecRelation specRelation : getSpecRelationsFor(element)) {
					++current;
					ProrRowSpecRelation prorRowSR = (ProrRowSpecRelation) getProrRowForSpecElement(
							specRelation, current, depth + 1);
					tmpCache.add(current, prorRowSR);
				}
			}
			int result = recurseSpecHierarchyForRow(++current, depth + 1,
					element.getChildren(), tmpCache);
			current = result;
		}
		return current;
	}

	/**
	 * Returns the actual {@link AttributeValue} for the given Column and the
	 * given {@link SpecElementWithUserDefinedAttributes}
	 */
	AttributeValue getValueForColumn(SpecElementWithAttributes element,
			int row, int col) {
		// Knock-out criteria
		if (element == null)
			return null;
		if (col >= specViewConfig.getColumns().size())
			return null;

		// Handle the Unified Column
		Column column = specViewConfig.getColumns().get(col);
		if (column instanceof UnifiedColumn) {
			AttributeValue av = ReqIF10Util.getAttributeValueForLabel(element,
					"ReqIF.ChapterName");
			if (av != null && ReqIF10Util.getTheValue(av) != null) {
				Object value = ReqIF10Util.getTheValue(av);
				if (value instanceof XhtmlContent) {
					XhtmlContent xhtmlContent = (XhtmlContent) value;
					String s = ProrXhtmlSimplifiedHelper
							.xhtmlToSimplifiedString(xhtmlContent);
					if (s != null && s.trim().length() > 0) {
						return av;
					}

				} else {
					if (value.toString().trim().length() > 0) {
						return av;
					}
				}
			}
			return ReqIF10Util.getAttributeValueForLabel(element, "ReqIF.Text");
		}

		String label = column.getLabel();

		return ReqIF10Util.getAttributeValueForLabel(element, label);
	}

	/**
	 * Returns the SpecRelations that use the given SpecObject (via the given
	 * SpecHierarchy) as a source. This method checks {@link #showSpecRelations}
	 * and returns immediately if it is false.
	 */
	private List<SpecRelation> getSpecRelationsFor(SpecHierarchy specHierarchy) {
		if (specHierarchy.getObject() == null)
			return Collections.emptyList();
		SpecObject source = specHierarchy.getObject();
		ReqIF reqif = ReqIF10Util.getReqIF(source);
		// Can happen if source is detached from the reqif model (e.g. just
		// being deleted)
		if (reqif == null)
			return Collections.emptyList();
		List<SpecRelation> list = new ArrayList<SpecRelation>();
		for (SpecRelation relation : reqif.getCoreContent().getSpecRelations()) {
			if (source.equals(relation.getSource())) {
				list.add(relation);
			}
		}
		return list;
	}

	void updateElement(SpecElementWithAttributes element) {
		recurseUpdateElement(0, element, root.getChildren());
		flushCache();
	}

	/**
	 * Recurses over all SpecHierarchies and updates wherever it finds the given
	 * specObject. As a specObject can appear multiple time, we have to cover
	 * the whole tree.
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private int recurseUpdateElement(int row,
			SpecElementWithAttributes element, List list) {
		for (Object entry : list) {
			List children = new ArrayList();
			boolean refresh = false;
			if (element instanceof SpecRelation && element.equals(entry)) {
				refresh = true;
			} else if (entry instanceof SpecHierarchy) {
				SpecHierarchy specHierarchy = (SpecHierarchy) entry;
				children.addAll(specHierarchy.getChildren());

				ProrRow prorRow = rowMap.get(specHierarchy);
				if (prorRow != null && prorRow instanceof ProrRowSpecHierarchy) {
					if (((ProrRowSpecHierarchy) prorRow).isShowSpecRelation())
						children.addAll(getSpecRelationsFor(specHierarchy));
				}

				if (element.equals(specHierarchy.getObject())) {
					refresh = true;
				}
			}
			// Workaround: provide null for "old value" to force a recognition
			// of
			// the change.
			if (refresh) {
				firePropertyChange(IContentProvider.Content, row, 0, null,
						entry);
			}
			row++;
			row = recurseUpdateElement(row, element, children);
		}
		return row;
	}

	public int getRowCount() {
		return getCache().size();
	}	
}
