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.Attribute;
import ca.queensu.cs.mase.urml.Capsule;
import ca.queensu.cs.mase.urml.CapsuleInst;
import ca.queensu.cs.mase.urml.Expression;
import ca.queensu.cs.mase.urml.LocalVar;
import ca.queensu.cs.mase.urml.Operation;
import ca.queensu.cs.mase.urml.Port;
import ca.queensu.cs.mase.urml.StatementOperation;
import ca.queensu.cs.mase.urml.TimerPort;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtend2.lib.StringConcatenation;

@SuppressWarnings("all")
public class ListGenerator {
  private Capsule cap;
  
  public ListGenerator(final Capsule cap) {
    this.cap = cap;
  }
  
  public CharSequence generate() {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _listPorts = this.listPorts();
    _builder.append(_listPorts);
    _builder.newLineIfNotEmpty();
    CharSequence _listTimers = this.listTimers();
    _builder.append(_listTimers);
    _builder.newLineIfNotEmpty();
    CharSequence _listCapsuleInsts = this.listCapsuleInsts();
    _builder.append(_listCapsuleInsts);
    _builder.newLineIfNotEmpty();
    CharSequence _listAttribOps = this.listAttribOps();
    _builder.append(_listAttribOps);
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  /**
   * Defines the message ports
   * @return generated code
   */
  private CharSequence listPorts() {
    StringConcatenation _builder = new StringConcatenation();
    {
      EList<Port> _internalPorts = this.cap.getInternalPorts();
      for(final Port port : _internalPorts) {
        _builder.append("MessagePort _p_");
        String _name = port.getName();
        _builder.append(_name);
        _builder.append(" = new MessagePort(\"");
        String _name_1 = port.getName();
        _builder.append(_name_1);
        _builder.append("\", new _P_");
        String _name_2 = port.getProtocol().getName();
        _builder.append(_name_2);
        _builder.append("());");
        _builder.newLineIfNotEmpty();
      }
    }
    {
      EList<Port> _interfacePorts = this.cap.getInterfacePorts();
      for(final Port port_1 : _interfacePorts) {
        _builder.append("MessagePort _p_");
        String _name_3 = port_1.getName();
        _builder.append(_name_3);
        _builder.append(" = new MessagePort(\"");
        String _name_4 = port_1.getName();
        _builder.append(_name_4);
        _builder.append("\", new _P_");
        String _name_5 = port_1.getProtocol().getName();
        _builder.append(_name_5);
        _builder.append("());");
        _builder.newLineIfNotEmpty();
      }
    }
    return _builder;
  }
  
  /**
   * Defines the timers
   * @return generated code
   */
  private CharSequence listTimers() {
    StringConcatenation _builder = new StringConcatenation();
    {
      EList<TimerPort> _timerPorts = this.cap.getTimerPorts();
      for(final TimerPort timer : _timerPorts) {
        _builder.append("final TimerPort _tp_");
        String _name = timer.getName();
        _builder.append(_name);
        _builder.append(" = new TimerPort();");
        _builder.newLineIfNotEmpty();
      }
    }
    return _builder;
  }
  
  /**
   * Defines the capsule instances
   * @return generated code
   */
  private CharSequence listCapsuleInsts() {
    StringConcatenation _builder = new StringConcatenation();
    {
      EList<CapsuleInst> _capsuleInsts = this.cap.getCapsuleInsts();
      for(final CapsuleInst ci : _capsuleInsts) {
        _builder.append("_C_");
        String _name = ci.getType().getName();
        _builder.append(_name);
        _builder.append(" _ci_");
        String _name_1 = ci.getName();
        _builder.append(_name_1);
        _builder.append(" = new _C_");
        String _name_2 = ci.getType().getName();
        _builder.append(_name_2);
        _builder.append("(this);");
        _builder.newLineIfNotEmpty();
      }
    }
    return _builder;
  }
  
  /**
   * Defines the attributes and operations
   * @return generated code
   */
  private CharSequence listAttribOps() {
    StringConcatenation _builder = new StringConcatenation();
    {
      EList<Attribute> _attributes = this.cap.getAttributes();
      for(final Attribute attrib : _attributes) {
        CharSequence _compile = this.compile(attrib);
        _builder.append(_compile);
        _builder.newLineIfNotEmpty();
      }
    }
    {
      EList<Operation> _operations = this.cap.getOperations();
      for(final Operation op : _operations) {
        CharSequence _compile_1 = this.compile(op);
        _builder.append(_compile_1);
        _builder.newLineIfNotEmpty();
      }
    }
    return _builder;
  }
  
  /**
   * Compiles the operation
   * @param op operation to be compiled
   * @return generated code
   */
  private CharSequence compile(final Operation op) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public ");
    String _type = this.type(op);
    _builder.append(_type);
    _builder.append(" _f_");
    String _name = op.getName();
    _builder.append(_name);
    _builder.append("(");
    {
      EList<LocalVar> _localVars = op.getLocalVars();
      boolean _hasElements = false;
      for(final LocalVar param : _localVars) {
        if (!_hasElements) {
          _hasElements = true;
        } else {
          _builder.appendImmediate(", ", "");
        }
        String _type_1 = this.type(param);
        _builder.append(_type_1);
        _builder.append(" _l_");
        String _name_1 = param.getName();
        _builder.append(_name_1);
      }
    }
    _builder.append(") {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    {
      EList<StatementOperation> _statements = op.getOperationCode().getStatements();
      for(final StatementOperation st : _statements) {
        String _state = this.state(st);
        _builder.append(_state, "\t");
      }
    }
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }
  
  /**
   * Compiles the attribute
   */
  private CharSequence compile(final Attribute attrib) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("private ");
    String _type = this.type(attrib);
    _builder.append(_type);
    _builder.append(" _a_");
    String _name = attrib.getName();
    _builder.append(_name);
    {
      Expression _defaultValue = attrib.getDefaultValue();
      boolean _tripleNotEquals = (_defaultValue != null);
      if (_tripleNotEquals) {
        _builder.append(" = ");
        String _express = this.express(attrib.getDefaultValue());
        _builder.append(_express);
      }
    }
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    return _builder;
  }
  
  /**
   * Returns the return primitive type of the operation
   * @param op the operation
   * @return the return type (primitive type)
   */
  private String type(final Operation 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";
      } else {
        _xifexpression_1 = "void";
      }
      _xifexpression = _xifexpression_1;
    }
    return _xifexpression;
  }
  
  /**
   * Returns the primitive type of the local variable
   * @param op the local variable
   * @return the string represents the primitive type
   * of the local variable
   */
  private String type(final LocalVar 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";
      } else {
        _xifexpression_1 = "void";
      }
      _xifexpression = _xifexpression_1;
    }
    return _xifexpression;
  }
  
  /**
   * Returns the primitive type of the attribute
   * @op the attribute
   * @return a string represents the primitive type of
   * the attribute
   */
  private String type(final Attribute 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 expression
   * @param ex the expression
   * @return string expressing ex
   */
  private String express(final Expression ex) {
    return new ExpressionGenerator().express(ex);
  }
  
  /**
   * Compiles the statement
   * @param obj the statement
   * @return string expressing the statement
   */
  private String state(final EObject obj) {
    return new StatementGenerator().state(obj);
  }
}
