package de.prob2.ui.states;

import java.util.Map;

import de.prob.animator.domainobjects.AbstractEvalResult;
import de.prob.animator.domainobjects.EnumerationWarning;
import de.prob.animator.domainobjects.EvalResult;
import de.prob.animator.domainobjects.EvaluationErrorResult;
import de.prob.animator.domainobjects.IEvalElement;
import de.prob.animator.domainobjects.IdentifierNotInitialised;
import de.prob.animator.domainobjects.StateError;
import de.prob.animator.domainobjects.WDError;
import de.prob.animator.prologast.ASTCategory;
import de.prob.animator.prologast.ASTFormula;

import javafx.scene.control.TreeTableCell;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

final class ValueCell extends TreeTableCell<StateItem<?>, StateItem<?>> {
	private static final Logger LOGGER = LoggerFactory.getLogger(ValueCell.class);
	
	private final Map<IEvalElement, AbstractEvalResult> values;
	private final boolean isCurrent;
	
	ValueCell(final Map<IEvalElement, AbstractEvalResult> values, final boolean isCurrent) {
		super();
		
		this.values = values;
		this.isCurrent = isCurrent;
	}
	
	@Override
	protected void updateItem(final StateItem<?> item, final boolean empty) {
		super.updateItem(item, empty);
		
		this.getStyleClass().removeAll("false", "true", "errorresult");
		
		if (item == null || empty) {
			this.setText(null);
			this.setGraphic(null);
		} else {
			final Object contents = item.getContents();
			
			if (contents instanceof String || contents instanceof ASTCategory) {
				this.setText(null);
			} else if (contents instanceof ASTFormula) {
				final AbstractEvalResult result = this.values.get(((ASTFormula)contents).getFormula());
				checkResult(result);
			} else if (contents instanceof StateError) {
				this.setText(this.isCurrent ? ((StateError)contents).getShortDescription() : null);
				this.getStyleClass().add("errorresult");
			} else {
				throw new IllegalArgumentException("Don't know how to show the value of a " + contents.getClass() + " instance");
			}
			this.setGraphic(null);
		}
	}

	private void checkResult(final AbstractEvalResult result) {
		if (result == null) {
			this.setText(null);
		} else if (result instanceof EvalResult) {
			final EvalResult eresult = (EvalResult)result;
			this.setText(eresult.getValue());
			if ("FALSE".equals(eresult.getValue())) {
				this.getStyleClass().add("false");
			} else if ("TRUE".equals(eresult.getValue())) {
				this.getStyleClass().add("true");
			}
		} else if (result instanceof IdentifierNotInitialised) {
			this.setText("(not initialized)");
			this.getStyleClass().add("errorresult");
		} else if (result instanceof WDError) {
			this.setText("(not well-defined)");
			this.getStyleClass().add("errorresult");
		} else if (result instanceof EvaluationErrorResult) {
			this.setText("Error: " + ((EvaluationErrorResult) result).getResult());
			this.getStyleClass().add("errorresult");
		} else if (result instanceof EnumerationWarning) {
			this.setText("(enumeration warning)");
			this.getStyleClass().add("errorresult");
		} else {
			LOGGER.warn("Unknown result type, falling back to toString: {}", result.getClass());
			// noinspection ObjectToString
			this.setText(result.getClass() + " toString: " + result);
		}
	}
}

@@ -579,16 +579,58 @@
 rmula;%0A%0A
+import javafx.scene.control.OverrunStyle;%0A
 import j
@@ -1134,16 +1134,77 @@
 urrent;%0A
+%09%09%0A%09%09this.setTextOverrun(OverrunStyle.CENTER_WORD_ELLIPSIS);%0A
 %09%7D%0A%09%0A%09@O

Truncate long StatesView values in the middle instead of at the end This matches ProB's style of truncating long values.