package jetbrains.mps.editor.runtime.impl.cellActions;

/*Generated by MPS */

import jetbrains.mps.annotations.GeneratedClass;
import jetbrains.mps.editor.runtime.cells.AbstractCellAction;
import jetbrains.mps.openapi.editor.EditorContext;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import jetbrains.mps.openapi.editor.cells.EditorCellContext;
import jetbrains.mps.openapi.editor.menus.transformation.SNodeLocation;
import java.util.Objects;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.smodel.behaviour.BHReflection;
import jetbrains.mps.core.aspects.behaviour.SMethodIdV2;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SAbstractLink;
import org.jetbrains.mps.openapi.language.SReferenceLink;
import org.jetbrains.mps.openapi.language.SConcept;

@GeneratedClass(node = "r:b9f36c08-4a75-4513-9277-a390d3426e0f(jetbrains.mps.editor.runtime.impl.cellActions)/7082927757140330659", model = "r:b9f36c08-4a75-4513-9277-a390d3426e0f(jetbrains.mps.editor.runtime.impl.cellActions)")
public class CellAction_InsertPlaceholder extends AbstractCellAction {
  private final boolean myIsAfter;
  public CellAction_InsertPlaceholder(boolean isAfter) {
    myIsAfter = isAfter;
  }

  @Override
  public boolean canExecute(EditorContext editorContext) {
    return findPlaceToInsert(editorContext.getContextCell()) != null;
  }
  public void execute(EditorContext editorContext) {
    findPlaceToInsert(editorContext.getContextCell()).withAfter(myIsAfter).insertPlaceholder();
  }
  private PlaceToInsert findPlaceToInsert(EditorCell contextCell) {
    PlaceToInsert placeFromCollectionCell = getPlaceFromCollectionCell(contextCell);
    if (placeFromCollectionCell != null) {
      return placeFromCollectionCell;
    }

    SNode parentNode;
    SNode childNode;
    SContainmentLink containmentLink;

    while (contextCell != null) {
      EditorCellContext cellContext = contextCell.getCellContext();
      PlaceToInsert placeToInsert = null;
      if (cellContext != null) {
        SNodeLocation nodeLocation = cellContext.getNodeLocation();
        if (nodeLocation != null) {
          parentNode = nodeLocation.getParent();
          childNode = nodeLocation.getContextNode();
          containmentLink = nodeLocation.getContainmentLink();
          if (Objects.equals(containmentLink, LINKS.smodelAttribute$KJ43)) {
            if (SNodeOperations.isInstanceOf(((SNode) childNode), CONCEPTS.ChildAttribute$m8)) {
              containmentLink = ((SContainmentLink) BHReflection.invoke0(SNodeOperations.cast(childNode, CONCEPTS.ChildAttribute$m8), CONCEPTS.ChildAttribute$m8, SMethodIdV2.create("getLink", 709746936026609871L, 0x553941aeb020c32eL)));
            } else if (SNodeOperations.isInstanceOf(((SNode) childNode), CONCEPTS.NodeAttribute$x2)) {
              childNode = parentNode;
              parentNode = check_d2uk49_a0b0a0a3a1a2a7a5(parentNode);
              containmentLink = check_d2uk49_a0c0a0a3a1a2a7a5(childNode);
            }
          }
          if (containmentLink != null && containmentLink.isMultiple() && !(Objects.equals(containmentLink, LINKS.smodelAttribute$KJ43)) && parentNode != null) {
            return new PlaceToInsert(parentNode, childNode, containmentLink);
          }
        }
      }
      contextCell = contextCell.getParent();
    }
    return null;
  }

  private static class PlaceToInsert {
    @NotNull
    private final SNode myParentNode;
    @Nullable
    private final SNode myChildNode;
    @NotNull
    private SContainmentLink myContainmentLink;
    private boolean myIsAfter = true;

    private PlaceToInsert(@NotNull SNode parentNode, @Nullable SNode childNode, @NotNull SContainmentLink containmentLink) {
      myParentNode = parentNode;
      myChildNode = childNode;
      myContainmentLink = containmentLink;
    }

    /*package*/ void insertPlaceholder() {
      SNode placeholder = SConceptOperations.createNewNode(MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x339681b4da4ef1a7L, "jetbrains.mps.lang.core.structure.BasePlaceholder"));
      BHReflection.invoke0(placeholder, CONCEPTS.ChildAttribute$m8, SMethodIdV2.create("setLink", 709746936026609906L, 0x553941aeb020c32eL), myContainmentLink);
      if (myIsAfter) {
        myParentNode.insertChildAfter(LINKS.smodelAttribute$KJ43, placeholder, myChildNode);
      } else {
        myParentNode.insertChildBefore(LINKS.smodelAttribute$KJ43, placeholder, myChildNode);
      }
    }

    /*package*/ PlaceToInsert withAfter(boolean isAfter) {
      myIsAfter = isAfter;
      return this;
    }
  }

  private static PlaceToInsert getPlaceFromCollectionCell(EditorCell cell) {
    if (cell.getSRole() == null) {
      return null;
    }

    SAbstractLink role = (SAbstractLink) cell.getSRole();
    if (role == null || (role instanceof SReferenceLink) || !(role.isMultiple())) {
      return null;
    }

    return new PlaceToInsert(cell.getSNode(), null, (SContainmentLink) role);
  }
  private static SNode check_d2uk49_a0b0a0a3a1a2a7a5(SNode checkedDotOperand) {
    if (null != checkedDotOperand) {
      return checkedDotOperand.getParent();
    }
    return null;
  }
  private static SContainmentLink check_d2uk49_a0c0a0a3a1a2a7a5(SNode checkedDotOperand) {
    if (null != checkedDotOperand) {
      return checkedDotOperand.getContainmentLink();
    }
    return null;
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept ChildAttribute$m8 = MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x9d98713f247885aL, "jetbrains.mps.lang.core.structure.ChildAttribute");
    /*package*/ static final SConcept NodeAttribute$x2 = MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x2eb1ad060897da54L, "jetbrains.mps.lang.core.structure.NodeAttribute");
  }

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