package jetbrains.mps.baseLanguage.editor;

/*Generated by MPS */

import jetbrains.mps.nodeEditor.menus.substitute.SubstituteMenuBase;
import jetbrains.mps.lang.editor.menus.EditorMenuDescriptorBase;
import jetbrains.mps.smodel.SNodePointer;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import jetbrains.mps.lang.editor.menus.MenuPart;
import jetbrains.mps.openapi.editor.menus.substitute.SubstituteMenuItem;
import jetbrains.mps.openapi.editor.menus.substitute.SubstituteMenuContext;
import java.util.ArrayList;
import jetbrains.mps.lang.editor.menus.substitute.ConstraintsFilteringSubstituteMenuPartDecorator;
import jetbrains.mps.lang.editor.menus.substitute.SingleItemSubstituteMenuPart;
import org.jetbrains.annotations.Nullable;
import jetbrains.mps.lang.editor.menus.substitute.DefaultSubstituteMenuItem;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.smodel.action.SNodeFactoryOperations;
import jetbrains.mps.baseLanguage.actions.ExpectedType_FactoryUtil;
import jetbrains.mps.baseLanguage.actions.PrecedenceUtil;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.lang.core.behavior.BaseConcept__BehaviorDescriptor;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.smodel.builder.SNodeBuilder;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SConcept;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import org.jetbrains.mps.openapi.language.SReferenceLink;
import org.jetbrains.mps.openapi.language.SProperty;

public class smartCast extends SubstituteMenuBase {
  public smartCast() {
    super(false, new EditorMenuDescriptorBase("named substitute menu " + "smartCast", new SNodePointer("r:00000000-0000-4000-0000-011c895902c3(jetbrains.mps.baseLanguage.editor)", "1741258697586960298")));
  }
  @NotNull
  @Override
  protected List<MenuPart<SubstituteMenuItem, SubstituteMenuContext>> getParts(final SubstituteMenuContext _context) {
    List<MenuPart<SubstituteMenuItem, SubstituteMenuContext>> result = new ArrayList<MenuPart<SubstituteMenuItem, SubstituteMenuContext>>();
    result.add(new ConstraintsFilteringSubstituteMenuPartDecorator(new SMP_Action_nkius4_a(), CONCEPTS.Expression$mB));
    result.add(new ConstraintsFilteringSubstituteMenuPartDecorator(new SMP_Action_nkius4_b(), CONCEPTS.Expression$mB));
    return result;
  }

  private class SMP_Action_nkius4_a extends SingleItemSubstituteMenuPart {

    @Nullable
    @Override
    protected SubstituteMenuItem createItem(SubstituteMenuContext _context) {
      Item item = new Item(_context);
      item.resetTraceInfo();
      return item;
    }
    private class Item extends DefaultSubstituteMenuItem {
      private final SubstituteMenuContext _context;
      public Item(SubstituteMenuContext context) {
        super(CONCEPTS.Expression$mB, context);
        _context = context;
      }

      /*package*/ void resetTraceInfo() {
        String description = "Substitute item: " + getMatchingText("");
        updateTraceInfo(description, new SNodePointer("r:00000000-0000-4000-0000-011c895902c3(jetbrains.mps.baseLanguage.editor)", "1741258697586960300"));
      }

      @Nullable
      @Override
      public SNode createNode(@NotNull String pattern) {
        if (!(SNodeOperations.isInstanceOf(_context.getCurrentTargetNode(), CONCEPTS.Expression$mB))) {
          return SNodeFactoryOperations.createNewNode(CONCEPTS.CastExpression$$8, null);
        }
        SNode originalExpression = ExpectedType_FactoryUtil.getOriginalExpression(_context.getParentNode(), SNodeOperations.cast(_context.getCurrentTargetNode(), CONCEPTS.Expression$mB));
        SNode castType = null;
        if ((originalExpression != null)) {
          castType = ExpectedType_FactoryUtil.createExpectedType(SNodeOperations.cast(originalExpression, CONCEPTS.Expression$mB));
        }
        if (SNodeOperations.isInstanceOf(_context.getParentNode(), CONCEPTS.Expression$mB) && !(SNodeOperations.isInstanceOf(_context.getParentNode(), CONCEPTS.ParenthesizedExpression$Ws))) {
          SNode p = _quotation_createNode_nkius4_a0a0e0a0(SNodeOperations.copyNode(castType), SNodeOperations.copyNode(_context.getCurrentTargetNode()));
          PrecedenceUtil.parenthesiseIfNecessary(SLinkOperations.getTarget(SNodeOperations.cast(SLinkOperations.getTarget(p, LINKS.expression$TlhM), CONCEPTS.CastExpression$$8), LINKS.expression$XDmN));
          return p;
        } else {
          SNode c = _quotation_createNode_nkius4_a0a0a4a0a(SNodeOperations.copyNode(castType), SNodeOperations.copyNode(_context.getCurrentTargetNode()));
          PrecedenceUtil.parenthesiseIfNecessary(SLinkOperations.getTarget(c, LINKS.expression$XDmN));
          return c;
        }
      }

      @Nullable
      @Override
      public String getMatchingText(@NotNull String pattern) {
        return CONCEPTS.CastExpression$$8.getConceptAlias();
      }
      @Nullable
      @Override
      public String getDescriptionText(@NotNull String pattern) {
        return CONCEPTS.CastExpression$$8.getShortDescription();
      }
    }
  }
  private class SMP_Action_nkius4_b extends SingleItemSubstituteMenuPart {

    @Nullable
    @Override
    protected SubstituteMenuItem createItem(SubstituteMenuContext _context) {
      Item item = new Item(_context);
      item.resetTraceInfo();
      return item;
    }
    private class Item extends DefaultSubstituteMenuItem {
      private final SubstituteMenuContext _context;
      public Item(SubstituteMenuContext context) {
        super(CONCEPTS.Expression$mB, context);
        _context = context;
      }

      /*package*/ void resetTraceInfo() {
        String description = "Substitute item: " + getMatchingText("");
        updateTraceInfo(description, new SNodePointer("r:00000000-0000-4000-0000-011c895902c3(jetbrains.mps.baseLanguage.editor)", "1741258697586960470"));
      }

      @Nullable
      @Override
      public SNode createNode(@NotNull String pattern) {
        SNode cast = SNodeFactoryOperations.createNewNode(_context.getModel(), CONCEPTS.CastExpression$$8, null);
        SNode parens = SNodeFactoryOperations.createNewNode(_context.getModel(), CONCEPTS.ParenthesizedExpression$Ws, null);
        SLinkOperations.setTarget(parens, LINKS.expression$TlhM, cast);
        SNode instanceOf = ExpectedType_FactoryUtil.getCorrespondingInstanceOf((_context.getCurrentTargetNode() != null && SNodeOperations.getParent(_context.getCurrentTargetNode()) == _context.getParentNode() ? _context.getCurrentTargetNode() : _context.getParentNode()));
        if ((instanceOf != null)) {
          SLinkOperations.setTarget(cast, LINKS.type$XD7M, SNodeOperations.copyNode(SLinkOperations.getTarget(instanceOf, LINKS.classType$StzW)));
          SLinkOperations.setTarget(cast, LINKS.expression$XDmN, (_context.getCurrentTargetNode() == null || SNodeOperations.getConcept(_context.getCurrentTargetNode()).isAbstract() ? SNodeOperations.copyNode(SLinkOperations.getTarget(instanceOf, LINKS.leftExpression$StkV)) : null));
          if ((SLinkOperations.getTarget(cast, LINKS.expression$XDmN) == null) && SNodeOperations.isInstanceOf(_context.getCurrentTargetNode(), CONCEPTS.Expression$mB)) {
            SLinkOperations.setTarget(cast, LINKS.expression$XDmN, SNodeOperations.copyNode(_context.getCurrentTargetNode()));
          }
        } else if (SNodeOperations.isInstanceOf(_context.getCurrentTargetNode(), CONCEPTS.Expression$mB)) {
          SNode originalExpression = ExpectedType_FactoryUtil.getOriginalExpression(_context.getParentNode(), SNodeOperations.cast(_context.getCurrentTargetNode(), CONCEPTS.Expression$mB));
          if ((originalExpression != null)) {
            SNode castType = ExpectedType_FactoryUtil.createExpectedType(SNodeOperations.cast(_context.getCurrentTargetNode(), CONCEPTS.Expression$mB));
            if (castType != null) {
              SLinkOperations.setTarget(cast, LINKS.type$XD7M, castType);
            }
          }

          SLinkOperations.setTarget(cast, LINKS.expression$XDmN, SNodeOperations.copyNode(_context.getCurrentTargetNode()));
        }
        SNode expr = SLinkOperations.getTarget(SNodeOperations.cast(SLinkOperations.getTarget(parens, LINKS.expression$TlhM), CONCEPTS.CastExpression$$8), LINKS.expression$XDmN);
        if (expr != null) {
          PrecedenceUtil.parenthesiseIfNecessary(expr);
        }
        return parens;
      }

      @Nullable
      @Override
      public String getMatchingText(@NotNull String pattern) {
        if (pattern.startsWith("(")) {
          String typeName = "type";
          String varName = "expr";
          SNode instanceOf = ExpectedType_FactoryUtil.getCorrespondingInstanceOf((_context.getCurrentTargetNode() != null && SNodeOperations.getParent(_context.getCurrentTargetNode()) == _context.getParentNode() ? _context.getCurrentTargetNode() : _context.getParentNode()));
          SNode var;
          if (instanceOf != null) {
            if (SNodeOperations.isInstanceOf(SLinkOperations.getTarget(instanceOf, LINKS.classType$StzW), CONCEPTS.ClassifierType$bL)) {
              typeName = BaseConcept__BehaviorDescriptor.getPresentation_idhEwIMiw.invoke(SNodeOperations.cast(SLinkOperations.getTarget(instanceOf, LINKS.classType$StzW), CONCEPTS.ClassifierType$bL));
            }
            var = (_context.getCurrentTargetNode() == null || SNodeOperations.getConcept(_context.getCurrentTargetNode()).isAbstract() ? SLinkOperations.getTarget(instanceOf, LINKS.leftExpression$StkV) : _context.getCurrentTargetNode());
          } else {
            if (SNodeOperations.isInstanceOf(_context.getCurrentTargetNode(), CONCEPTS.Expression$mB)) {
              SNode originalExpression = ExpectedType_FactoryUtil.getOriginalExpression(_context.getParentNode(), SNodeOperations.cast(_context.getCurrentTargetNode(), CONCEPTS.Expression$mB));
              if ((originalExpression != null)) {
                SNode castType = ExpectedType_FactoryUtil.createExpectedType(SNodeOperations.cast(_context.getCurrentTargetNode(), CONCEPTS.Expression$mB));
                if (castType != null) {
                  if (SNodeOperations.isInstanceOf(castType, CONCEPTS.ClassifierType$bL)) {
                    typeName = BaseConcept__BehaviorDescriptor.getPresentation_idhEwIMiw.invoke((SNodeOperations.cast(castType, CONCEPTS.ClassifierType$bL)));
                  } else {
                    typeName = SConceptOperations.conceptAlias(SNodeOperations.getConcept(castType));
                  }
                }
              }
            }

            var = _context.getCurrentTargetNode();
          }
          if ((SNodeOperations.isInstanceOf(var, CONCEPTS.VariableReference$TC) && SNodeOperations.isInstanceOf(SLinkOperations.getTarget(SNodeOperations.cast(var, CONCEPTS.VariableReference$TC), LINKS.variableDeclaration$N1XG), CONCEPTS.LocalVariableDeclaration$41))) {
            varName = SPropertyOperations.getString(SLinkOperations.getTarget(SNodeOperations.cast(var, CONCEPTS.VariableReference$TC), LINKS.variableDeclaration$N1XG), PROPS.name$MnvL);
          } else if ((SNodeOperations.isInstanceOf(var, CONCEPTS.VariableReference$TC) && SNodeOperations.isInstanceOf(SLinkOperations.getTarget(SNodeOperations.cast(var, CONCEPTS.VariableReference$TC), LINKS.variableDeclaration$N1XG), CONCEPTS.ParameterDeclaration$RG))) {
            varName = SPropertyOperations.getString(SLinkOperations.getTarget(SNodeOperations.cast(var, CONCEPTS.VariableReference$TC), LINKS.variableDeclaration$N1XG), PROPS.name$MnvL);
          }
          return "((" + typeName + ")" + varName + ")";
        }
        return "((type)expr)";

      }
      @Nullable
      @Override
      public String getDescriptionText(@NotNull String pattern) {
        return "smart type cast expression";
      }
    }
  }
  private static SNode _quotation_createNode_nkius4_a0a0e0a0(Object parameter_1, Object parameter_2) {
    SNode quotedNode_3 = null;
    SNode quotedNode_4 = null;
    SNode quotedNode_5 = null;
    SNode quotedNode_6 = null;
    SNodeBuilder nb = new SNodeBuilder(null, null).init(MetaAdapterFactory.getConcept(MetaAdapterFactory.getLanguage(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, "jetbrains.mps.baseLanguage"), 0xfb4ed32b7fL, "ParenthesizedExpression"));
    quotedNode_3 = nb.getResult();
    SNodeBuilder nb1 = new SNodeBuilder(null, null).init(MetaAdapterFactory.getConcept(MetaAdapterFactory.getLanguage(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, "jetbrains.mps.baseLanguage"), 0xf940dabe4aL, "CastExpression"));
    quotedNode_4 = nb1.getResult();
    quotedNode_5 = (SNode) parameter_1;
    if (quotedNode_5 != null) {
      quotedNode_4.addChild(MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940dabe4aL, 0xf940dabe4bL, "type"), SNodeOperations.copyIfNecessary(quotedNode_5));
    }
    quotedNode_6 = (SNode) parameter_2;
    if (quotedNode_6 != null) {
      quotedNode_4.addChild(MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940dabe4aL, 0xf940dabe4cL, "expression"), SNodeOperations.copyIfNecessary(quotedNode_6));
    }
    quotedNode_3.addChild(MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfb4ed32b7fL, 0xfb4ed32b80L, "expression"), quotedNode_4);
    return quotedNode_3;
  }
  private static SNode _quotation_createNode_nkius4_a0a0a4a0a(Object parameter_1, Object parameter_2) {
    SNode quotedNode_3 = null;
    SNode quotedNode_4 = null;
    SNode quotedNode_5 = null;
    SNodeBuilder nb = new SNodeBuilder(null, null).init(MetaAdapterFactory.getConcept(MetaAdapterFactory.getLanguage(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, "jetbrains.mps.baseLanguage"), 0xf940dabe4aL, "CastExpression"));
    quotedNode_3 = nb.getResult();
    quotedNode_4 = (SNode) parameter_1;
    if (quotedNode_4 != null) {
      quotedNode_3.addChild(MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940dabe4aL, 0xf940dabe4bL, "type"), SNodeOperations.copyIfNecessary(quotedNode_4));
    }
    quotedNode_5 = (SNode) parameter_2;
    if (quotedNode_5 != null) {
      quotedNode_3.addChild(MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940dabe4aL, 0xf940dabe4cL, "expression"), SNodeOperations.copyIfNecessary(quotedNode_5));
    }
    return quotedNode_3;
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept Expression$mB = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c37f506fL, "jetbrains.mps.baseLanguage.structure.Expression");
    /*package*/ static final SConcept CastExpression$$8 = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940dabe4aL, "jetbrains.mps.baseLanguage.structure.CastExpression");
    /*package*/ static final SConcept ParenthesizedExpression$Ws = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfb4ed32b7fL, "jetbrains.mps.baseLanguage.structure.ParenthesizedExpression");
    /*package*/ static final SConcept ClassifierType$bL = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101de48bf9eL, "jetbrains.mps.baseLanguage.structure.ClassifierType");
    /*package*/ static final SConcept VariableReference$TC = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, "jetbrains.mps.baseLanguage.structure.VariableReference");
    /*package*/ static final SConcept LocalVariableDeclaration$41 = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc67c7efL, "jetbrains.mps.baseLanguage.structure.LocalVariableDeclaration");
    /*package*/ static final SConcept ParameterDeclaration$RG = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e94L, "jetbrains.mps.baseLanguage.structure.ParameterDeclaration");
  }

  private static final class LINKS {
    /*package*/ static final SContainmentLink expression$TlhM = MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfb4ed32b7fL, 0xfb4ed32b80L, "expression");
    /*package*/ static final SContainmentLink expression$XDmN = MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940dabe4aL, 0xf940dabe4cL, "expression");
    /*package*/ static final SContainmentLink type$XD7M = MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940dabe4aL, 0xf940dabe4bL, "type");
    /*package*/ static final SContainmentLink classType$StzW = MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfbbff03700L, 0xfbbff06219L, "classType");
    /*package*/ static final SContainmentLink leftExpression$StkV = MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfbbff03700L, 0xfbbff06218L, "leftExpression");
    /*package*/ static final SReferenceLink variableDeclaration$N1XG = MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c77f1e98L, 0xf8cc6bf960L, "variableDeclaration");
  }

  private static final class PROPS {
    /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name");
  }
}
