package ca.queensu.cs.mase.generator.capsules.members;

import ca.queensu.cs.mase.generator.dispatchers.ExpressionGenerator;
import ca.queensu.cs.mase.generator.dispatchers.StatementGenerator;
import ca.queensu.cs.mase.urml.ActionCode;
import ca.queensu.cs.mase.urml.Expression;
import ca.queensu.cs.mase.urml.IncomingVariable;
import ca.queensu.cs.mase.urml.Statement;
import ca.queensu.cs.mase.urml.TimerPort;
import ca.queensu.cs.mase.urml.Transition;
import ca.queensu.cs.mase.urml.Trigger_in;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtend2.lib.StringConcatenation;

@SuppressWarnings("all")
public class TransitionDefineGenerator {
  private List<Transition> allTransitions;
  
  private Map<Transition, Integer> nonameTrans;
  
  private static int nonameTransCount = 0;
  
  public TransitionDefineGenerator(final List<Transition> allTransitions, final Map<Transition, Integer> nonameTrans) {
    this.allTransitions = allTransitions;
    this.nonameTrans = nonameTrans;
  }
  
  /**
   * A transition
   * @return generated code
   */
  public CharSequence generate() {
    StringConcatenation _builder = new StringConcatenation();
    {
      for(final Transition t : this.allTransitions) {
        String _xifexpression = null;
        String _name = t.getName();
        boolean _tripleEquals = (_name == null);
        if (_tripleEquals) {
          _xifexpression = this.getNewNoNameTrans(t);
        } else {
          _xifexpression = t.getName();
        }
        String tname = _xifexpression;
        _builder.newLineIfNotEmpty();
        _builder.append("/**");
        _builder.newLine();
        _builder.append(" ");
        _builder.append("* A transition with name: ");
        _builder.append(tname, " ");
        _builder.newLineIfNotEmpty();
        _builder.append(" ");
        _builder.append("*/");
        _builder.newLine();
        _builder.append("private Transition _tran_");
        _builder.append(tname);
        _builder.append(" = new Transition(");
        _builder.newLineIfNotEmpty();
        _builder.newLine();
        _builder.append("\t");
        _builder.append("// name");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("\"");
        _builder.append(tname, "\t");
        _builder.append("\",");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("// guard");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("() -> {");
        _builder.newLine();
        {
          Expression _guard = t.getGuard();
          boolean _tripleEquals_1 = (_guard == null);
          if (_tripleEquals_1) {
            _builder.append("\t\t");
            _builder.append("return true;");
            _builder.newLine();
          } else {
            _builder.append("\t\t");
            _builder.append("return ");
            String _express = this.express(t.getGuard());
            _builder.append(_express, "\t\t");
            _builder.append(";");
            _builder.newLineIfNotEmpty();
          }
        }
        _builder.append("\t");
        _builder.append("},");
        _builder.newLine();
        _builder.append("\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("// action code");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("params -> {");
        _builder.newLine();
        {
          int _size = t.getTriggers().size();
          boolean _notEquals = (_size != 0);
          if (_notEquals) {
            {
              EList<IncomingVariable> _parameters = t.getTriggers().get(0).getParameters();
              for(final IncomingVariable p : _parameters) {
                _builder.append("\t\t");
                int count = 0;
                _builder.newLineIfNotEmpty();
                _builder.append("\t\t");
                String _type = this.type(p);
                _builder.append(_type, "\t\t");
                _builder.append(" _i_");
                String _name_1 = p.getName();
                _builder.append(_name_1, "\t\t");
                _builder.append(" = ((");
                String _commonObjType = this.commonObjType(p);
                _builder.append(_commonObjType, "\t\t");
                _builder.append(") (params.get(");
                _builder.append(count, "\t\t");
                _builder.append("))).val;");
                _builder.newLineIfNotEmpty();
                _builder.append("\t\t");
                String _xblockexpression = null;
                {
                  count = (count + 1);
                  _xblockexpression = "";
                }
                _builder.append(_xblockexpression, "\t\t");
                _builder.newLineIfNotEmpty();
              }
            }
          }
        }
        {
          ActionCode _action = t.getAction();
          boolean _tripleNotEquals = (_action != null);
          if (_tripleNotEquals) {
            _builder.append("\t\t");
            {
              EList<Statement> _statements = t.getAction().getStatements();
              for(final Statement st : _statements) {
                String _state = this.state(st);
                _builder.append(_state, "\t\t");
              }
            }
            _builder.newLineIfNotEmpty();
          }
        }
        _builder.append("\t");
        _builder.append("},");
        _builder.newLine();
        _builder.append("\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("// triggers");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("Arrays.asList(");
        _builder.newLine();
        {
          EList<Trigger_in> _triggers = t.getTriggers();
          boolean _hasElements = false;
          for(final Trigger_in trig : _triggers) {
            if (!_hasElements) {
              _hasElements = true;
            } else {
              _builder.appendImmediate(",", "\t\t");
            }
            _builder.append("\t\t");
            _builder.append("new TriggerIn(");
            _builder.newLine();
            _builder.append("\t\t");
            _builder.append("\t");
            _builder.append("_p_");
            String _name_2 = trig.getFrom().getName();
            _builder.append(_name_2, "\t\t\t");
            _builder.append(", _P_");
            String _name_3 = trig.getFrom().getProtocol().getName();
            _builder.append(_name_3, "\t\t\t");
            _builder.append("._s_");
            String _name_4 = trig.getSignal().getName();
            _builder.append(_name_4, "\t\t\t");
            _builder.newLineIfNotEmpty();
            _builder.append("\t\t");
            _builder.append(")");
            _builder.newLine();
          }
        }
        _builder.append("\t");
        _builder.append("),");
        _builder.newLine();
        _builder.append("\t");
        _builder.newLine();
        _builder.append("\t");
        _builder.append("// timer port");
        _builder.newLine();
        {
          TimerPort _timerPort = t.getTimerPort();
          boolean _tripleEquals_2 = (_timerPort == null);
          if (_tripleEquals_2) {
            _builder.append("\t");
            _builder.append("null");
            _builder.newLine();
          } else {
            _builder.append("\t");
            _builder.append("_tp_");
            String _name_5 = t.getTimerPort().getName();
            _builder.append(_name_5, "\t");
            _builder.newLineIfNotEmpty();
          }
        }
        _builder.append(");");
        _builder.newLine();
      }
    }
    return _builder;
  }
  
  /**
   * Compiles the expression
   * @param ex the expression
   * @return string expressing ex
   */
  private String express(final Expression ex) {
    return new ExpressionGenerator().express(ex);
  }
  
  private String getNewNoNameTrans(final Transition t) {
    String _xblockexpression = null;
    {
      int i = TransitionDefineGenerator.nonameTransCount;
      TransitionDefineGenerator.nonameTransCount++;
      this.nonameTrans.put(t, Integer.valueOf(i));
      _xblockexpression = ("_noname_" + Integer.valueOf(i));
    }
    return _xblockexpression;
  }
  
  /**
   * Returns the CommonObj type corresponding to the
   * incoming variable
   * @param op the incoming variable
   * @return a string that represents the CommonObj
   * of the incoming variable
   */
  private String commonObjType(final IncomingVariable op) {
    String _xifexpression = null;
    boolean _isIsBool = op.isIsBool();
    if (_isIsBool) {
      _xifexpression = "Bool";
    } else {
      String _xifexpression_1 = null;
      boolean _isIsInt = op.isIsInt();
      if (_isIsInt) {
        _xifexpression_1 = "Int";
      }
      _xifexpression = _xifexpression_1;
    }
    return _xifexpression;
  }
  
  /**
   * Returns the primitive type of the incoming variable
   * @param op the incoming variable
   * @return a string representing the primitive type
   * of the incoming variable
   */
  private String type(final IncomingVariable op) {
    String _xifexpression = null;
    boolean _isIsInt = op.isIsInt();
    if (_isIsInt) {
      _xifexpression = "int";
    } else {
      String _xifexpression_1 = null;
      boolean _isIsBool = op.isIsBool();
      if (_isIsBool) {
        _xifexpression_1 = "boolean";
      }
      _xifexpression = _xifexpression_1;
    }
    return _xifexpression;
  }
  
  /**
   * Compiles the statement
   * @param obj the statement
   * @return string expressing the statement
   */
  private String state(final EObject obj) {
    return new StatementGenerator().state(obj);
  }
}
