/**
 * generated by Xtext
 */
package ca.queensu.cs.mase.generator;

import ca.queensu.cs.mase.generator.CommonCapsuleGenerator;
import ca.queensu.cs.mase.generator.LauncherGenerator;
import ca.queensu.cs.mase.generator.capsules.CapsuleGenerator;
import ca.queensu.cs.mase.generator.protocols.ProtocolGenerator;
import ca.queensu.cs.mase.urml.Capsule;
import ca.queensu.cs.mase.urml.Model;
import ca.queensu.cs.mase.urml.Protocol;
import java.util.Collections;
import java.util.function.Consumer;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtext.generator.IFileSystemAccess2;
import org.eclipse.xtext.generator.IGenerator2;
import org.eclipse.xtext.generator.IGeneratorContext;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Pair;
import org.eclipse.xtext.xbase.lib.StringExtensions;

@SuppressWarnings("all")
public class UrmlGenerator implements IGenerator2 {
  private Model model;
  
  public void afterGenerate(final Resource input, final IFileSystemAccess2 fsa, final IGeneratorContext context) {
  }
  
  public void beforeGenerate(final Resource input, final IFileSystemAccess2 fsa, final IGeneratorContext context) {
  }
  
  public void doGenerate(final Resource resource, final IFileSystemAccess2 fsa, final IGeneratorContext context) {
    EObject _get = resource.getContents().get(0);
    this.model = ((Model) _get);
    String mfname = this.modelPackageName().replace(".", "/");
    EList<Capsule> _capsules = this.model.getCapsules();
    for (final Capsule cap : _capsules) {
      String _name = cap.getName();
      String _plus = ((mfname + "/_C_") + _name);
      String _plus_1 = (_plus + ".java");
      fsa.generateFile(_plus_1, this.compile(cap));
    }
    EList<Protocol> _protocols = this.model.getProtocols();
    for (final Protocol prot : _protocols) {
      String _name_1 = prot.getName();
      String _plus_2 = ((mfname + "/_P_") + _name_1);
      String _plus_3 = (_plus_2 + ".java");
      fsa.generateFile(_plus_3, this.compile(prot));
    }
    fsa.generateFile((mfname + "/Launcher.java"), this.compileLauncher());
    CharSequence _compileInt = this.compileInt();
    Pair<String, CharSequence> _mappedTo = Pair.<String, CharSequence>of("Int.java", _compileInt);
    CharSequence _compileBool = this.compileBool();
    Pair<String, CharSequence> _mappedTo_1 = Pair.<String, CharSequence>of("Bool.java", _compileBool);
    CharSequence _compileCommon = this.compileCommon();
    Pair<String, CharSequence> _mappedTo_2 = Pair.<String, CharSequence>of("CommonObj.java", _compileCommon);
    CharSequence _compileCommonCapsule = this.compileCommonCapsule();
    Pair<String, CharSequence> _mappedTo_3 = Pair.<String, CharSequence>of("Capsule.java", _compileCommonCapsule);
    CharSequence _compilePort = this.compilePort();
    Pair<String, CharSequence> _mappedTo_4 = Pair.<String, CharSequence>of("MessagePort.java", _compilePort);
    CharSequence _compileProtocol = this.compileProtocol();
    Pair<String, CharSequence> _mappedTo_5 = Pair.<String, CharSequence>of("Protocol.java", _compileProtocol);
    CharSequence _compileConnector = this.compileConnector();
    Pair<String, CharSequence> _mappedTo_6 = Pair.<String, CharSequence>of("Connector.java", _compileConnector);
    CharSequence _compileCapPortPair = this.compileCapPortPair();
    Pair<String, CharSequence> _mappedTo_7 = Pair.<String, CharSequence>of("CapsulePortPair.java", _compileCapPortPair);
    CharSequence _compileMessage = this.compileMessage();
    Pair<String, CharSequence> _mappedTo_8 = Pair.<String, CharSequence>of("Message.java", _compileMessage);
    CharSequence _compileSignal = this.compileSignal();
    Pair<String, CharSequence> _mappedTo_9 = Pair.<String, CharSequence>of("Signal.java", _compileSignal);
    CharSequence _compileState = this.compileState();
    Pair<String, CharSequence> _mappedTo_10 = Pair.<String, CharSequence>of("State.java", _compileState);
    CharSequence _compileTransition = this.compileTransition();
    Pair<String, CharSequence> _mappedTo_11 = Pair.<String, CharSequence>of("Transition.java", _compileTransition);
    CharSequence _compileTriggerIn = this.compileTriggerIn();
    Pair<String, CharSequence> _mappedTo_12 = Pair.<String, CharSequence>of("TriggerIn.java", _compileTriggerIn);
    CharSequence _compileTimerPort = this.compileTimerPort();
    Pair<String, CharSequence> _mappedTo_13 = Pair.<String, CharSequence>of("TimerPort.java", _compileTimerPort);
    final Consumer<Pair<String, CharSequence>> _function = new Consumer<Pair<String, CharSequence>>() {
      public void accept(final Pair<String, CharSequence> it) {
        String _replace = UrmlGenerator.this.urmlRuntimeName().replace(".", "/");
        String _plus = (_replace + 
          "/");
        String _key = it.getKey();
        String _plus_1 = (_plus + _key);
        fsa.generateFile(_plus_1, it.getValue());
      }
    };
    Collections.<Pair<String, CharSequence>>unmodifiableList(CollectionLiterals.<Pair<String, CharSequence>>newArrayList(_mappedTo, _mappedTo_1, _mappedTo_2, _mappedTo_3, _mappedTo_4, _mappedTo_5, _mappedTo_6, _mappedTo_7, _mappedTo_8, _mappedTo_9, _mappedTo_10, _mappedTo_11, _mappedTo_12, _mappedTo_13)).forEach(_function);
  }
  
  private CharSequence urmlRuntime() {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("package ");
    String _urmlRuntimeName = this.urmlRuntimeName();
    _builder.append(_urmlRuntimeName);
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  private String urmlRuntimeName() {
    return "urml.runtime";
  }
  
  private CharSequence modelPackage() {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("package ");
    String _modelPackageName = this.modelPackageName();
    _builder.append(_modelPackageName);
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  private String modelPackageName() {
    String _firstLower = StringExtensions.toFirstLower(this.model.getName());
    return ("model." + _firstLower);
  }
  
  private CharSequence compile(final Protocol p) {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _modelPackage = this.modelPackage();
    _builder.append(_modelPackage);
    _builder.newLineIfNotEmpty();
    CharSequence _generate = new ProtocolGenerator(p).generate();
    _builder.append(_generate);
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  private CharSequence compileSignal() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("public class Signal {}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compileMessage() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("import java.util.*;");
    _builder.newLine();
    _builder.append("public class Message {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public MessagePort port;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Signal signal;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public List<CommonObj> parameters;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Message(MessagePort msgPort, Signal signal, ");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("List<CommonObj> param) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.port = msgPort;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.signal = signal;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.parameters = param;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compileCapPortPair() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("public class CapsulePortPair {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Capsule cap;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public MessagePort port;");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compile(final Capsule cap) {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _modelPackage = this.modelPackage();
    _builder.append(_modelPackage);
    _builder.newLineIfNotEmpty();
    CharSequence _generate = new CapsuleGenerator(cap).generate();
    _builder.append(_generate);
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  private CharSequence compileInt() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("public class Int extends CommonObj {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public int val;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Int(int v) { val = v; }");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compileBool() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("public class Bool extends CommonObj {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public boolean val;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Bool(boolean v) { val = v; }");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compileCommon() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("public class CommonObj {");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compileCommonCapsule() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    CharSequence _compile = new CommonCapsuleGenerator().compile();
    _builder.append(_compile);
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  private CharSequence compileProtocol() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("import java.util.*;");
    _builder.newLine();
    _builder.append("public class Protocol {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("protected Protocol() {}");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("protected List<Signal> incomingSignals;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("protected List<Signal> outgoingSignals;");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compilePort() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("public class MessagePort {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public String name;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Protocol prot;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public MessagePort(String name, Protocol protocol) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.name = name;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.prot = protocol;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compileTimerPort() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("public class TimerPort {");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compileConnector() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("public class Connector {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Capsule cap1;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Capsule cap2;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public MessagePort port1;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public MessagePort port2;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Connector(Capsule c1, MessagePort p1, Capsule c2, MessagePort p2) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("cap1 = c1; cap2 = c2; port1 = p1; port2 = p2;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compileLauncher() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _modelPackage = this.modelPackage();
    _builder.append(_modelPackage);
    _builder.newLineIfNotEmpty();
    CharSequence _generate = new LauncherGenerator(this.model).generate();
    _builder.append(_generate);
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  private CharSequence compileState() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("public class State {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public String name;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Runnable entry;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Runnable exit;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public State(String name, Runnable entry, Runnable exit) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.name = name;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.entry = entry;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.exit = exit;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compileTransition() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("import java.util.*;");
    _builder.newLine();
    _builder.append("import java.util.function.*;");
    _builder.newLine();
    _builder.append("public class Transition {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public String name;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Supplier<Boolean> guard;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Consumer<List<? extends CommonObj>> action;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public List<TriggerIn> triggerIn;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public TimerPort timerPort;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Transition(String name, Supplier<Boolean> guard, ");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("Consumer<List<? extends CommonObj>> action, ");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("List<TriggerIn> triggerIn, TimerPort timerPort) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.name = name;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.guard = guard;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.action = action;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.triggerIn = triggerIn;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.timerPort = timerPort;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}\t");
    _builder.newLine();
    return _builder;
  }
  
  private CharSequence compileTriggerIn() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _urmlRuntime = this.urmlRuntime();
    _builder.append(_urmlRuntime);
    _builder.newLineIfNotEmpty();
    _builder.append("public class TriggerIn {");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public MessagePort port;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Signal signal;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public TriggerIn(MessagePort p, Signal s) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("port = p;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("signal = s;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}\t");
    _builder.newLine();
    return _builder;
  }
}
