/**
 * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 * 
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *         Florian Pirchner - Initial implementation
 */
package org.eclipse.osbp.dsl.services.xtext.jvmmodel;

import com.google.inject.Inject;
import java.util.Arrays;
import java.util.Set;
import javax.persistence.EntityManagerFactory;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.osbp.dsl.common.xtext.extensions.NamingExtensions;
import org.eclipse.osbp.dsl.dto.lib.services.impl.AbstractDTOService;
import org.eclipse.osbp.dsl.dto.lib.services.impl.AbstractDTOServiceWithMutablePersistence;
import org.eclipse.osbp.dsl.dto.xtext.extensions.MethodNamingExtensions;
import org.eclipse.osbp.dsl.semantic.common.types.LAttribute;
import org.eclipse.osbp.dsl.semantic.common.types.LTypedPackage;
import org.eclipse.osbp.dsl.semantic.service.LCardinality;
import org.eclipse.osbp.dsl.semantic.service.LDTOService;
import org.eclipse.osbp.dsl.semantic.service.LInjectedService;
import org.eclipse.osbp.dsl.semantic.service.LInjectedServices;
import org.eclipse.osbp.dsl.semantic.service.LServiceOperation;
import org.eclipse.osbp.dsl.semantic.service.OSBPServiceFactory;
import org.eclipse.osbp.dsl.services.xtext.extensions.ModelExtensions;
import org.eclipse.osbp.dsl.services.xtext.extensions.ServicesTypesBuilder;
import org.eclipse.osbp.xtext.oxtype.logger.TimeLogger;
import org.eclipse.osbp.xtext.oxtype.resource.ExtendedModelInferrer;
import org.eclipse.xtend2.lib.StringConcatenationClient;
import org.eclipse.xtext.common.types.JvmConstructor;
import org.eclipse.xtext.common.types.JvmField;
import org.eclipse.xtext.common.types.JvmFormalParameter;
import org.eclipse.xtext.common.types.JvmGenericType;
import org.eclipse.xtext.common.types.JvmMember;
import org.eclipse.xtext.common.types.JvmOperation;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.util.TypeReferences;
import org.eclipse.xtext.naming.IQualifiedNameProvider;
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor;
import org.eclipse.xtext.xbase.lib.Extension;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>Infers a JVM model from the source model.</p>
 * 
 * <p>The JVM model should contain all elements that would appear in the Java code
 * which is generated from the source model. Other models link against the JVM model rather than the source model.</p>
 */
@SuppressWarnings("all")
public class ServicesGrammarJvmModelInferrer extends ExtendedModelInferrer {
  /**
   * convenience API to build and initialize JVM types and their members.
   */
  protected final Logger log = LoggerFactory.getLogger(this.getClass());
  
  @Inject
  @Extension
  private IQualifiedNameProvider _iQualifiedNameProvider;
  
  @Inject
  @Extension
  private ServicesTypesBuilder _servicesTypesBuilder;
  
  @Inject
  @Extension
  private ModelExtensions _modelExtensions;
  
  @Inject
  @Extension
  private NamingExtensions _namingExtensions;
  
  @Inject
  private TypeReferences references;
  
  @Inject
  private MethodNamingExtensions dtoNamings;
  
  protected void _inferFullState(final JvmType type, final EObject element, final IJvmDeclaredTypeAcceptor acceptor, final boolean isPrelinkingPhase, final String selector) {
  }
  
  protected void _infer(final LDTOService service, final IJvmDeclaredTypeAcceptor acceptor, final boolean isPrelinkingPhase) {
    final JvmGenericType type = this._servicesTypesBuilder.toJvmType(service);
    this.inferFullState(type, service, acceptor, isPrelinkingPhase, "");
  }
  
  protected void _inferTypesOnly(final LDTOService service, final IJvmDeclaredTypeAcceptor acceptor, final boolean isPrelinkingPhase) {
    final JvmGenericType type = this._servicesTypesBuilder.toJvmType(service);
    acceptor.<JvmGenericType>accept(type);
    this.inferTypesOnlyByDelegates(service, acceptor, isPrelinkingPhase);
  }
  
  protected void _inferFullState(final JvmGenericType type, final LDTOService service, final IJvmDeclaredTypeAcceptor acceptor, final boolean isPrelinkingPhase, final String selector) {
    final Procedure1<JvmGenericType> _function = (JvmGenericType it) -> {
      final TimeLogger doInferLog = TimeLogger.start(it.getClass());
      EObject _eContainer = service.eContainer();
      this._servicesTypesBuilder.setFileHeader(it, this._servicesTypesBuilder.getDocumentation(((LTypedPackage) _eContainer)));
      this._servicesTypesBuilder.setDocumentation(it, this._servicesTypesBuilder.getDocumentation(service));
      boolean _basedOnEntity = this._modelExtensions.basedOnEntity(service.getDto());
      if (_basedOnEntity) {
        boolean _isMutablePersistenceId = service.isMutablePersistenceId();
        if (_isMutablePersistenceId) {
          EList<JvmTypeReference> _superTypes = it.getSuperTypes();
          JvmTypeReference _typeForName = this.references.getTypeForName(AbstractDTOServiceWithMutablePersistence.class, service, 
            this._modelExtensions.toTypeReference(service.getDto()), this._modelExtensions.toTypeReference(this._modelExtensions.wrappedEntity(service.getDto())));
          this._servicesTypesBuilder.<JvmTypeReference>operator_add(_superTypes, _typeForName);
        } else {
          EList<JvmTypeReference> _superTypes_1 = it.getSuperTypes();
          JvmTypeReference _typeForName_1 = this.references.getTypeForName(AbstractDTOService.class, service, this._modelExtensions.toTypeReference(service.getDto()), 
            this._modelExtensions.toTypeReference(this._modelExtensions.wrappedEntity(service.getDto())));
          this._servicesTypesBuilder.<JvmTypeReference>operator_add(_superTypes_1, _typeForName_1);
        }
        boolean _isMutablePersistenceId_1 = service.isMutablePersistenceId();
        if (_isMutablePersistenceId_1) {
          EList<JvmMember> _members = it.getMembers();
          final Procedure1<JvmConstructor> _function_1 = (JvmConstructor it_1) -> {
            StringConcatenationClient _client = new StringConcatenationClient() {
              @Override
              protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
                _builder.append("// set the default persistence ID");
                _builder.newLine();
                _builder.append("setPersistenceId(\"");
                String _persistenceId = service.getPersistenceId();
                _builder.append(_persistenceId);
                _builder.append("\");");
              }
            };
            this._servicesTypesBuilder.setBody(it_1, _client);
          };
          JvmConstructor _constructor = this._servicesTypesBuilder.toConstructor(service, _function_1);
          this._servicesTypesBuilder.<JvmConstructor>operator_add(_members, _constructor);
        } else {
          EList<JvmMember> _members_1 = it.getMembers();
          final Procedure1<JvmConstructor> _function_2 = (JvmConstructor it_1) -> {
          };
          JvmConstructor _constructor_1 = this._servicesTypesBuilder.toConstructor(service, _function_2);
          this._servicesTypesBuilder.<JvmConstructor>operator_add(_members_1, _constructor_1);
        }
        JvmTypeReference _dtoJvm = service.getDtoJvm();
        boolean _tripleNotEquals = (_dtoJvm != null);
        if (_tripleNotEquals) {
          EList<JvmMember> _members_2 = it.getMembers();
          final Procedure1<JvmOperation> _function_3 = (JvmOperation it_1) -> {
            StringConcatenationClient _client = new StringConcatenationClient() {
              @Override
              protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
                _builder.append("return ");
                String _name = service.getDto().getName();
                _builder.append(_name);
                _builder.append(".class;");
              }
            };
            this._servicesTypesBuilder.setBody(it_1, _client);
          };
          JvmOperation _method = this._servicesTypesBuilder.toMethod(service, "getDtoClass", 
            this.references.getTypeForName(Class.class, service, this._servicesTypesBuilder.cloneWithProxies(service.getDtoJvm())), _function_3);
          this._servicesTypesBuilder.<JvmOperation>operator_add(_members_2, _method);
        }
        EList<JvmMember> _members_3 = it.getMembers();
        final Procedure1<JvmOperation> _function_4 = (JvmOperation it_1) -> {
          StringConcatenationClient _client = new StringConcatenationClient() {
            @Override
            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
              _builder.append("return ");
              String _name = ServicesGrammarJvmModelInferrer.this._modelExtensions.wrappedEntity(service.getDto()).getName();
              _builder.append(_name);
              _builder.append(".class;");
            }
          };
          this._servicesTypesBuilder.setBody(it_1, _client);
        };
        JvmOperation _method_1 = this._servicesTypesBuilder.toMethod(service, "getEntityClass", 
          this.references.getTypeForName(Class.class, service, this._modelExtensions.toTypeReference(service.getDto().getWrappedType())), _function_4);
        this._servicesTypesBuilder.<JvmOperation>operator_add(_members_3, _method_1);
        LAttribute _idAttribute = service.getDto().getIdAttribute();
        boolean _tripleNotEquals_1 = (_idAttribute != null);
        if (_tripleNotEquals_1) {
          EList<JvmMember> _members_4 = it.getMembers();
          final Procedure1<JvmOperation> _function_5 = (JvmOperation it_1) -> {
            EList<JvmFormalParameter> _parameters = it_1.getParameters();
            JvmFormalParameter _parameter = this._servicesTypesBuilder.toParameter(service, "dto", this._modelExtensions.toTypeReference(service.getDto()));
            this._servicesTypesBuilder.<JvmFormalParameter>operator_add(_parameters, _parameter);
            StringConcatenationClient _client = new StringConcatenationClient() {
              @Override
              protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
                _builder.append("return dto.");
                LAttribute _idAttribute = service.getDto().getIdAttribute();
                String _getterName = null;
                if (_idAttribute!=null) {
                  _getterName=ServicesGrammarJvmModelInferrer.this._namingExtensions.toGetterName(_idAttribute);
                }
                _builder.append(_getterName);
                _builder.append("();");
              }
            };
            this._servicesTypesBuilder.setBody(it_1, _client);
          };
          JvmOperation _method_2 = this._servicesTypesBuilder.toMethod(service, "getId", this.references.getTypeForName(Object.class, service, null), _function_5);
          this._servicesTypesBuilder.<JvmOperation>operator_add(_members_4, _method_2);
        } else {
          JvmTypeReference _dtoJvm_1 = service.getDtoJvm();
          boolean _tripleNotEquals_2 = (_dtoJvm_1 != null);
          if (_tripleNotEquals_2) {
            EList<JvmMember> _members_5 = it.getMembers();
            final Procedure1<JvmOperation> _function_6 = (JvmOperation it_1) -> {
              EList<JvmFormalParameter> _parameters = it_1.getParameters();
              JvmFormalParameter _parameter = this._servicesTypesBuilder.toParameter(service, "dto", this._servicesTypesBuilder.cloneWithProxies(service.getDtoJvm()));
              this._servicesTypesBuilder.<JvmFormalParameter>operator_add(_parameters, _parameter);
              StringConcatenationClient _client = new StringConcatenationClient() {
                @Override
                protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
                  _builder.append("throw new UnsupportedOperationException(\"No id available for DTO.\");");
                }
              };
              this._servicesTypesBuilder.setBody(it_1, _client);
            };
            JvmOperation _method_3 = this._servicesTypesBuilder.toMethod(service, "getId", this.references.getTypeForName(Object.class, service, null), _function_6);
            this._servicesTypesBuilder.<JvmOperation>operator_add(_members_5, _method_3);
          }
        }
        EList<LServiceOperation> _operations = service.getOperations();
        for (final LServiceOperation f : _operations) {
          EList<JvmMember> _members_6 = it.getMembers();
          final Procedure1<JvmOperation> _function_7 = (JvmOperation it_1) -> {
            this._servicesTypesBuilder.setDocumentation(it_1, this._servicesTypesBuilder.getDocumentation(f));
            EList<JvmFormalParameter> _params = f.getParams();
            for (final JvmFormalParameter p : _params) {
              EList<JvmFormalParameter> _parameters = it_1.getParameters();
              JvmFormalParameter _parameter = this._servicesTypesBuilder.toParameter(p, p.getName(), p.getParameterType());
              this._servicesTypesBuilder.<JvmFormalParameter>operator_add(_parameters, _parameter);
            }
            this._servicesTypesBuilder.setBody(it_1, f.getBody());
          };
          JvmOperation _method_4 = this._servicesTypesBuilder.toMethod(f, this._modelExtensions.toName(f), f.getType(), _function_7);
          this._servicesTypesBuilder.<JvmOperation>operator_add(_members_6, _method_4);
        }
      } else {
        EList<JvmMember> _members_7 = it.getMembers();
        final Procedure1<JvmConstructor> _function_8 = (JvmConstructor it_1) -> {
        };
        JvmConstructor _constructor_2 = this._servicesTypesBuilder.toConstructor(service, _function_8);
        this._servicesTypesBuilder.<JvmConstructor>operator_add(_members_7, _constructor_2);
        final LInjectedService emfService = OSBPServiceFactory.eINSTANCE.createLInjectedService();
        emfService.setAttributeName("emf");
        emfService.setCardinality(LCardinality.ONE_TO_ONE);
        emfService.setService(this.references.getTypeForName(EntityManagerFactory.class, service, null));
        EList<LInjectedService> _services = service.getInjectedServices().getServices();
        this._servicesTypesBuilder.<LInjectedService>operator_add(_services, emfService);
        LInjectedServices _injectedServices = service.getInjectedServices();
        boolean _tripleNotEquals_3 = (_injectedServices != null);
        if (_tripleNotEquals_3) {
          EList<LInjectedService> _services_1 = service.getInjectedServices().getServices();
          for (final LInjectedService f_1 : _services_1) {
            LCardinality _cardinality = f_1.getCardinality();
            if (_cardinality != null) {
              switch (_cardinality) {
                case ZERO_TO_ONE:
                  EList<JvmMember> _members_8 = it.getMembers();
                  JvmField _field = this._servicesTypesBuilder.toField(f_1, f_1.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_1.getService()));
                  this._servicesTypesBuilder.<JvmField>operator_add(_members_8, _field);
                  break;
                case ZERO_TO_MANY:
                  EList<JvmMember> _members_9 = it.getMembers();
                  JvmField _field_1 = this._servicesTypesBuilder.toField(f_1, f_1.getAttributeName(), 
                    this.references.getTypeForName(Set.class, service, this._servicesTypesBuilder.cloneWithProxies(f_1.getService())));
                  this._servicesTypesBuilder.<JvmField>operator_add(_members_9, _field_1);
                  break;
                case ONE_TO_ONE:
                  EList<JvmMember> _members_10 = it.getMembers();
                  JvmField _field_2 = this._servicesTypesBuilder.toField(f_1, f_1.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_1.getService()));
                  this._servicesTypesBuilder.<JvmField>operator_add(_members_10, _field_2);
                  break;
                case ONE_TO_MANY:
                  EList<JvmMember> _members_11 = it.getMembers();
                  JvmField _field_3 = this._servicesTypesBuilder.toField(f_1, f_1.getAttributeName(), 
                    this.references.getTypeForName(Set.class, service, this._servicesTypesBuilder.cloneWithProxies(f_1.getService())));
                  this._servicesTypesBuilder.<JvmField>operator_add(_members_11, _field_3);
                  break;
                default:
                  EList<JvmMember> _members_12 = it.getMembers();
                  JvmField _field_4 = this._servicesTypesBuilder.toField(f_1, f_1.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_1.getService()));
                  this._servicesTypesBuilder.<JvmField>operator_add(_members_12, _field_4);
                  break;
              }
            } else {
              EList<JvmMember> _members_12 = it.getMembers();
              JvmField _field_4 = this._servicesTypesBuilder.toField(f_1, f_1.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_1.getService()));
              this._servicesTypesBuilder.<JvmField>operator_add(_members_12, _field_4);
            }
          }
        }
        EList<LServiceOperation> _operations_1 = service.getOperations();
        for (final LServiceOperation f_2 : _operations_1) {
          EList<JvmMember> _members_13 = it.getMembers();
          final Procedure1<JvmOperation> _function_9 = (JvmOperation it_1) -> {
            this._servicesTypesBuilder.setDocumentation(it_1, this._servicesTypesBuilder.getDocumentation(f_2));
            EList<JvmFormalParameter> _params = f_2.getParams();
            for (final JvmFormalParameter p : _params) {
              EList<JvmFormalParameter> _parameters = it_1.getParameters();
              JvmFormalParameter _parameter = this._servicesTypesBuilder.toParameter(p, p.getName(), p.getParameterType());
              this._servicesTypesBuilder.<JvmFormalParameter>operator_add(_parameters, _parameter);
            }
            this._servicesTypesBuilder.setBody(it_1, f_2.getBody());
          };
          JvmOperation _method_5 = this._servicesTypesBuilder.toMethod(f_2, this._modelExtensions.toName(f_2), f_2.getType(), _function_9);
          this._servicesTypesBuilder.<JvmOperation>operator_add(_members_13, _method_5);
        }
        LInjectedServices _injectedServices_1 = service.getInjectedServices();
        boolean _tripleNotEquals_4 = (_injectedServices_1 != null);
        if (_tripleNotEquals_4) {
          EList<LInjectedService> _services_2 = service.getInjectedServices().getServices();
          for (final LInjectedService f_3 : _services_2) {
            LCardinality _cardinality_1 = f_3.getCardinality();
            if (_cardinality_1 != null) {
              switch (_cardinality_1) {
                case ZERO_TO_ONE:
                  EList<JvmMember> _members_14 = it.getMembers();
                  JvmOperation _bindService = this._servicesTypesBuilder.toBindService(f_3, f_3.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_3.getService()));
                  this._servicesTypesBuilder.<JvmOperation>operator_add(_members_14, _bindService);
                  EList<JvmMember> _members_15 = it.getMembers();
                  JvmOperation _unbindService = this._servicesTypesBuilder.toUnbindService(f_3, f_3.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_3.getService()));
                  this._servicesTypesBuilder.<JvmOperation>operator_add(_members_15, _unbindService);
                  break;
                case ONE_TO_ONE:
                  EList<JvmMember> _members_16 = it.getMembers();
                  JvmOperation _bindService_1 = this._servicesTypesBuilder.toBindService(f_3, f_3.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_3.getService()));
                  this._servicesTypesBuilder.<JvmOperation>operator_add(_members_16, _bindService_1);
                  EList<JvmMember> _members_17 = it.getMembers();
                  JvmOperation _unbindService_1 = this._servicesTypesBuilder.toUnbindService(f_3, f_3.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_3.getService()));
                  this._servicesTypesBuilder.<JvmOperation>operator_add(_members_17, _unbindService_1);
                  break;
                case ZERO_TO_MANY:
                  EList<JvmMember> _members_18 = it.getMembers();
                  JvmOperation _addService = this._servicesTypesBuilder.toAddService(f_3, f_3.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_3.getService()));
                  this._servicesTypesBuilder.<JvmOperation>operator_add(_members_18, _addService);
                  EList<JvmMember> _members_19 = it.getMembers();
                  JvmOperation _removeService = this._servicesTypesBuilder.toRemoveService(f_3, f_3.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_3.getService()));
                  this._servicesTypesBuilder.<JvmOperation>operator_add(_members_19, _removeService);
                  break;
                case ONE_TO_MANY:
                  EList<JvmMember> _members_20 = it.getMembers();
                  JvmOperation _addService_1 = this._servicesTypesBuilder.toAddService(f_3, f_3.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_3.getService()));
                  this._servicesTypesBuilder.<JvmOperation>operator_add(_members_20, _addService_1);
                  EList<JvmMember> _members_21 = it.getMembers();
                  JvmOperation _removeService_1 = this._servicesTypesBuilder.toRemoveService(f_3, f_3.getAttributeName(), this._servicesTypesBuilder.cloneWithProxies(f_3.getService()));
                  this._servicesTypesBuilder.<JvmOperation>operator_add(_members_21, _removeService_1);
                  break;
                default:
                  break;
              }
            }
          }
        }
      }
      String _name = service.getName();
      String _plus = ("Inferring service " + _name);
      doInferLog.stop(this.log, _plus);
    };
    acceptor.<JvmGenericType>accept(type).initializeLater(_function);
  }
  
  public void inferFullState(final JvmType type, final EObject service, final IJvmDeclaredTypeAcceptor acceptor, final boolean isPrelinkingPhase, final String selector) {
    if (type instanceof JvmGenericType
         && service instanceof LDTOService) {
      _inferFullState((JvmGenericType)type, (LDTOService)service, acceptor, isPrelinkingPhase, selector);
      return;
    } else if (type != null
         && service != null) {
      _inferFullState(type, service, acceptor, isPrelinkingPhase, selector);
      return;
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(type, service, acceptor, isPrelinkingPhase, selector).toString());
    }
  }
  
  public void infer(final EObject service, final IJvmDeclaredTypeAcceptor acceptor, final boolean isPrelinkingPhase) {
    if (service instanceof LDTOService) {
      _infer((LDTOService)service, acceptor, isPrelinkingPhase);
      return;
    } else if (service != null) {
      _infer(service, acceptor, isPrelinkingPhase);
      return;
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(service, acceptor, isPrelinkingPhase).toString());
    }
  }
  
  public void inferTypesOnly(final EObject service, final IJvmDeclaredTypeAcceptor acceptor, final boolean isPrelinkingPhase) {
    if (service instanceof LDTOService) {
      _inferTypesOnly((LDTOService)service, acceptor, isPrelinkingPhase);
      return;
    } else if (service != null) {
      _inferTypesOnly(service, acceptor, isPrelinkingPhase);
      return;
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(service, acceptor, isPrelinkingPhase).toString());
    }
  }
}
