package jetbrains.mps.generator.impl;

/*Generated by MPS */

import jetbrains.mps.annotations.GeneratedClass;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.smodel.behaviour.BHReflection;
import jetbrains.mps.core.aspects.behaviour.SMethodIdV2;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.LinkedList;
import org.jetbrains.mps.openapi.language.SConcept;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SEnumOperations;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import org.jetbrains.mps.openapi.language.SProperty;

@GeneratedClass(node = "r:ab837574-aa54-4b18-9762-b783ef089263(jetbrains.mps.generator.impl)/894226751621690778", model = "r:ab837574-aa54-4b18-9762-b783ef089263(jetbrains.mps.generator.impl)")
public final class GeneratorUtilEx {
  public static String getPatternVariableName(SNode ref) {
    return ((String) BHReflection.invoke0(ref, CONCEPTS.TemplateArgumentPatternRef$dA, SMethodIdV2.create("getVariableName", 2902001550281937661L, 0x3bd222b39cd71affL)));
  }
  public static List<SNode> getTemplateFragments(@NotNull SNode template) {
    List<SNode> templateFragments = new ArrayList<SNode>();
    LinkedList<SNode> queue = new LinkedList<SNode>();
    queue.addFirst(template);
    final SConcept conceptTemplateFragment = CONCEPTS.TemplateFragment$eq;
    while (!(queue.isEmpty())) {
      SNode subnode = queue.removeFirst();
      // do not look for TemplateFragments in subnode's children as TFs couldn't be nested
      boolean tfFound = false;
      for (SNode attr : SLinkOperations.getChildren(subnode, LINKS.smodelAttribute$KJ43)) {
        if (SConceptOperations.isExactly(SNodeOperations.asSConcept(SNodeOperations.getConcept(attr)), SNodeOperations.asSConcept(conceptTemplateFragment))) {
          templateFragments.add((SNode) attr);
          tfFound = true;
          break;
        }
      }
      if (!(tfFound)) {
        queue.addAll(SNodeOperations.getChildren(subnode));
      }
    }
    return templateFragments;
  }

  /**
   * Arguments for ITemplateCall are expressions we need to evaluate. 
   * Simple expressions, like literals or variable references we know how to process, don't require generated function while complex expressions 
   * need a java code to get evaluated (unless we implement support for evaluation some day). 
   * Simple expressions are to get evaluated with {@link jetbrains.mps.generator.impl.GeneratorUtilEx#evaluateExpression(SNode) }
   * 
   * @param expr expression to check
   * @return true if expression is not simple enough to get evaluated in runtime without actual Java code generated
   */
  public static boolean shallGenerateFunctionToEvaluate(SNode expr) {
    // Some Expressions (e.g. genContext.variable) used to get wrapped with TypeHintExpression at startup (see AddTypeHints script),
    // but now it's TypeHintAttribute we shall not notice here
    // 
    // For generated templates, assumptions here shall match switch_Argument,
    // for interpreted, TemplateCall#toExpressionRuntime
    if (SNodeOperations.isInstanceOf(expr, CONCEPTS.TemplateArgumentQueryExpression$Zq)) {
      return true;
    }
    boolean customProcessing = SNodeOperations.isInstanceOf(expr, CONCEPTS.TemplateArgumentVarRefExpression2$1W);
    customProcessing |= SNodeOperations.isInstanceOf(expr, CONCEPTS.TemplateArgumentPatternRef$dA);
    customProcessing |= SNodeOperations.isInstanceOf(expr, CONCEPTS.TemplateArgumentParameterExpression$$z);
    // XXX generated templates are fine with genContext operations, however, there's no support for these in TemplateCall#toExpressionRuntime() yet.
    // I'd need a switch by GenerationContextOp_Base subconcepts that get translated into respective TemplateContext call.
    if (customProcessing) {
      return false;
    }
    boolean literal = SNodeOperations.isInstanceOf(expr, CONCEPTS.NullLiteral$QQ);
    literal |= SNodeOperations.isInstanceOf(expr, CONCEPTS.BooleanConstant$n4);
    literal |= SNodeOperations.isInstanceOf(expr, CONCEPTS.IntegerConstant$Na);
    literal |= SNodeOperations.isInstanceOf(expr, CONCEPTS.StringLiteral$xu);
    return !(literal);
  }

  public static Object evaluateExpression(SNode expr) {
    if (SNodeOperations.isInstanceOf(expr, CONCEPTS.BooleanConstant$n4)) {
      return SPropertyOperations.getBoolean(SNodeOperations.cast(expr, CONCEPTS.BooleanConstant$n4), PROPS.value$5y_M);
    } else if (SNodeOperations.isInstanceOf(expr, CONCEPTS.IntegerConstant$Na)) {
      return SPropertyOperations.getInteger(SNodeOperations.cast(expr, CONCEPTS.IntegerConstant$Na), PROPS.value$jgCM);
    } else if (SNodeOperations.isInstanceOf(expr, CONCEPTS.StringLiteral$xu)) {
      return SPropertyOperations.getString(SNodeOperations.cast(expr, CONCEPTS.StringLiteral$xu), PROPS.value$w7MM);
    } else if (SNodeOperations.isInstanceOf(expr, CONCEPTS.NullLiteral$QQ)) {
      return null;
    }
    throw new IllegalArgumentException();
  }

  public static void dispatchRuleConsequence(@NotNull SNode ruleConsequence, @NotNull ConsequenceDispatch dispatch) {
    if (SNodeOperations.isInstanceOf(ruleConsequence, CONCEPTS.TemplateDeclarationReference$QT)) {
      dispatch.templateDeclarationReference(ruleConsequence);
    } else if (SNodeOperations.isInstanceOf(ruleConsequence, CONCEPTS.InlineTemplateWithContext_RuleConsequence$9i)) {
      dispatch.inlineTemplateWithContext(ruleConsequence);
    } else if (SNodeOperations.isInstanceOf(ruleConsequence, CONCEPTS.InlineTemplate_RuleConsequence$u9)) {
      dispatch.inlineTemplate(ruleConsequence);
    } else if (SNodeOperations.isInstanceOf(ruleConsequence, CONCEPTS.InlineSwitch_RuleConsequence$1f)) {
      dispatch.inlineSwitch(ruleConsequence);
    } else if (SNodeOperations.isInstanceOf(ruleConsequence, CONCEPTS.WeaveEach_RuleConsequence$tI)) {
      dispatch.weaveEach(ruleConsequence);
    } else if (SNodeOperations.isInstanceOf(ruleConsequence, CONCEPTS.AbandonInput_RuleConsequence$o$)) {
      dispatch.abandonInput(ruleConsequence);
    } else if (SNodeOperations.isInstanceOf(ruleConsequence, CONCEPTS.DismissTopMappingRule$Ws)) {
      dispatch.dismissTopRule(ruleConsequence);
    } else {
      dispatch.unknown(ruleConsequence);
    }
  }
  public static String getGeneratorMessage_text(SNode generatorMessage) {
    return SPropertyOperations.getString(generatorMessage, PROPS.messageText$7Xrf);
  }
  public static DismissTopMappingRuleException.MessageType getGeneratorMessage_kind(SNode generatorMessage) {
    if (generatorMessage == null) {
      // this is how it used to be, although to me default to warn/info might be better
      return null;
    }
    if (SEnumOperations.isMember(SPropertyOperations.getEnum(generatorMessage, PROPS.messageType$vgra), 0x11055c831d8L)) {
      return DismissTopMappingRuleException.MessageType.error;
    } else
    if (SEnumOperations.isMember(SPropertyOperations.getEnum(generatorMessage, PROPS.messageType$vgra), 0x11055c81594L)) {
      return DismissTopMappingRuleException.MessageType.warning;
    } else {
      return DismissTopMappingRuleException.MessageType.info;
    }
  }
  public interface ConsequenceDispatch {
    void inlineSwitch(SNode ruleConsequence);
    void inlineTemplateWithContext(SNode ruleConsequence);
    void inlineTemplate(SNode ruleConsequence);
    void templateDeclarationReference(SNode ruleConsequence);
    void weaveEach(SNode ruleConsequence);
    void abandonInput(SNode ruleConsequence);
    void dismissTopRule(SNode ruleConsequence);
    void unknown(SNode ruleConsequence);
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept TemplateArgumentPatternRef$dA = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x42d71bfbeb1a07e5L, "jetbrains.mps.lang.generator.structure.TemplateArgumentPatternRef");
    /*package*/ static final SConcept TemplateFragment$eq = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xff1b29b76cL, "jetbrains.mps.lang.generator.structure.TemplateFragment");
    /*package*/ static final SConcept TemplateArgumentQueryExpression$Zq = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x380132d742e8ccb0L, "jetbrains.mps.lang.generator.structure.TemplateArgumentQueryExpression");
    /*package*/ static final SConcept TemplateArgumentVarRefExpression2$1W = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xe8e73f9584aee0fL, "jetbrains.mps.lang.generator.structure.TemplateArgumentVarRefExpression2");
    /*package*/ static final SConcept TemplateArgumentParameterExpression$$z = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x457655815a794e79L, "jetbrains.mps.lang.generator.structure.TemplateArgumentParameterExpression");
    /*package*/ static final SConcept NullLiteral$QQ = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf940cd6167L, "jetbrains.mps.baseLanguage.structure.NullLiteral");
    /*package*/ static final SConcept BooleanConstant$n4 = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b201L, "jetbrains.mps.baseLanguage.structure.BooleanConstant");
    /*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 TemplateDeclarationReference$QT = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x11013906056L, "jetbrains.mps.lang.generator.structure.TemplateDeclarationReference");
    /*package*/ static final SConcept InlineTemplateWithContext_RuleConsequence$9i = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x7b85dded0be53d6cL, "jetbrains.mps.lang.generator.structure.InlineTemplateWithContext_RuleConsequence");
    /*package*/ static final SConcept InlineTemplate_RuleConsequence$u9 = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x112103dd1e8L, "jetbrains.mps.lang.generator.structure.InlineTemplate_RuleConsequence");
    /*package*/ static final SConcept InlineSwitch_RuleConsequence$1f = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x11644fa2edeL, "jetbrains.mps.lang.generator.structure.InlineSwitch_RuleConsequence");
    /*package*/ static final SConcept WeaveEach_RuleConsequence$tI = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x1104fcac3b1L, "jetbrains.mps.lang.generator.structure.WeaveEach_RuleConsequence");
    /*package*/ static final SConcept AbandonInput_RuleConsequence$o$ = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x1180b1792dbL, "jetbrains.mps.lang.generator.structure.AbandonInput_RuleConsequence");
    /*package*/ static final SConcept DismissTopMappingRule$Ws = MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x11013931abdL, "jetbrains.mps.lang.generator.structure.DismissTopMappingRule");
  }

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

  private static final class PROPS {
    /*package*/ static final SProperty value$5y_M = MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc56b201L, 0xf8cc56b202L, "value");
    /*package*/ static final SProperty value$jgCM = MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8cc59b314L, 0xf8cc59b315L, "value");
    /*package*/ static final SProperty value$w7MM = MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf93d565d10L, 0xf93d565d11L, "value");
    /*package*/ static final SProperty messageText$7Xrf = MetaAdapterFactory.getProperty(0xb401a68083254110L, 0x8fd384331ff25befL, 0x11055c63121L, 0x11055c67157L, "messageText");
    /*package*/ static final SProperty messageType$vgra = MetaAdapterFactory.getProperty(0xb401a68083254110L, 0x8fd384331ff25befL, 0x11055c63121L, 0x11055c93e57L, "messageType");
  }
}
