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

import ca.queensu.cs.mase.generator.capsules.methods.NoInitialTransitionInStateMachineException;
import ca.queensu.cs.mase.urml.Capsule;
import ca.queensu.cs.mase.urml.StateMachine;
import ca.queensu.cs.mase.urml.State_;
import ca.queensu.cs.mase.urml.Transition;
import java.util.Map;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtext.EcoreUtil2;

@SuppressWarnings("all")
public class InitialTransitionGenerator {
  private Transition init;
  
  private Map<Transition, Integer> nonameTrans;
  
  public InitialTransitionGenerator(final Transition init, final Map<Transition, Integer> nonameTrans) {
    this.init = init;
    this.nonameTrans = nonameTrans;
  }
  
  public CharSequence generate() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _genInitMethod = this.genInitMethod();
    _builder.append(_genInitMethod);
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  /**
   * Generate the initial transition chain
   * @return generated code
   */
  private CharSequence genInitMethod() {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("/**");
    _builder.newLine();
    _builder.append(" ");
    _builder.append("* Initial transition chain");
    _builder.newLine();
    _builder.append(" ");
    _builder.append("*/");
    _builder.newLine();
    _builder.append("public void startInit() {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("synchronized (lock) {");
    _builder.newLine();
    _builder.append("\t\t");
    String _genInitMethod2 = this.genInitMethod2(this.init);
    _builder.append(_genInitMethod2, "\t\t");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  /**
   * Generate the initial transition chain
   * @param init the initial transition
   * @return generated code
   */
  private String genInitMethod2(final Transition init) {
    String result = "";
    State_ state = null;
    if ((init != null)) {
      String initname = this.genName(init);
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("_tran_");
      _builder.append(initname);
      _builder.append(".action.accept(new ArrayList<>());");
      _builder.newLineIfNotEmpty();
      String _plus = (result + _builder);
      result = _plus;
      state = init.getTo();
      StringConcatenation _builder_1 = new StringConcatenation();
      _builder_1.append("currentState = _state_");
      String _name = state.getName();
      _builder_1.append(_name);
      _builder_1.append(";");
      _builder_1.newLineIfNotEmpty();
      _builder_1.append("_state_");
      String _name_1 = state.getName();
      _builder_1.append(_name_1);
      _builder_1.append(".entry.run();");
      _builder_1.newLineIfNotEmpty();
      String _plus_1 = (result + _builder_1);
      result = _plus_1;
      while ((state.getSubstatemachine() != null)) {
        {
          StateMachine sm = state.getSubstatemachine();
          Transition subInitial = this.findInit(sm);
          if ((subInitial == null)) {
            throw new NoInitialTransitionInStateMachineException();
          }
          String subInitialname = this.genName(subInitial);
          StringConcatenation _builder_2 = new StringConcatenation();
          _builder_2.append("_tran_");
          _builder_2.append(subInitialname);
          _builder_2.append(".action.accept(new ArrayList<>());");
          _builder_2.newLineIfNotEmpty();
          String _plus_2 = (result + _builder_2);
          result = _plus_2;
          state = subInitial.getTo();
          StringConcatenation _builder_3 = new StringConcatenation();
          _builder_3.append("currentState = _state_");
          String _name_2 = state.getName();
          _builder_3.append(_name_2);
          _builder_3.append(";");
          _builder_3.newLineIfNotEmpty();
          _builder_3.append("_state_");
          String _name_3 = state.getName();
          _builder_3.append(_name_3);
          _builder_3.append(".entry.run();");
          _builder_3.newLineIfNotEmpty();
          String _plus_3 = (result + _builder_3);
          result = _plus_3;
        }
      }
    }
    return result;
  }
  
  private String genName(final Transition t) {
    String _xifexpression = null;
    String _name = t.getName();
    boolean _tripleEquals = (_name == null);
    if (_tripleEquals) {
      Integer _get = this.nonameTrans.get(t);
      _xifexpression = ("_noname_" + _get);
    } else {
      _xifexpression = t.getName();
    }
    return _xifexpression;
  }
  
  /**
   * Find the initial transition for the given state machine
   * @param sm the given state machine
   * @return the initial transition of sm
   */
  private Transition findInit(final StateMachine sm) {
    Capsule c = this.<Capsule>container(sm, Capsule.class);
    if ((c != null)) {
      EList<Transition> _transitions = sm.getTransitions();
      for (final Transition t : _transitions) {
        boolean _isInit = t.isInit();
        if (_isInit) {
          return t;
        }
      }
    }
    return null;
  }
  
  /**
   * Returns the container of the EObject obj with type
   * t
   * @param
   */
  private <T extends EObject> T container(final EObject obj, final Class<T> t) {
    return EcoreUtil2.<T>getContainerOfType(obj, t);
  }
}
