package jetbrains.mps.lang.test.scripts;

/*Generated by MPS */

import java.lang.ref.WeakReference;
import jetbrains.mps.lang.test.runtime.TestsErrorsChecker;
import java.time.Instant;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.components.ComponentHost;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.IAttributeDescriptor;
import jetbrains.mps.lang.test.behavior.NodeOperationsContainer__BehaviorDescriptor;
import jetbrains.mps.errors.item.NodeReportItem;
import jetbrains.mps.lang.test.runtime.NodeCheckerUtil;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.kernel.model.MissingDependenciesFixer;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.model.SModelReference;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SModelOperations;
import jetbrains.mps.smodel.ModelImports;
import org.jetbrains.mps.openapi.language.SConcept;

public final class SpecifyRuleMessagesHelper {
  private static final int SEC_TO_CHECK_AGAIN = 5;
  private static WeakReference<TestsErrorsChecker> ourLastCheck;
  private static Instant ourLastTimestamp = Instant.MIN;

  private final SNode myNodeWeCheck;
  private final ComponentHost myHost;

  public SpecifyRuleMessagesHelper(@NotNull SNode nodeWeCheck, @Nullable ComponentHost host) {
    myNodeWeCheck = nodeWeCheck;
    myHost = host;
  }

  public void fillContainerWithRuleMessages() {
    attachNewContainerIfNeeded(myNodeWeCheck);
    SNode operationsContainer = new IAttributeDescriptor.NodeAttribute(CONCEPTS.NodeOperationsContainer$aj).get(myNodeWeCheck);
    assert (operationsContainer != null);
    NodeOperationsContainer__BehaviorDescriptor.detachAllErrorOperations_id4QaU5oI0Q4j.invoke(operationsContainer);
    Iterable<NodeReportItem> reporters = getErrorReporters();
    for (NodeReportItem reporter : reporters) {
      @Nullable SNode ruleNode = NodeCheckerUtil.getRuleNodeFromReporter(reporter, SNodeOperations.getModel(myNodeWeCheck).getRepository());
      NodeOperationsContainer__BehaviorDescriptor.createNodeAndAttachReference_idnMEi6H8iBO.invoke(operationsContainer, ruleNode, reporter);
      if (ruleNode != null) {
        SpecifyRuleMessagesHelper.addModelImports(operationsContainer, ruleNode);
      }
    }
    new MissingDependenciesFixer(SNodeOperations.getModel(operationsContainer)).fixModuleDependencies();
  }

  private static void attachNewContainerIfNeeded(SNode node) {
    if ((new IAttributeDescriptor.NodeAttribute(CONCEPTS.NodeOperationsContainer$aj).get(node) == null)) {
      SNode container = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0x8585453e6bfb4d80L, 0x98deb16074f1d86cL, 0x11b07a3d4b5L, "jetbrains.mps.lang.test.structure.NodeOperationsContainer"));
      new IAttributeDescriptor.NodeAttribute(CONCEPTS.NodeOperationsContainer$aj).set(node, container);
    }
  }

  public Iterable<NodeReportItem> getErrorReporters() {
    SNode containingRoot = SNodeOperations.getContainingRoot(myNodeWeCheck);
    return new TestsErrorsChecker(containingRoot, myHost).getErrors(myNodeWeCheck);
  }

  private static void addModelImports(SNode container, SNode ruleNode) {
    SModelReference ruleModelRef = SModelOperations.getPointer(SNodeOperations.getModel(ruleNode));
    new ModelImports(SNodeOperations.getModel(container)).addModelImport(ruleModelRef);
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept NodeOperationsContainer$aj = MetaAdapterFactory.getConcept(0x8585453e6bfb4d80L, 0x98deb16074f1d86cL, 0x11b07a3d4b5L, "jetbrains.mps.lang.test.structure.NodeOperationsContainer");
  }
}
