package jetbrains.mps.baseLanguage.methodReferences.generator.templates;

/*Generated by MPS */

import jetbrains.mps.generator.runtime.Generated;
import jetbrains.mps.generator.impl.query.QueryProviderBase;
import jetbrains.mps.generator.template.BaseMappingRuleContext;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.typechecking.TypecheckingFacade;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.baseLanguage.behavior.IInternalType__BehaviorDescriptor;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.generator.template.InsertMacroContext;
import jetbrains.mps.baseLanguage.methodReferences.typesystem.MethodReferenceToClosureUtil;
import java.util.Map;
import jetbrains.mps.generator.impl.query.ReductionRuleCondition;
import java.util.HashMap;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.generator.impl.query.QueryKey;
import jetbrains.mps.generator.template.ReductionRuleQueryContext;
import jetbrains.mps.generator.impl.GenerationFailureException;
import jetbrains.mps.generator.impl.query.InsertMacroQuery;
import org.jetbrains.annotations.Nullable;
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.SReferenceLink;

@Generated
public class QueriesGenerated extends QueryProviderBase {
  public QueriesGenerated() {
    super(1);
  }
  public static boolean rule_Condition_0_0(final BaseMappingRuleContext _context) {
    // Java only support method references for interfaces
    SNode type = TypecheckingFacade.getFromContext().getTypeOf(_context.getNode());
    {
      final SNode internal = type;
      if (SNodeOperations.isInstanceOf(internal, CONCEPTS.IInternalType$eR)) {
        // Filter out method reference type
        type = IInternalType__BehaviorDescriptor.getPublicType_idhEwIXGa.invoke(internal);
      }
    }

    {
      final SNode fncType = type;
      if (SNodeOperations.isInstanceOf(fncType, CONCEPTS.FunctionType$9U)) {
        // No way to predict what will be the use of a function type
        return true;
      }
    }

    SNode classifierType = TypecheckingFacade.getFromContext().coerceType(type, CONCEPTS.ClassifierType$bL);
    return !(SNodeOperations.isInstanceOf(SLinkOperations.getTarget(classifierType, LINKS.classifier$cxMr), CONCEPTS.Interface$db));
  }
  public static SNode insertMacro_Query_0_0(final InsertMacroContext _context) {
    return MethodReferenceToClosureUtil.convertToClosure(_context.getNode(), SLinkOperations.getTarget(_context.getNode(), LINKS.method$8Sfb));
  }
  private final Map<String, ReductionRuleCondition> rrcMethods = new HashMap<String, ReductionRuleCondition>();
  {
    int i = 0;
    rrcMethods.put("6436749721956358698", new RRC(i++));
  }
  @Override
  @NotNull
  public ReductionRuleCondition getReductionRuleCondition(@NotNull QueryKey identity) {
    ReductionRuleCondition query = identity.forTemplateNode(rrcMethods);
    return (query != null ? query : super.getReductionRuleCondition(identity));
  }
  private static class RRC implements ReductionRuleCondition {
    private final int methodKey;
    public RRC(int methodKey) {
      this.methodKey = methodKey;
    }
    @Override
    public boolean check(ReductionRuleQueryContext ctx) throws GenerationFailureException {
      switch (methodKey) {
        case 0:
          return QueriesGenerated.rule_Condition_0_0(ctx);
        default:
          throw new GenerationFailureException(String.format("Inconsistent QueriesGenerated: there's no condition method for rule %s (key: #%d)", ctx.getTemplateReference(), methodKey));
      }
    }
  }
  private final Map<String, InsertMacroQuery> imqMethods = new HashMap<String, InsertMacroQuery>();
  {
    imqMethods.put("1984904195974329327", new IMQ(0));
  }
  @NotNull
  @Override
  public InsertMacroQuery getInsertMacroQuery(@NotNull QueryKey queryKey) {
    InsertMacroQuery query = queryKey.forTemplateNode(imqMethods);
    return (query != null ? query : super.getInsertMacroQuery(queryKey));
  }
  private static class IMQ implements InsertMacroQuery {
    private final int methodKey;
    /*package*/ IMQ(int methodKey) {
      this.methodKey = methodKey;
    }
    @Nullable
    public SNode evaluate(@NotNull InsertMacroContext ctx) throws GenerationFailureException {
      switch (methodKey) {
        case 0:
          return QueriesGenerated.insertMacro_Query_0_0(ctx);
        default:
          throw new GenerationFailureException(String.format("Inconsistent QueriesGenerated: there's no method for query %s (key: #%d)", ctx.getTemplateReference(), methodKey));
      }
    }
  }

  private static final class CONCEPTS {
    /*package*/ static final SInterfaceConcept IInternalType$eR = MetaAdapterFactory.getInterfaceConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x118cd59904dL, "jetbrains.mps.baseLanguage.structure.IInternalType");
    /*package*/ static final SConcept FunctionType$9U = MetaAdapterFactory.getConcept(0xfd3920347849419dL, 0x907112563d152375L, 0x1174a4d19ffL, "jetbrains.mps.baseLanguage.closures.structure.FunctionType");
    /*package*/ static final SConcept ClassifierType$bL = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101de48bf9eL, "jetbrains.mps.baseLanguage.structure.ClassifierType");
    /*package*/ static final SConcept Interface$db = MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, "jetbrains.mps.baseLanguage.structure.Interface");
  }

  private static final class LINKS {
    /*package*/ static final SReferenceLink classifier$cxMr = MetaAdapterFactory.getReferenceLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101de48bf9eL, 0x101de490babL, "classifier");
    /*package*/ static final SReferenceLink method$8Sfb = MetaAdapterFactory.getReferenceLink(0xacfc188dd5d64598L, 0xb3706f4a983f05b2L, 0x30ab9441ca549e7bL, 0x34d254ec4f413c1L, "method");
  }
}
