package jetbrains.mps.baseLanguage.migration;

/*Generated by MPS */

import jetbrains.mps.lang.migration.runtime.base.MigrationScriptBase;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.module.SModule;
import org.jetbrains.mps.openapi.module.SearchScope;
import jetbrains.mps.lang.smodel.query.runtime.CommandUtil;
import jetbrains.mps.project.EditableFilteringScope;
import jetbrains.mps.lang.smodel.query.runtime.QueryExecutionContext;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPointerOperations;
import jetbrains.mps.smodel.SNodePointer;
import java.util.Objects;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import jetbrains.mps.internal.collections.runtime.CollectionSequence;
import jetbrains.mps.ide.findusages.model.scopes.ModelsScope;
import org.jetbrains.mps.openapi.model.SModel;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import jetbrains.mps.baseLanguage.behavior.IBLDeprecatable__BehaviorDescriptor;
import org.jetbrains.mps.openapi.language.SAbstractConcept;
import jetbrains.mps.lang.migration.runtime.base.Problem;
import java.util.List;
import java.util.ArrayList;
import jetbrains.mps.lang.migration.runtime.base.DeprecatedConceptNotMigratedProblem;
import jetbrains.mps.lang.migration.runtime.base.MigrationScriptReference;
import jetbrains.mps.smodel.builder.SNodeBuilder;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import org.jetbrains.mps.openapi.language.SReferenceLink;
import org.jetbrains.mps.openapi.language.SConcept;
import org.jetbrains.mps.openapi.language.SInterfaceConcept;
import org.jetbrains.mps.openapi.language.SProperty;

public class UseDeprecatedInsteadOfToRemoveOrScheduledForRemoval extends MigrationScriptBase {
  private final String description = "Replace the ToRemove and the ScheduledForRemoval annotations with the standard Java's Deprecated annotation";
  public String getCaption() {
    return description;
  }
  @Override
  public boolean isRerunnable() {
    return true;
  }
  public SNode execute(final SModule m) {
    doExecute(m);
    return null;
  }
  public void doExecute(final SModule m) {
    {
      SearchScope scope_pulpev_a0e = CommandUtil.createScope(m);
      final SearchScope scope_pulpev_a0e_0 = new EditableFilteringScope(scope_pulpev_a0e);
      final QueryExecutionContext context = () -> scope_pulpev_a0e_0;

      Sequence.fromIterable(CommandUtil.models(CommandUtil.selectScope(null, context))).visitAll((currentModel) -> {
        final SNode scheduledAnnotation = Sequence.fromIterable(SNodeOperations.ofConcept(SLinkOperations.getChildren(SPointerOperations.resolveNode(new SNodePointer("3f233e7f-b8a6-46d2-a57f-795d56775243/java:org.jetbrains.annotations(Annotations/)", "~ApiStatus"), m.getRepository()), LINKS.member$L_2d), CONCEPTS.Annotation$he)).findFirst((it) -> Objects.equals(SPropertyOperations.getString(it, PROPS.name$MnvL), "ScheduledForRemoval"));
        final SNode inVersionMethod = ListSequence.fromList(SLinkOperations.getChildren(scheduledAnnotation, LINKS.method$_DCK)).findFirst((it) -> Objects.equals(SPropertyOperations.getString(it, PROPS.name$MnvL), "inVersion"));
        CollectionSequence.fromCollection(CommandUtil.instances(CommandUtil.selectScope(new ModelsScope(Sequence.<SModel>singleton(currentModel)), context), CONCEPTS.AnnotationInstance$yl, false)).where((it) -> SLinkOperations.hasPointer(it, LINKS.annotation$12Ek, new SNodePointer("3f233e7f-b8a6-46d2-a57f-795d56775243/java:jetbrains.mps.util.annotation(Annotations/)", "~ToRemove")) || Objects.equals(SLinkOperations.getTarget(it, LINKS.annotation$12Ek), scheduledAnnotation)).visitAll((toRemove) -> {
          SNode valueExpr = (SLinkOperations.hasPointer(toRemove, LINKS.annotation$12Ek, new SNodePointer("3f233e7f-b8a6-46d2-a57f-795d56775243/java:jetbrains.mps.util.annotation(Annotations/)", "~ToRemove")) ? SLinkOperations.getTarget(ListSequence.fromList(SLinkOperations.getChildren(toRemove, LINKS.value$uK2B)).findFirst((it) -> SLinkOperations.hasPointer(it, LINKS.key$bSmV, new SNodePointer("3f233e7f-b8a6-46d2-a57f-795d56775243/java:jetbrains.mps.util.annotation(Annotations/)", "~ToRemove.version()"))), LINKS.value$Y7om) : SLinkOperations.getTarget(ListSequence.fromList(SLinkOperations.getChildren(toRemove, LINKS.value$uK2B)).findFirst((it) -> Objects.equals(SLinkOperations.getTarget(it, LINKS.key$bSmV), inVersionMethod)), LINKS.value$Y7om));
          SNode annotatedNode = SNodeOperations.getParent(toRemove);
          if (!(SNodeOperations.isInstanceOf(annotatedNode, CONCEPTS.IBLDeprecatable$ah))) {
            return;
          }

          SNode sinceExpr = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf93d565d10L, "jetbrains.mps.baseLanguage.structure.StringLiteral"));
          if (SNodeOperations.isInstanceOf(valueExpr, CONCEPTS.FloatingPointConstant$3o)) {
            SPropertyOperations.assign(sinceExpr, PROPS.value$w7MM, SPropertyOperations.getString(SNodeOperations.as(valueExpr, CONCEPTS.FloatingPointConstant$3o), PROPS.value$ENN8));
          } else if (SNodeOperations.isInstanceOf(valueExpr, CONCEPTS.IntegerConstant$Na)) {
            SPropertyOperations.assign(sinceExpr, PROPS.value$w7MM, String.valueOf(SPropertyOperations.getInteger(SNodeOperations.as(valueExpr, CONCEPTS.IntegerConstant$Na), PROPS.value$jgCM)));
          } else if (SNodeOperations.isInstanceOf(valueExpr, CONCEPTS.StringLiteral$xu)) {
            SPropertyOperations.assign(sinceExpr, PROPS.value$w7MM, SPropertyOperations.getString(SNodeOperations.as(valueExpr, CONCEPTS.StringLiteral$xu), PROPS.value$w7MM));
          } else {
            sinceExpr = null;
          }

          IBLDeprecatable__BehaviorDescriptor.markDeprecated_id6Va_BJexupi.invoke(SNodeOperations.as(annotatedNode, CONCEPTS.IBLDeprecatable$ah));
          SNode deprecatedAnnotation = ListSequence.fromList(SNodeOperations.getNodeDescendants(annotatedNode, CONCEPTS.AnnotationInstance$yl, false, new SAbstractConcept[]{})).findFirst((it) -> SLinkOperations.hasPointer(it, LINKS.annotation$12Ek, new SNodePointer("6354ebe7-c22a-4a0f-ac54-50b52ab9b065/java:java.lang(JDK/)", "~Deprecated")));
          if (deprecatedAnnotation == null) {
            return;
          }

          if (sinceExpr != null && ListSequence.fromList(SLinkOperations.getChildren(deprecatedAnnotation, LINKS.value$uK2B)).all((it) -> !(SLinkOperations.hasPointer(it, LINKS.key$bSmV, new SNodePointer("6354ebe7-c22a-4a0f-ac54-50b52ab9b065/java:java.lang(JDK/)", "~Deprecated.since()"))))) {
            SNode instanceValueSince = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x114a71b1af4L, "jetbrains.mps.baseLanguage.structure.AnnotationInstanceValue"));
            SLinkOperations.setTarget(instanceValueSince, LINKS.key$bSmV, SPointerOperations.resolveNode(new SNodePointer("6354ebe7-c22a-4a0f-ac54-50b52ab9b065/java:java.lang(JDK/)", "~Deprecated.since()"), m.getRepository()));
            SLinkOperations.setTarget(instanceValueSince, LINKS.value$Y7om, sinceExpr);
            ListSequence.fromList(SLinkOperations.getChildren(deprecatedAnnotation, LINKS.value$uK2B)).addElement(instanceValueSince);
          }
          if (ListSequence.fromList(SLinkOperations.getChildren(deprecatedAnnotation, LINKS.value$uK2B)).all((it) -> !(SLinkOperations.hasPointer(it, LINKS.key$bSmV, new SNodePointer("6354ebe7-c22a-4a0f-ac54-50b52ab9b065/java:java.lang(JDK/)", "~Deprecated.forRemoval()"))))) {
            SNode instanceValueToRemove = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x114a71b1af4L, "jetbrains.mps.baseLanguage.structure.AnnotationInstanceValue"));
            SLinkOperations.setTarget(instanceValueToRemove, LINKS.key$bSmV, SPointerOperations.resolveNode(new SNodePointer("6354ebe7-c22a-4a0f-ac54-50b52ab9b065/java:java.lang(JDK/)", "~Deprecated.forRemoval()"), m.getRepository()));
            SLinkOperations.setTarget(instanceValueToRemove, LINKS.value$Y7om, createBooleanConstant_pulpev_a0c0m0a0a2a0a0b0a0g());
            ListSequence.fromList(SLinkOperations.getChildren(deprecatedAnnotation, LINKS.value$uK2B)).addElement(instanceValueToRemove);
          }
          SNodeOperations.deleteNode(toRemove);
        });
      });
    }
  }
  @Override
  public Iterable<Problem> check(SModule m) {
    final SNode scheduledAnnotation = Sequence.fromIterable(SNodeOperations.ofConcept(SLinkOperations.getChildren(SPointerOperations.resolveNode(new SNodePointer("3f233e7f-b8a6-46d2-a57f-795d56775243/java:org.jetbrains.annotations(Annotations/)", "~ApiStatus"), m.getRepository()), LINKS.member$L_2d), CONCEPTS.Annotation$he)).findFirst((it) -> Objects.equals(SPropertyOperations.getString(it, PROPS.name$MnvL), "ScheduledForRemoval"));

    final List<Problem> problems = ListSequence.fromList(new ArrayList<Problem>());
    {
      SearchScope scope_pulpev_d0f = CommandUtil.createScope(m);
      final SearchScope scope_pulpev_d0f_0 = new EditableFilteringScope(scope_pulpev_d0f);
      final QueryExecutionContext context = () -> scope_pulpev_d0f_0;
      Sequence.fromIterable(CommandUtil.models(CommandUtil.selectScope(null, context))).visitAll((currentModel) -> CollectionSequence.fromCollection(CommandUtil.instances(CommandUtil.selectScope(new ModelsScope(Sequence.<SModel>singleton(currentModel)), context), CONCEPTS.AnnotationInstance$yl, false)).where((it) -> SLinkOperations.hasPointer(it, LINKS.annotation$12Ek, new SNodePointer("3f233e7f-b8a6-46d2-a57f-795d56775243/java:jetbrains.mps.util.annotation(Annotations/)", "~ToRemove")) || Objects.equals(SLinkOperations.getTarget(it, LINKS.annotation$12Ek), scheduledAnnotation)).visitAll((toRemove) -> ListSequence.fromList(problems).addElement(new DeprecatedConceptNotMigratedProblem(toRemove))));
    }
    return problems;
  }
  public MigrationScriptReference getReference() {
    return new MigrationScriptReference(MetaAdapterFactory.getLanguage(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, "jetbrains.mps.baseLanguage"), 11);
  }

  private static SNode createBooleanConstant_pulpev_a0c0m0a0a2a0a0b0a0g() {
    SNodeBuilder n0 = new SNodeBuilder().init(CONCEPTS.BooleanConstant$n4);
    n0.setProperty(PROPS.value$5y_M, "" + (true));
    return n0.getResult();
  }

  private static final class LINKS {
    /*package*/ static final SContainmentLink member$L_2d = MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, 0x4a9a46de59132803L, "member");
    /*package*/ static final SContainmentLink method$_DCK = MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, 0x101f2cc410bL, "method");
    /*package*/ static final SReferenceLink annotation$12Ek = MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x114a6b4ccabL, 0x114a6b85d40L, "annotation");
    /*package*/ static final SContainmentLink value$uK2B = MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x114a6b4ccabL, 0x114a71c697fL, "value");
    /*package*/ static final SReferenceLink key$bSmV = MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x114a71b1af4L, 0x114a71b44e3L, "key");
    /*package*/ static final SContainmentLink value$Y7om = MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x114a71b1af4L, 0x114a71c0fc4L, "value");
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept Annotation$he = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x114a69dc80cL, "jetbrains.mps.baseLanguage.structure.Annotation");
    /*package*/ static final SConcept AnnotationInstance$yl = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x114a6b4ccabL, "jetbrains.mps.baseLanguage.structure.AnnotationInstance");
    /*package*/ static final SInterfaceConcept IBLDeprecatable$ah = MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x11d2ea8a339L, "jetbrains.mps.baseLanguage.structure.IBLDeprecatable");
    /*package*/ static final SConcept FloatingPointConstant$3o = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x102cb19a434L, "jetbrains.mps.baseLanguage.structure.FloatingPointConstant");
    /*package*/ static final SConcept IntegerConstant$Na = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc59b314L, "jetbrains.mps.baseLanguage.structure.IntegerConstant");
    /*package*/ static final SConcept StringLiteral$xu = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf93d565d10L, "jetbrains.mps.baseLanguage.structure.StringLiteral");
    /*package*/ static final SConcept BooleanConstant$n4 = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b201L, "jetbrains.mps.baseLanguage.structure.BooleanConstant");
  }

  private static final class PROPS {
    /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name");
    /*package*/ static final SProperty value$w7MM = MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf93d565d10L, 0xf93d565d11L, "value");
    /*package*/ static final SProperty value$ENN8 = MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x102cb19a434L, 0x103245d193fL, "value");
    /*package*/ static final SProperty value$jgCM = MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc59b314L, 0xf8cc59b315L, "value");
    /*package*/ static final SProperty value$5y_M = MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b201L, 0xf8cc56b202L, "value");
  }
}
