package jetbrains.mps.baseLanguage.kotlinRefs.editor;

/*Generated by MPS */

import jetbrains.mps.editor.runtime.cells.AbstractCellAction;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.openapi.editor.EditorContext;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.editor.runtime.selection.SelectionUtil;
import jetbrains.mps.openapi.editor.selection.SelectionManager;
import jetbrains.mps.baseLanguage.editor.MethodArgumentsUtil;
import jetbrains.mps.smodel.action.SNodeFactoryOperations;
import jetbrains.mps.openapi.editor.cells.EditorCell;
import jetbrains.mps.openapi.editor.cells.CellAction;
import jetbrains.mps.openapi.editor.cells.CellActionType;
import jetbrains.mps.nodeEditor.cellProviders.AbstractCellListHandler;
import java.util.Objects;
import org.jetbrains.mps.openapi.language.SInterfaceConcept;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SConcept;
import org.jetbrains.mps.openapi.language.SContainmentLink;

public class AddDeleteKotlinFunctionCallArgument {

  /*package*/ static AbstractCellAction createAction_DELETE(final SNode node) {
    return new AbstractCellAction() {
      public void execute(EditorContext editorContext) {
        this.execute_internal(editorContext, node);
      }
      public void execute_internal(EditorContext editorContext, SNode node) {
        SNode methodCall = SNodeOperations.cast(SNodeOperations.getParent(node), CONCEPTS.IKotlinFunctionLikeCall$lJ);
        SNode prevSibling = SNodeOperations.getPrevSibling(node);
        SNode nextSibling = SNodeOperations.getNextSibling(node);
        SNodeOperations.deleteNode(node);
        // TODO implement for kotlin?
        if ((nextSibling != null)) {
          SelectionUtil.selectLabelCellAnSetCaret(editorContext, nextSibling, SelectionManager.FIRST_CELL, 0);
        } else if ((prevSibling != null)) {
          SelectionUtil.selectNode(editorContext, prevSibling);
        } else {
          SelectionUtil.selectCell(editorContext, methodCall, "EMPTY_PARAMETER_LIST");
        }
      }
      @Override
      public boolean canExecute(EditorContext editorContext) {
        return this.canExecute_internal(editorContext, node);
      }
      public boolean canExecute_internal(EditorContext editorContext, SNode node) {
        return SNodeOperations.hasRole(node, LINKS.actualArgument$Q6nt);
      }

    };
  }
  /*package*/ static AbstractCellAction createAction_BACKSPACE(final SNode node) {
    return new AbstractCellAction() {
      public void execute(EditorContext editorContext) {
        this.execute_internal(editorContext, node);
      }
      public void execute_internal(EditorContext editorContext, SNode node) {
        SNode methodCall = SNodeOperations.cast(SNodeOperations.getParent(node), CONCEPTS.IKotlinFunctionLikeCall$lJ);
        SNode prevSibling = SNodeOperations.getPrevSibling(node);
        SNode nextSibling = SNodeOperations.getNextSibling(node);
        SNodeOperations.deleteNode(node);
        // TODO implement for kotlin?
        if ((prevSibling != null)) {
          SelectionUtil.selectLabelCellAnSetCaret(editorContext, prevSibling, SelectionManager.LAST_CELL, -1);
        } else if ((nextSibling != null)) {
          SelectionUtil.selectNode(editorContext, nextSibling);
        } else {
          SelectionUtil.selectCell(editorContext, methodCall, "EMPTY_PARAMETER_LIST");
        }
      }
      @Override
      public boolean canExecute(EditorContext editorContext) {
        return this.canExecute_internal(editorContext, node);
      }
      public boolean canExecute_internal(EditorContext editorContext, SNode node) {
        return SNodeOperations.hasRole(node, LINKS.actualArgument$Q6nt);
      }

    };
  }
  /*package*/ static AbstractCellAction createAction_INSERT(final SNode node) {
    return new AbstractCellAction() {
      public void execute(EditorContext editorContext) {
        this.execute_internal(editorContext, node);
      }
      public void execute_internal(EditorContext editorContext, SNode node) {
        SNode argument = MethodArgumentsUtil.getMethodArgumentAncestor(node);
        SNode newArgument = SNodeOperations.insertNextSiblingChild(argument, SNodeFactoryOperations.createNewNode(CONCEPTS.Expression$mB, null));
        // TODO implement for kotlin?
        SelectionUtil.selectNode(editorContext, newArgument);
      }

    };
  }

  public static void setCellActions(EditorCell editorCell, SNode node, EditorContext context) {
    CellAction originalDelete = editorCell.getAction(CellActionType.DELETE);
    CellAction originalBackspace = editorCell.getAction(CellActionType.BACKSPACE);

    // set actions that were actually defined
    setDefinedCellActions(editorCell, node, context);

    // If we set a DELETE action but no BACKSPACE action,
    // use the DELETE action for BACKSPACE as well.
    CellAction delete = editorCell.getAction(CellActionType.DELETE);
    CellAction backspace = editorCell.getAction(CellActionType.BACKSPACE);
    if (delete != originalDelete && backspace == originalBackspace) {
      editorCell.setAction(CellActionType.BACKSPACE, delete);
    }
    if (delete != originalDelete) {
      editorCell.putUserObject(AbstractCellListHandler.ELEMENT_CELL_DELETE_SET, OB);
    }
    if (backspace != originalBackspace) {
      editorCell.putUserObject(AbstractCellListHandler.ELEMENT_CELL_BACKSPACE_SET, OB);
    }
  }

  private static final Object OB = new Object();

  public static void setDefinedCellActions(EditorCell editorCell, SNode node, EditorContext context) {
    // set cell actions from all imported action maps

    // set cell actions defined directly in this action map
    editorCell.setAction(CellActionType.DELETE, createAction_DELETE(node));
    editorCell.setAction(CellActionType.BACKSPACE, createAction_BACKSPACE(node));
    editorCell.setAction(CellActionType.INSERT, createAction_INSERT(node));
  }

  public static void setDefinedCellActionsOfType(EditorCell editorCell, SNode node, EditorContext context, CellActionType actionType) {

    // set cell action(s) of the given type from imported action maps

    // set cell action of the given type defined directly in this action map
    if (Objects.equals(actionType, CellActionType.DELETE)) {
      editorCell.setAction(actionType, createAction_DELETE(node));
    }
    if (Objects.equals(actionType, CellActionType.BACKSPACE)) {
      editorCell.setAction(actionType, createAction_BACKSPACE(node));
    }
    if (Objects.equals(actionType, CellActionType.INSERT)) {
      editorCell.setAction(actionType, createAction_INSERT(node));
    }
  }

  private static final class CONCEPTS {
    /*package*/ static final SInterfaceConcept IKotlinFunctionLikeCall$lJ = MetaAdapterFactory.getInterfaceConcept(0x2405a196e75d462cL, 0x938bae8e3fac20aaL, 0xeac1f33ddc380f3L, "jetbrains.mps.baseLanguage.kotlinRefs.structure.IKotlinFunctionLikeCall");
    /*package*/ static final SConcept Expression$mB = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37f506fL, "jetbrains.mps.baseLanguage.structure.Expression");
  }

  private static final class LINKS {
    /*package*/ static final SContainmentLink actualArgument$Q6nt = MetaAdapterFactory.getContainmentLink(0x2405a196e75d462cL, 0x938bae8e3fac20aaL, 0xeac1f33ddc380f3L, 0xeac1f33ddc3b0dfL, "actualArgument");
  }
}
