/**
   * Evaluates a valid expression and returns the resulting String in GeoGebra notation.
   *
   * @param casInput: in GeoGebraCAS syntax
   * @param useGeoGebraVariables: whether GeoGebra objects should be substituted before evaluation
   * @return evaluation result
   * @throws Throwable
   */
  public String evaluateGeoGebraCAS(ValidExpression casInput, boolean useGeoGebraVariables)
      throws Throwable {
    // convert parsed input to Maxima string
    String MaximaString = toMaximaString(casInput, useGeoGebraVariables);

    // Maxima simplification is turned off by default using simp:false;
    // We turn it on here using ev(command, simp) when KeepInput is not used
    if (!casInput.isKeepInputUsed()) {
      StringBuilder sb = new StringBuilder();
      sb.append("ev(");
      sb.append(MaximaString);
      sb.append(",simp)");
      MaximaString = sb.toString();
    }

    // EVALUATE input in Maxima
    String result = evaluateMaxima(MaximaString);

    // convert Maxima result back into GeoGebra syntax
    String ggbString = toGeoGebraString(result);

    // TODO: remove
    System.out.println("eval with Maxima: " + MaximaString);
    System.out.println("   result: " + result);
    System.out.println("   ggbString: " + ggbString);

    return ggbString;
  }
  /**
   * Evaluates the given ExpressionValue and returns the result in MathPiper syntax.
   *
   * @param resolveVariables: states whether variables from the GeoGebra kernel should be used. Note
   *     that this changes the given ExpressionValue.
   */
  public synchronized String toMaximaString(ValidExpression ve, boolean resolveVariables) {

    // resolve global variables
    if (resolveVariables) {
      casParser.resolveVariablesForCAS(ve);
    }

    // convert to Maxima String
    String MaximaStr = doToMaximaString(ve, resolveVariables);

    // handle assignments
    String veLabel = ve.getLabel();
    if (veLabel != null) {
      StringBuilder sb = new StringBuilder();

      if (ve instanceof FunctionNVar) {
        // function, e.g. f(x) := 2*x
        FunctionNVar fun = (FunctionNVar) ve;
        sb.append(veLabel);
        sb.append("(");
        sb.append(fun.getVarString());
        sb.append(") := ");

        // evaluate right hand side:
        // import for e.g. g(x) := Eval(D(x) x^2)
        // sb.append("Eval(");
        sb.append(MaximaStr);
        // sb.append(")");
        MaximaStr = sb.toString();
      } else {
        // assignment, e.g. a := 5
        MaximaStr = veLabel + " := " + MaximaStr;
      }
    }

    // TODO: remove
    //		System.out.println("CASmaxima.toMaxima: " + MaximaStr);
    return MaximaStr;
  }