package jetbrains.mps.lang.migration.runtime.base;

/*Generated by MPS */

import jetbrains.mps.annotations.GeneratedClass;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.language.SProperty;
import java.util.Objects;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.smodel.behaviour.BHReflection;
import jetbrains.mps.core.aspects.behaviour.SMethodIdV2;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import org.jetbrains.mps.openapi.language.SReferenceLink;
import org.jetbrains.mps.openapi.language.SAbstractConcept;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations;
import org.jetbrains.mps.openapi.model.SReference;
import jetbrains.mps.smodel.SModelInternal;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SConcept;

@GeneratedClass(node = "528ff3b9-5fc4-40dd-931f-c6ce3650640e/r:f69c3fa1-0e30-4980-84e2-190ae44e4c3d(jetbrains.mps.lang.migration.runtime/jetbrains.mps.lang.migration.runtime.base)/4853505765036703346", model = "528ff3b9-5fc4-40dd-931f-c6ce3650640e/r:f69c3fa1-0e30-4980-84e2-190ae44e4c3d(jetbrains.mps.lang.migration.runtime/jetbrains.mps.lang.migration.runtime.base)")
public class RefactoringRuntime {

  public static void changePropertyInstance(SNode node, final SProperty oldProp, final SProperty newProp) {
    if (node.hasProperty(newProp) && !(Objects.equals(node.getProperty(oldProp), node.getProperty(newProp))) || node.getProperty(oldProp) == null) {
      // merge case
      return;
    }

    Iterable<SNode> attributes = (Iterable<SNode>) node.getChildren(LINKS.smodelAttribute$KJ43);
    Sequence.fromIterable(SNodeOperations.ofConcept(attributes, CONCEPTS.PropertyAttribute$Gb)).where((it) -> ((SProperty) BHReflection.invoke0(it, CONCEPTS.PropertyAttribute$Gb, SMethodIdV2.create("getProperty", 1341860900488756504L, 0x553941aeb020c32eL))).equals(oldProp)).visitAll((it) -> BHReflection.invoke0(it, CONCEPTS.PropertyAttribute$Gb, SMethodIdV2.create("setProperty", 7714691473529670203L, 0x553941aeb020c32eL), newProp));

    String value = node.getProperty(oldProp);
    node.setProperty(newProp, value);
    node.setProperty(oldProp, null);
  }

  public static void changeContainmentLinkInstance(SNode node, final SContainmentLink oldLink, final SContainmentLink newLink) {
    if (node.getChildren(newLink).iterator().hasNext()) {
      // merge case
      return;
    }

    Iterable<SNode> attributes = (Iterable<SNode>) node.getChildren(LINKS.smodelAttribute$KJ43);
    Sequence.fromIterable(SNodeOperations.ofConcept(attributes, CONCEPTS.ChildAttribute$m8)).where((it) -> ((SContainmentLink) BHReflection.invoke0(it, CONCEPTS.ChildAttribute$m8, SMethodIdV2.create("getLink", 709746936026609871L, 0x553941aeb020c32eL))).equals(oldLink)).visitAll((it) -> BHReflection.invoke0(it, CONCEPTS.ChildAttribute$m8, SMethodIdV2.create("setLink", 709746936026609906L, 0x553941aeb020c32eL), newLink));

    List<SNode> children = ListSequence.fromListWithValues(new ArrayList<SNode>(), (Iterable<SNode>) node.getChildren(oldLink));
    for (SNode child : ListSequence.fromList(children)) {
      node.removeChild(child);
      node.addChild(newLink, child);
    }
  }

  public static void changeReferenceLinkInstances(SNode node, final SReferenceLink oldLink, final SReferenceLink newLink) {
    if (node.getReference(newLink) != null) {
      // merge case
      return;
    }

    Iterable<SNode> attributes = (Iterable<SNode>) node.getChildren(LINKS.smodelAttribute$KJ43);
    Sequence.fromIterable(SNodeOperations.ofConcept(attributes, CONCEPTS.LinkAttribute$v_)).where((it) -> ((SReferenceLink) BHReflection.invoke0(it, CONCEPTS.LinkAttribute$v_, SMethodIdV2.create("getLink", 1341860900489573894L, 0x553941aeb020c32eL))).equals(oldLink)).visitAll((it) -> BHReflection.invoke0(it, CONCEPTS.LinkAttribute$v_, SMethodIdV2.create("setLink", 7714691473529772139L, 0x553941aeb020c32eL), newLink));

    SNode referenceTarget = node.getReferenceTarget(oldLink);
    node.setReferenceTarget(newLink, referenceTarget);
    node.setReferenceTarget(oldLink, null);
  }

  public static SNode replaceWithNewConcept(final SNode node, SAbstractConcept newConcept) {
    jetbrains.mps.smodel.SNode newInstance = (jetbrains.mps.smodel.SNode) SConceptOperations.createNewNode(SNodeOperations.asInstanceConcept(newConcept));
    newInstance.setId(((jetbrains.mps.smodel.SNode) node).getNodeId());

    for (SProperty prop : Sequence.fromIterable(node.getProperties())) {
      newInstance.setProperty(prop, node.getProperty(prop));
    }
    for (SReference ref : Sequence.fromIterable(node.getReferences())) {
      newInstance.setReferenceTarget(ref.getLink(), ref.getTargetNode());
    }
    for (SNode child : Sequence.fromIterable(node.getChildren())) {
      SContainmentLink containmentLink = child.getContainmentLink();
      node.removeChild(child);
      newInstance.addChild(containmentLink, child);
    }
    if (SNodeOperations.getModel(node) instanceof SModelInternal) {
      if (!(as_7voxfg_a0a0a0a6a7_0(SNodeOperations.getModel(node), SModelInternal.class).importedLanguageIds().contains(newConcept.getLanguage()))) {
        as_7voxfg_a0a0a0a6a7(SNodeOperations.getModel(node), SModelInternal.class).addLanguage(newConcept.getLanguage());
      }
    }
    final SNode result = SNodeOperations.replaceWithAnother(node, newInstance);
    ListSequence.fromList(SNodeOperations.getNodeDescendants(result, null, true, new SAbstractConcept[]{})).translate((it) -> SNodeOperations.getReferences(it)).where((it) -> SLinkOperations.getTargetNode(it) == node).visitAll((it) -> it.getSourceNode().setReferenceTarget(it.getLink(), result));
    return result;
  }
  private static <T> T as_7voxfg_a0a0a0a6a7(Object o, Class<T> type) {
    return (type.isInstance(o) ? (T) o : null);
  }
  private static <T> T as_7voxfg_a0a0a0a6a7_0(Object o, Class<T> type) {
    return (type.isInstance(o) ? (T) o : null);
  }

  private static final class LINKS {
    /*package*/ static final SContainmentLink smodelAttribute$KJ43 = MetaAdapterFactory.getContainmentLink(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, 0x47bf8397520e5942L, "smodelAttribute");
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept PropertyAttribute$Gb = MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x2eb1ad060897da56L, "jetbrains.mps.lang.core.structure.PropertyAttribute");
    /*package*/ static final SConcept ChildAttribute$m8 = MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x9d98713f247885aL, "jetbrains.mps.lang.core.structure.ChildAttribute");
    /*package*/ static final SConcept LinkAttribute$v_ = MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x2eb1ad060897da51L, "jetbrains.mps.lang.core.structure.LinkAttribute");
  }
}
