package jetbrains.mps.lang.generator.pluginSolution.plugin;

/*Generated by MPS */

import org.jetbrains.mps.openapi.module.SRepository;
import org.jetbrains.mps.openapi.model.SModel;
import org.jetbrains.mps.openapi.model.SNode;
import java.util.Set;
import org.jetbrains.mps.openapi.module.SModuleReference;
import java.util.HashSet;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.lang.smodel.behavior.ModuleIdentity__BehaviorDescriptor;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import org.jetbrains.mps.openapi.language.SLanguage;
import jetbrains.mps.smodel.Generator;
import jetbrains.mps.lang.smodel.behavior.LanguageIdentity__BehaviorDescriptor;
import org.jetbrains.mps.openapi.language.SConcept;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SContainmentLink;

/*package*/ class GenPlanFunnel {
  private final SRepository myGeneratorLookupRepo;
  private final SModel myTargetModel;
  private final SNode myTarget;
  private final Set<SModuleReference> mySeenGenerators = new HashSet<SModuleReference>();
  private boolean myDistinctSteps = false;
  private boolean myUseGenerators = true;
  private SNode mySharedGeneratorsStep;
  private SNode mySharedLanguagesStep;

  /*package*/ GenPlanFunnel(@NotNull SRepository generatorLookupRepo, @NotNull SNode target) {
    myTarget = target;
    myTargetModel = SNodeOperations.getModel(target);
    myGeneratorLookupRepo = generatorLookupRepo;
  }

  public GenPlanFunnel distinctSteps(boolean distinctSteps) {
    myDistinctSteps = distinctSteps;
    return this;
  }

  public GenPlanFunnel applyGenerators() {
    myUseGenerators = true;
    return this;
  }

  public GenPlanFunnel transformLanguages() {
    myUseGenerators = false;
    return this;
  }

  public void next(SModuleReference generatorIdentity) {
    if (!(mySeenGenerators.add(generatorIdentity))) {
      return;
    }

    if (myUseGenerators) {
      SNode gmp = SModelOperations.createNewNode(myTargetModel, null, CONCEPTS.GeneratorModulePointer$49);
      SLinkOperations.setNewChild(gmp, LINKS.module$u1do, null);
      ModuleIdentity__BehaviorDescriptor.setModuleReference_idnJmxU5cSTj.invoke(SLinkOperations.getTarget(gmp, LINKS.module$u1do), generatorIdentity);

      SNode generatorStep;
      if (myDistinctSteps || mySharedGeneratorsStep == null) {
        generatorStep = SModelOperations.createNewNode(myTargetModel, null, CONCEPTS.ApplyGenerators$PQ);
        ListSequence.fromList(SLinkOperations.getChildren(myTarget, LINKS.steps$Xwbb)).addElement(generatorStep);
      } else {
        generatorStep = mySharedGeneratorsStep;
      }
      if (!(myDistinctSteps) && mySharedGeneratorsStep == null) {
        mySharedGeneratorsStep = generatorStep;
      }
      ListSequence.fromList(SLinkOperations.getChildren(generatorStep, LINKS.generator$bWty)).addElement(gmp);
    } else {
      SLanguage srcLanguage = as_mld0p3_a0a0a0a2a71(generatorIdentity.resolve(myGeneratorLookupRepo), Generator.class).sourceLanguage();
      SNode langId = SModelOperations.createNewNode(myTargetModel, null, CONCEPTS.LanguageId$UR);
      LanguageIdentity__BehaviorDescriptor.setLanguage_id34EJa6aIcyw.invoke(langId, srcLanguage);
      SNode transform;
      if (myDistinctSteps || mySharedLanguagesStep == null) {
        transform = SModelOperations.createNewNode(myTargetModel, null, CONCEPTS.Transform$a_);
        ListSequence.fromList(SLinkOperations.getChildren(myTarget, LINKS.steps$Xwbb)).addElement(transform);
      } else {
        transform = mySharedLanguagesStep;
      }
      if (!(myDistinctSteps) && mySharedLanguagesStep == null) {
        mySharedLanguagesStep = transform;
      }
      ListSequence.fromList(SLinkOperations.getChildren(transform, LINKS.languages$AUhz)).addElement(langId);
    }
  }
  private static <T> T as_mld0p3_a0a0a0a2a71(Object o, Class<T> type) {
    return (type.isInstance(o) ? (T) o : null);
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept GeneratorModulePointer$49 = MetaAdapterFactory.getConcept(0x7866978ea0f04cc7L, 0x81bc4d213d9375e1L, 0x73246de9adecb80dL, "jetbrains.mps.lang.smodel.structure.GeneratorModulePointer");
    /*package*/ static final SConcept ApplyGenerators$PQ = MetaAdapterFactory.getConcept(0x7ab1a6fa0a114b95L, 0x9e4875f363d6cb00L, 0x73246de9adeca171L, "jetbrains.mps.lang.generator.plan.structure.ApplyGenerators");
    /*package*/ static final SConcept LanguageId$UR = MetaAdapterFactory.getConcept(0x7866978ea0f04cc7L, 0x81bc4d213d9375e1L, 0x312abca18ab8c8c0L, "jetbrains.mps.lang.smodel.structure.LanguageId");
    /*package*/ static final SConcept Transform$a_ = MetaAdapterFactory.getConcept(0x7ab1a6fa0a114b95L, 0x9e4875f363d6cb00L, 0x19443180a2071802L, "jetbrains.mps.lang.generator.plan.structure.Transform");
  }

  private static final class LINKS {
    /*package*/ static final SContainmentLink module$u1do = MetaAdapterFactory.getContainmentLink(0x7866978ea0f04cc7L, 0x81bc4d213d9375e1L, 0x73246de9adecb80dL, 0x73246de9adecb874L, "module");
    /*package*/ static final SContainmentLink steps$Xwbb = MetaAdapterFactory.getContainmentLink(0x7ab1a6fa0a114b95L, 0x9e4875f363d6cb00L, 0x19443180a20717fbL, 0x19443180a2071807L, "steps");
    /*package*/ static final SContainmentLink generator$bWty = MetaAdapterFactory.getContainmentLink(0x7ab1a6fa0a114b95L, 0x9e4875f363d6cb00L, 0x73246de9adeca171L, 0x73246de9adf5a45cL, "generator");
    /*package*/ static final SContainmentLink languages$AUhz = MetaAdapterFactory.getContainmentLink(0x7ab1a6fa0a114b95L, 0x9e4875f363d6cb00L, 0x19443180a2071802L, 0x28dd6d5a7549fa8dL, "languages");
  }
}
