package ca.queensu.cs.mase.generator.dispatchers;

import ca.queensu.cs.mase.urml.Attribute;
import ca.queensu.cs.mase.urml.BoolLiteral;
import ca.queensu.cs.mase.urml.ConditionalAndExpression;
import ca.queensu.cs.mase.urml.ConditionalOrExpression;
import ca.queensu.cs.mase.urml.Divide;
import ca.queensu.cs.mase.urml.Equal;
import ca.queensu.cs.mase.urml.Expression;
import ca.queensu.cs.mase.urml.FunctionCall;
import ca.queensu.cs.mase.urml.GreaterThan;
import ca.queensu.cs.mase.urml.GreaterThanOrEqual;
import ca.queensu.cs.mase.urml.Identifiable;
import ca.queensu.cs.mase.urml.Identifier;
import ca.queensu.cs.mase.urml.IncomingVariable;
import ca.queensu.cs.mase.urml.IntLiteral;
import ca.queensu.cs.mase.urml.LessThan;
import ca.queensu.cs.mase.urml.LessThanOrEqual;
import ca.queensu.cs.mase.urml.LocalVar;
import ca.queensu.cs.mase.urml.Minus;
import ca.queensu.cs.mase.urml.Modulo;
import ca.queensu.cs.mase.urml.Multiply;
import ca.queensu.cs.mase.urml.NotBooleanExpression;
import ca.queensu.cs.mase.urml.NotEqual;
import ca.queensu.cs.mase.urml.Plus;
import ca.queensu.cs.mase.urml.UnaryExpression;
import java.util.Arrays;
import org.eclipse.emf.common.util.EList;
import org.eclipse.xtend2.lib.StringConcatenation;

/**
 * A code generator for expressions
 */
@SuppressWarnings("all")
public class ExpressionGenerator {
  protected String _express(final Expression exp) {
    String _express = this.express(exp);
    String _plus = ("(" + _express);
    return (_plus + ")");
  }
  
  protected String _express(final IntLiteral exp) {
    return Integer.toString(exp.getInt());
  }
  
  protected String _express(final BoolLiteral exp) {
    return Boolean.toString(exp.isTrue());
  }
  
  protected String _express(final NotBooleanExpression exp) {
    String _express = this.express(exp.getExp());
    return ("!" + _express);
  }
  
  protected String _express(final UnaryExpression exp) {
    String _express = this.express(exp.getExp());
    return ("-" + _express);
  }
  
  protected String _express(final ConditionalOrExpression exp) {
    StringConcatenation _builder = new StringConcatenation();
    String _express = this.express(exp.getLeft());
    _builder.append(_express);
    _builder.append(" || ");
    String _express_1 = this.express(exp.getRest());
    _builder.append(_express_1);
    return _builder.toString();
  }
  
  protected String _express(final ConditionalAndExpression exp) {
    StringConcatenation _builder = new StringConcatenation();
    String _express = this.express(exp.getLeft());
    _builder.append(_express);
    _builder.append(" && ");
    String _express_1 = this.express(exp.getRest());
    _builder.append(_express_1);
    return _builder.toString();
  }
  
  protected String _express(final Plus exp) {
    StringConcatenation _builder = new StringConcatenation();
    String _express = this.express(exp.getLeft());
    _builder.append(_express);
    _builder.append(" + ");
    String _express_1 = this.express(exp.getRest());
    _builder.append(_express_1);
    return _builder.toString();
  }
  
  protected String _express(final Minus exp) {
    StringConcatenation _builder = new StringConcatenation();
    String _express = this.express(exp.getLeft());
    _builder.append(_express);
    _builder.append(" - ");
    String _express_1 = this.express(exp.getRest());
    _builder.append(_express_1);
    return _builder.toString();
  }
  
  protected String _express(final Multiply exp) {
    String _express = this.express(exp.getLeft());
    String _plus = (_express + " * ");
    String _express_1 = this.express(exp.getRest());
    return (_plus + _express_1);
  }
  
  protected String _express(final Divide exp) {
    String _express = this.express(exp.getLeft());
    String _plus = (_express + " / ");
    String _express_1 = this.express(exp.getRest());
    return (_plus + _express_1);
  }
  
  protected String _express(final Modulo exp) {
    String _express = this.express(exp.getLeft());
    String _plus = (_express + " % ");
    String _express_1 = this.express(exp.getRest());
    return (_plus + _express_1);
  }
  
  protected String _express(final LessThanOrEqual exp) {
    String _express = this.express(exp.getLeft());
    String _plus = (_express + " <= ");
    String _express_1 = this.express(exp.getRest());
    return (_plus + _express_1);
  }
  
  protected String _express(final LessThan exp) {
    String _express = this.express(exp.getLeft());
    String _plus = (_express + " < ");
    String _express_1 = this.express(exp.getRest());
    return (_plus + _express_1);
  }
  
  protected String _express(final GreaterThanOrEqual exp) {
    String _express = this.express(exp.getLeft());
    String _plus = (_express + " >= ");
    String _express_1 = this.express(exp.getRest());
    return (_plus + _express_1);
  }
  
  protected String _express(final GreaterThan exp) {
    String _express = this.express(exp.getLeft());
    String _plus = (_express + " > ");
    String _express_1 = this.express(exp.getRest());
    return (_plus + _express_1);
  }
  
  protected String _express(final Equal exp) {
    String _express = this.express(exp.getLeft());
    String _plus = (_express + " == ");
    String _express_1 = this.express(exp.getRest());
    return (_plus + _express_1);
  }
  
  protected String _express(final NotEqual exp) {
    String _express = this.express(exp.getLeft());
    String _plus = (_express + " != ");
    String _express_1 = this.express(exp.getRest());
    return (_plus + _express_1);
  }
  
  protected String _express(final Identifier exp) {
    String _xblockexpression = null;
    {
      Identifiable identifiable = exp.getId();
      String _xifexpression = null;
      if ((identifiable instanceof Attribute)) {
        String _name = ((Attribute) identifiable).getName();
        _xifexpression = ("_a_" + _name);
      } else {
        String _xifexpression_1 = null;
        if ((identifiable instanceof LocalVar)) {
          String _name_1 = ((LocalVar) identifiable).getName();
          _xifexpression_1 = ("_l_" + _name_1);
        } else {
          String _xifexpression_2 = null;
          if ((identifiable instanceof IncomingVariable)) {
            String _name_2 = ((IncomingVariable) identifiable).getName();
            _xifexpression_2 = ("_i_" + _name_2);
          }
          _xifexpression_1 = _xifexpression_2;
        }
        _xifexpression = _xifexpression_1;
      }
      _xblockexpression = _xifexpression;
    }
    return _xblockexpression;
  }
  
  protected String _express(final FunctionCall exp) {
    String _name = exp.getCall().getName();
    String _plus = ("_f_" + _name);
    String _plus_1 = (_plus + "(");
    StringConcatenation _builder = new StringConcatenation();
    {
      EList<Expression> _params = exp.getParams();
      boolean _hasElements = false;
      for(final Expression param : _params) {
        if (!_hasElements) {
          _hasElements = true;
        } else {
          _builder.appendImmediate(",", "");
        }
        String _express = this.express(param);
        _builder.append(_express);
      }
    }
    String _plus_2 = (_plus_1 + _builder);
    return (_plus_2 + ")");
  }
  
  public String express(final Expression exp) {
    if (exp instanceof BoolLiteral) {
      return _express((BoolLiteral)exp);
    } else if (exp instanceof FunctionCall) {
      return _express((FunctionCall)exp);
    } else if (exp instanceof IntLiteral) {
      return _express((IntLiteral)exp);
    } else if (exp instanceof ConditionalAndExpression) {
      return _express((ConditionalAndExpression)exp);
    } else if (exp instanceof ConditionalOrExpression) {
      return _express((ConditionalOrExpression)exp);
    } else if (exp instanceof Divide) {
      return _express((Divide)exp);
    } else if (exp instanceof Equal) {
      return _express((Equal)exp);
    } else if (exp instanceof GreaterThan) {
      return _express((GreaterThan)exp);
    } else if (exp instanceof GreaterThanOrEqual) {
      return _express((GreaterThanOrEqual)exp);
    } else if (exp instanceof Identifier) {
      return _express((Identifier)exp);
    } else if (exp instanceof LessThan) {
      return _express((LessThan)exp);
    } else if (exp instanceof LessThanOrEqual) {
      return _express((LessThanOrEqual)exp);
    } else if (exp instanceof Minus) {
      return _express((Minus)exp);
    } else if (exp instanceof Modulo) {
      return _express((Modulo)exp);
    } else if (exp instanceof Multiply) {
      return _express((Multiply)exp);
    } else if (exp instanceof NotBooleanExpression) {
      return _express((NotBooleanExpression)exp);
    } else if (exp instanceof NotEqual) {
      return _express((NotEqual)exp);
    } else if (exp instanceof Plus) {
      return _express((Plus)exp);
    } else if (exp instanceof UnaryExpression) {
      return _express((UnaryExpression)exp);
    } else if (exp != null) {
      return _express(exp);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(exp).toString());
    }
  }
}
