package jetbrains.mps.smodel.test.concepts;

/*Generated by MPS */

import jetbrains.mps.MPSLaunch;
import jetbrains.mps.lang.test.runtime.BaseTransformationTest;
import org.junit.jupiter.api.extension.RegisterExtension;
import jetbrains.mps.lang.test.runtime.TestParametersCacheExtension;
import jetbrains.mps.lang.test.runtime.TestParametersCache;
import org.junit.jupiter.api.Test;
import jetbrains.mps.lang.test.runtime.BaseTestBody;
import jetbrains.mps.lang.test.runtime.TransformationTest;
import org.junit.Assert;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import org.jetbrains.mps.openapi.language.SInterfaceConcept;
import org.jetbrains.mps.openapi.language.SConcept;
import org.jetbrains.mps.openapi.language.SAbstractConcept;
import jetbrains.mps.util.IterableUtil;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;

@MPSLaunch
public class SConceptHierarchy_Test extends BaseTransformationTest {
  @RegisterExtension
  private static final TestParametersCacheExtension ourParametersCacheExtension = new TestParametersCacheExtension(new TestParametersCache(SConceptHierarchy_Test.class, "${mps_home}", "r:783567bb-6a97-47d3-ab6c-d2a82efd2145(jetbrains.mps.smodel.test.concepts@tests)", false));

  public SConceptHierarchy_Test() {
    super(ourParametersCacheExtension.getParametersCache());
  }

  @Test
  public void test_conceptHierarchy() throws Throwable {
    new TestBody(this).test_conceptHierarchy();
  }
  @Test
  public void test_conceptSuperConcept() throws Throwable {
    new TestBody(this).test_conceptSuperConcept();
  }
  @Test
  public void test_defaultIfaceConcept() throws Throwable {
    new TestBody(this).test_defaultIfaceConcept();
  }

  /*package*/ static class TestBody extends BaseTestBody {

    /*package*/ TestBody(TransformationTest owner) {
      super(owner);
    }

    public void test_conceptHierarchy() throws Exception {
      runWithinCommand(() -> {
        Assert.assertTrue(SConceptOperations.isSubConceptOf(SNodeOperations.asSConcept(CONCEPTS.INamedConcept$Kd), CONCEPTS.BaseConcept$gP));
        Assert.assertTrue(CONCEPTS.INamedConcept$Kd.isSubConceptOf(CONCEPTS.BaseConcept$gP));
        Assert.assertFalse(SConceptOperations.isSubConceptOf(SNodeOperations.asSConcept(CONCEPTS.BaseConcept$gP), CONCEPTS.INamedConcept$Kd));
        Assert.assertTrue(SConceptOperations.isSubConceptOf(SNodeOperations.asSConcept(CONCEPTS.INamedConcept$Kd), SNodeOperations.asSConcept(CONCEPTS.INamedConcept$Kd)));
        Assert.assertTrue(CONCEPTS.INamedConcept$Kd instanceof SInterfaceConcept);
        //  there's suspicious code in SConceptAdapter.getSuperInterfaces, make sure it didn't get out elsewhere
        Assert.assertTrue(CONCEPTS.ImplementationWithStubPart$Lx.getSuperInterfaces().iterator().next().equals(CONCEPTS.ImplementationPart$LI));
      });
    }
    public void test_conceptSuperConcept() throws Exception {
      runWithinCommand(() -> {
        // state the fact we do not report BaseConcept as its own super-concept
        // it's questionable, as it makes BC the only concept without superconcept.
        SConcept baseConcept = CONCEPTS.BaseConcept$gP;
        Assert.assertNull(baseConcept.getSuperConcept());
        Assert.assertFalse(baseConcept.getSuperInterfaces().iterator().hasNext());
        Assert.assertTrue(baseConcept.equals(CONCEPTS.Attribute$g1.getSuperConcept()));
        Assert.assertTrue(CONCEPTS.Attribute$g1.equals(CONCEPTS.NodeAttribute$x2.getSuperConcept()));
      });
    }
    public void test_defaultIfaceConcept() throws Exception {
      runWithinCommand(() -> {
        SAbstractConcept defaultIfaceConcept = SNodeOperations.getConcept(SConceptOperations.createNewNode(SNodeOperations.asInstanceConcept(CONCEPTS.INamedConcept$Kd)));
        Assert.assertTrue(SConceptOperations.isSubConceptOf(SNodeOperations.asSConcept(defaultIfaceConcept), CONCEPTS.INamedConcept$Kd));
        Assert.assertTrue(SConceptOperations.isSubConceptOf(SNodeOperations.asSConcept(defaultIfaceConcept), CONCEPTS.BaseConcept$gP));
        // next two checks are questionable, as it puzzles users (see mbeddr slack Sep 17, 2016)
        Assert.assertFalse(defaultIfaceConcept.equals(CONCEPTS.INamedConcept$Kd));
        Assert.assertFalse(SConceptOperations.isExactly(SNodeOperations.asSConcept(defaultIfaceConcept), CONCEPTS.INamedConcept$Kd));

        // was assert false; see MPS-33398
        Assert.assertTrue(CONCEPTS.INamedConcept$Kd.isSubConceptOf(defaultIfaceConcept));

        Assert.assertTrue(defaultIfaceConcept instanceof SConcept);
        Assert.assertTrue(((SConcept) defaultIfaceConcept).getSuperConcept().equals(CONCEPTS.BaseConcept$gP));
        Assert.assertTrue(IterableUtil.asCollection(((SConcept) defaultIfaceConcept).getSuperInterfaces()).size() == 1);
        Assert.assertTrue(((SConcept) defaultIfaceConcept).getSuperInterfaces().iterator().next().equals(CONCEPTS.INamedConcept$Kd));
      });
    }

  }

  private static final class CONCEPTS {
    /*package*/ static final SInterfaceConcept INamedConcept$Kd = MetaAdapterFactory.getInterfaceConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, "jetbrains.mps.lang.core.structure.INamedConcept");
    /*package*/ static final SConcept BaseConcept$gP = MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, "jetbrains.mps.lang.core.structure.BaseConcept");
    /*package*/ static final SInterfaceConcept ImplementationWithStubPart$Lx = MetaAdapterFactory.getInterfaceConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x612410e32cf46136L, "jetbrains.mps.lang.core.structure.ImplementationWithStubPart");
    /*package*/ static final SInterfaceConcept ImplementationPart$LI = MetaAdapterFactory.getInterfaceConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x12509ddfaa7c0557L, "jetbrains.mps.lang.core.structure.ImplementationPart");
    /*package*/ static final SConcept Attribute$g1 = MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x47bf8397520e5939L, "jetbrains.mps.lang.core.structure.Attribute");
    /*package*/ static final SConcept NodeAttribute$x2 = MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x2eb1ad060897da54L, "jetbrains.mps.lang.core.structure.NodeAttribute");
  }
}
