package jetbrains.mps.kotlin.tests.misc.stubs;

/*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 jetbrains.mps.smodel.SNodePointer;
import org.jetbrains.mps.openapi.model.SNodeReference;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPointerOperations;
import java.util.List;
import jetbrains.mps.lang.test.matcher.NodeDifference;
import jetbrains.mps.lang.test.matcher.NodesMatcher;
import org.junit.Assert;
import java.util.stream.Collectors;

@MPSLaunch
public class StubSamplesLoading_Test extends BaseTransformationTest {
  @RegisterExtension
  private static final TestParametersCacheExtension ourParametersCacheExtension = new TestParametersCacheExtension(new TestParametersCache(StubSamplesLoading_Test.class, "${mps_home}", "r:eec037d7-3e10-4036-974a-838b679589c3(jetbrains.mps.kotlin.tests.misc.stubs@tests)", false));

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

  @Test
  public void test_resultClassLoading() throws Throwable {
    new TestBody(this).test_resultClassLoading();
  }
  @Test
  public void test_componentFunctionLoading() throws Throwable {
    new TestBody(this).test_componentFunctionLoading();
  }

  /*package*/ static class TestBody extends BaseTestBody {

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

    public void test_resultClassLoading() throws Exception {
      runWithinCommand(() -> {
        addNodeById("2543656779682200128");
        addNodeById("6949626076594479409");
      });
      runWithinCommand(() -> TestBody.this.assertLoadedAs(new SNodePointer("b50d89c0-0fb9-4105-b652-222148c26a9b/kotlin:kotlin(jetbrains.mps.kotlin.stdlib/)", "~kotlin/Result"), getNodeById("~kotlin/Result")));
    }
    public void test_componentFunctionLoading() throws Exception {
      runWithinCommand(() -> {
        addNodeById("2543656779682200128");
        addNodeById("6949626076594479409");
      });
      runWithinCommand(() -> {
        // This method uses type parameter both in its receiver type and return type
        // If this fails after stubs changes, make sure loading of type parameters into context happens before loading of receiver and return type.
        TestBody.this.assertLoadedAs(new SNodePointer("b50d89c0-0fb9-4105-b652-222148c26a9b/kotlin:kotlin.collections(jetbrains.mps.kotlin.stdlib/)", "~#kotlin/Array<0>.component2<1>()"), getNodeById("~#kotlin/Array<0>.component2<1>()"));
      });
    }

    public void assertLoadedAs(SNodeReference reference, SNode compareTo) {
      // This may fails in several cases, such as:
      // - Kotlin version is updated and definition change on the stub side
      // - Stubs loading are updated
      // Either way, ensure no actual regression happened before updating the expected node here
      SNode stubLoaded = SPointerOperations.resolveNode(reference, myModel.getRepository());
      List<NodeDifference> diff = new NodesMatcher(compareTo, stubLoaded).diff();
      if (!(diff.isEmpty())) {
        Assert.fail(diff.stream().map(NodeDifference::print).collect(Collectors.joining("\n")));
      }
    }
  }
}
