package jetbrains.mps.baseLanguage.unitTest.execution.client;

/*Generated by MPS */

import org.jetbrains.mps.openapi.language.SAbstractConcept;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import jetbrains.mps.baseLanguage.unitTest.platform.TestDiscoveryRequest;
import jetbrains.mps.baseLanguage.unitTest.platform.TestDescriptor;
import java.util.Optional;
import jetbrains.mps.baseLanguage.unitTest.platform.TestDiscoveryParticipant;
import jetbrains.mps.baseLanguage.unitTest.platform.TestPlatform;
import jetbrains.mps.internal.collections.runtime.Sequence;
import org.jetbrains.mps.openapi.language.SProperty;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;

public enum TestNodeWrapperFactory {;

  private final boolean myRoot;
  private final SAbstractConcept myWrappedConcept;

  TestNodeWrapperFactory(SAbstractConcept wrappedConcept, boolean root) {
    myRoot = root;
    myWrappedConcept = wrappedConcept;
  }

  public boolean accept(SNode node) {
    return SNodeOperations.isInstanceOf(node, SNodeOperations.asSConcept(myWrappedConcept));
  }

  public boolean isRoot() {
    return myRoot;
  }

  @Nullable
  public static ITestNodeWrapper tryToWrap(@NotNull SNode node) {
    if (!(SPropertyOperations.getBoolean(SModelOperations.getModuleStub(SNodeOperations.getModel(node)), PROPS.compileInMPS$2Q_X))) {
      return null;
    }
    TestDiscoveryRequest request = new TestDiscoveryRequest(new TestDescriptor());
    Optional<ITestNodeWrapper> wrapped = request.discover(node).map((descriptor) -> {
      return new TestDescriptorWrapper(descriptor, new TestDescriptorWrapper(descriptor.getContainer()));

    });
    if (wrapped.isPresent()) {
      return wrapped.get();
    }
    return null;
  }

  public static SNode findWrappableAncestor(SNode source, boolean isRoot) {
    TestDiscoveryParticipant tdp = TestPlatform.getInstance().getAggregateDiscoveryParticipant();
    Iterable<SAbstractConcept> concepts = tdp.sourceConcepts();
    return SNodeOperations.getNodeAncestorWhereConceptInList(source, Sequence.fromIterable(concepts).toGenericArray(SAbstractConcept.class), true, isRoot);
  }

  private static final class PROPS {
    /*package*/ static final SProperty compileInMPS$2Q_X = MetaAdapterFactory.getProperty(0x86ef829012bb4ca7L, 0x947f093788f263a9L, 0x5869770da61dfe1eL, 0x5869770da61dfe24L, "compileInMPS");
  }
}
