package de.prob2.ui.consoles.b;

import com.google.inject.Inject;

import de.prob.animator.command.EvaluationCommand;
import de.prob.animator.domainobjects.AbstractEvalResult;
import de.prob.animator.domainobjects.ClassicalB;
import de.prob.animator.domainobjects.EvaluationException;
import de.prob.animator.domainobjects.IEvalElement;
import de.prob.exception.CliError;
import de.prob.exception.ProBError;
import de.prob.scripting.ClassicalBFactory;
import de.prob.scripting.ModelTranslationError;
import de.prob.statespace.AnimationSelector;
import de.prob.statespace.IAnimationChangeListener;
import de.prob.statespace.StateSpace;
import de.prob.statespace.Trace;

import de.prob2.ui.consoles.ConsoleExecResult;
import de.prob2.ui.consoles.ConsoleExecResultType;
import de.prob2.ui.consoles.ConsoleInstruction;
import de.prob2.ui.consoles.Executable;

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

public class BInterpreter implements IAnimationChangeListener, Executable {

	private static final Logger logger = LoggerFactory.getLogger(BInterpreter.class);
	private final StateSpace defaultSS;
	private Trace currentTrace;

	@Inject
	public BInterpreter(final ClassicalBFactory bfactory, final AnimationSelector animations) {
		StateSpace s = null;
		try {
			s = bfactory.create("MACHINE Empty END").load();
		} catch (CliError | ModelTranslationError | ProBError e) {
			logger.error("loading a model into ProB failed!", e);
		}
		defaultSS = s;
		animations.registerAnimationChangeListener(this);
	}

	@Override
	public ConsoleExecResult exec(final ConsoleInstruction instruction) {
		String line = instruction.getInstruction();
		AbstractEvalResult res;
		try {
			if ("clear".equals(instruction.getInstruction())) {
				return new ConsoleExecResult("clear","", ConsoleExecResultType.PASSED);
			}
			IEvalElement parsed = parse(line);
			if (currentTrace == null) {
				EvaluationCommand cmd = parsed.getCommand(defaultSS.getRoot());
				defaultSS.execute(cmd);
				res = cmd.getValue();
			} else {
				res = currentTrace.evalCurrent(parsed);
			}
		} catch (CliError | EvaluationException | ProBError e) {
			logger.info("B evaluation failed", e);
			return new ConsoleExecResult("", "Invalid syntax: " + e.getMessage(), ConsoleExecResultType.ERROR) ;
		}
		// noinspection ObjectToString
		return new ConsoleExecResult("", res.toString(), ConsoleExecResultType.PASSED);
	}
	
	public IEvalElement parse(final String line) {
		if (currentTrace == null) {
			return new ClassicalB(line);
		}
		return currentTrace.getModel().parseFormula(line);
	}
		
	@Override
	public void traceChange(final Trace currentTrace, final boolean currentAnimationChanged) {
		if (currentAnimationChanged) {
			this.currentTrace = currentTrace;
		}
	}

	@Override
	public void animatorStatus(final boolean busy) {
		// Not used
	}
}

@@ -282,60 +282,8 @@
 on;%0A
-import de.prob.animator.domainobjects.IEvalElement;%0A
 impo
@@ -445,105 +445,8 @@
 or;%0A
-import de.prob.statespace.AnimationSelector;%0Aimport de.prob.statespace.IAnimationChangeListener;%0A
 impo
@@ -482,41 +482,8 @@
 ace;
-%0Aimport de.prob.statespace.Trace;
 %0A%0Aim
@@ -665,16 +665,57 @@
 cutable;
+%0Aimport de.prob2.ui.prob2fx.CurrentTrace;
 %0A%0Aimport
@@ -806,34 +806,8 @@
 ents
- IAnimationChangeListener,
  Exe
@@ -946,16 +946,23 @@
 private 
+Current
 Trace cu
@@ -1048,36 +1048,33 @@
 nal 
-AnimationSelector animations
+CurrentTrace currentTrace
 ) %7B%0A
@@ -1301,56 +1301,40 @@
 ;%0A%09%09
-animations.registerAnimationChangeListener(this)
+this.currentTrace = currentTrace
 ;%0A%09%7D
@@ -1640,71 +1640,132 @@
 %0A%09%09%09
-IEvalElement parsed = parse(line);%0A%09%09%09if (currentTrace == null)
+if (currentTrace.exists()) %7B%0A%09%09%09%09res = currentTrace.get().evalCurrent(currentTrace.getModel().parseFormula(line));%0A%09%09%09%7D else
  %7B%0A%09
@@ -1791,22 +1791,36 @@
 d cmd = 
-parsed
+new ClassicalB(line)
 .getComm
@@ -1903,64 +1903,8 @@
 ();%0A
-%09%09%09%7D else %7B%0A%09%09%09%09res = currentTrace.evalCurrent(parsed);%0A
 %09%09%09%7D
@@ -2235,440 +2235,6 @@
 %0A%09%7D%0A
-%09%0A%09public IEvalElement parse(final String line) %7B%0A%09%09if (currentTrace == null) %7B%0A%09%09%09return new ClassicalB(line);%0A%09%09%7D%0A%09%09return currentTrace.getModel().parseFormula(line);%0A%09%7D%0A%09%09%0A%09@Override%0A%09public void traceChange(final Trace currentTrace, final boolean currentAnimationChanged) %7B%0A%09%09if (currentAnimationChanged) %7B%0A%09%09%09this.currentTrace = currentTrace;%0A%09%09%7D%0A%09%7D%0A%0A%09@Override%0A%09public void animatorStatus(final boolean busy) %7B%0A%09%09// Not used%0A%09%7D%0A
 %7D%0A

Use CurrentTrace instead of AnimationSelector in BInterpreter