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

import ca.queensu.cs.mase.urml.State_;
import ca.queensu.cs.mase.urml.Transition;
import com.google.common.collect.Multimap;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtext.EcoreUtil2;

@SuppressWarnings("all")
public class FindNextTransitionGenerator {
  private List<State_> allStates;
  
  private Multimap<State_, Transition> outgoingTransitions;
  
  private Map<Transition, Integer> nonameTrans;
  
  public FindNextTransitionGenerator(final List<State_> allStates, final Multimap<State_, Transition> o, final Map<Transition, Integer> nonameTrans) {
    this.allStates = allStates;
    this.outgoingTransitions = o;
    this.nonameTrans = nonameTrans;
  }
  
  public CharSequence generate() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _findNextTransitions = this.findNextTransitions();
    _builder.append(_findNextTransitions);
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  /**
   * Find the possible next transitions for each state
   * @return generated code
   */
  private CharSequence findNextTransitions() {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("/**");
    _builder.newLine();
    _builder.append(" ");
    _builder.append("* Find the possible next transitions for each state");
    _builder.newLine();
    _builder.append(" ");
    _builder.append("* @return outgoing transition for the current state");
    _builder.newLine();
    _builder.append(" ");
    _builder.append("*/");
    _builder.newLine();
    _builder.append("public List<? extends Transition> findPossibleTrans() {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("switch (currentState.name) {");
    _builder.newLine();
    {
      for(final State_ state : this.allStates) {
        _builder.append("\t\t");
        _builder.append("case \"");
        String _name = state.getName();
        _builder.append(_name, "\t\t");
        _builder.append("\":");
        _builder.newLineIfNotEmpty();
        _builder.append("\t\t");
        _builder.append("\t");
        _builder.append("return Arrays.asList(");
        String _genPossibleTrans = this.genPossibleTrans(state);
        _builder.append(_genPossibleTrans, "\t\t\t");
        _builder.append(");");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t\t");
    _builder.append("default:");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("return new ArrayList<>();");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  /**
   * Generate possible outgoing transitions from state s
   * @param s the state
   * @return generated code
   */
  private String genPossibleTrans(final State_ s) {
    State_ stateToGoThrough = s;
    String result = "";
    do {
      {
        Collection<Transition> _get = this.outgoingTransitions.get(stateToGoThrough);
        for (final Transition t : _get) {
          {
            String tname = this.genName(t);
            result = (((result + "_tran_") + tname) + ", ");
          }
        }
        stateToGoThrough = this.<State_>container(stateToGoThrough.eContainer(), State_.class);
      }
    } while((stateToGoThrough != null));
    int _length = result.length();
    boolean _greaterThan = (_length > 2);
    if (_greaterThan) {
      int _length_1 = result.length();
      int _minus = (_length_1 - 2);
      result = result.substring(0, _minus);
    }
    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;
  }
  
  /**
   * 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);
  }
}
