package jetbrains.mps.lang.behavior.findUsages;

/*Generated by MPS */

import jetbrains.mps.ide.findusages.findalgorithm.finders.GeneratedFinder;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.module.SearchScope;
import jetbrains.mps.lang.behavior.behavior.ConceptMethodDeclaration__BehaviorDescriptor;
import jetbrains.mps.baseLanguage.behavior.BaseMethodDeclaration__BehaviorDescriptor;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import jetbrains.mps.ide.findusages.model.scopes.ModelsScope;
import org.jetbrains.mps.openapi.language.SAbstractConcept;
import org.jetbrains.annotations.NotNull;
import jetbrains.mps.ide.findusages.findalgorithm.finders.IFinder;
import org.jetbrains.mps.openapi.util.ProgressMonitor;
import jetbrains.mps.ide.findusages.view.FindUtils;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.progress.EmptyProgressMonitor;
import jetbrains.mps.ide.findusages.model.SearchResult;
import jetbrains.mps.ide.findusages.model.SearchQuery;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.model.SNodeReference;
import org.jetbrains.mps.openapi.language.SConcept;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import org.jetbrains.mps.openapi.language.SReferenceLink;

public class OverridingMethods_Finder extends GeneratedFinder {
  public OverridingMethods_Finder() {
  }
  public boolean isVisible(SNode node, SearchScope scope) {
    if ((boolean) ConceptMethodDeclaration__BehaviorDescriptor.isVirtual_id6WSEafdhbZX.invoke(node) || (boolean) BaseMethodDeclaration__BehaviorDescriptor.isAnAbstractMethod_id28P2dHxCoRl.invoke(node)) {
      return SNodeOperations.isInstanceOf(SNodeOperations.getParent(node), CONCEPTS.ConceptBehavior$2);
    }
    return false;
  }
  @Override
  public boolean isVisible(SNode node) {
    return isVisible(node, new ModelsScope(node.getModel()));
  }
  @Override
  public String getDescription() {
    return "Overriding Methods";
  }
  @Override
  public String getLongDescription() {
    return "";
  }
  @Override
  public SAbstractConcept getSConcept() {
    return CONCEPTS.ConceptMethodDeclaration$N0;
  }
  @Override
  public boolean isApplicable(SNode node) {
    if ((boolean) ConceptMethodDeclaration__BehaviorDescriptor.isVirtual_id6WSEafdhbZX.invoke(node) || (boolean) BaseMethodDeclaration__BehaviorDescriptor.isAnAbstractMethod_id28P2dHxCoRl.invoke(node)) {
      return SNodeOperations.isInstanceOf(SNodeOperations.getParent(node), CONCEPTS.ConceptBehavior$2);
    }
    return false;
  }

  @Override
  protected void doFind0(@NotNull SNode node, final SearchScope scope, final IFinder.FindCallback callback, final ProgressMonitor monitor) {
    try {
      monitor.start("Looking for method implementations", 10);
      FindUtils.searchForResults(monitor.subTask(10), (searchResult) -> {
        SNode nodeParam = (SNode) searchResult.getObject();
        ((_FunctionTypes._void_P1_E0<SNode>) (SNode candidate) -> {
          if (SNodeOperations.isInstanceOf(candidate, CONCEPTS.ConceptMethodDeclaration$N0) && SLinkOperations.getTarget(SNodeOperations.cast(candidate, CONCEPTS.ConceptMethodDeclaration$N0), LINKS.overriddenMethod$quKH) == ConceptMethodDeclaration__BehaviorDescriptor.getOverridenMethod_idhP3pnNO.invoke(node)) {

            callback.onUsageFound(createSingleResult(candidate));
            FindUtils.searchForResults(new EmptyProgressMonitor(), new IFinder.FindCallback() {
              public void onUsageFound(SearchResult<?> searchResult) {
                SNode nodeParam = (SNode) searchResult.getObject();
                ((_FunctionTypes._void_P1_E0<SNode>) (SNode method) -> {
                  if (monitor.isCanceled()) {
                    return;
                  }
                  callback.onUsageFound(createSingleResult(method));
                }).invoke(nodeParam);
              }
            }, new SearchQuery(candidate, scope), FindUtils.getFinder("jetbrains.mps.lang.behavior.findUsages.OverridingMethods_Finder"));
          }
        }).invoke(nodeParam);
      }, new SearchQuery(node, scope), FindUtils.getFinder("jetbrains.mps.lang.structure.findUsages.NodeUsages_Finder"));
    } finally {
      monitor.done();
    }
  }


  @Nullable
  @Override
  public SNodeReference getDeclarationNode() {
    return buildNodePointer(FindUsagesDescriptor.DECLARING_MODEL, "1227530810320");
  }

  private static final class CONCEPTS {
    /*package*/ static final SConcept ConceptBehavior$2 = MetaAdapterFactory.getConcept(0xaf65afd8f0dd4942L, 0x87d963a55f2a9db1L, 0x11d43447b1aL, "jetbrains.mps.lang.behavior.structure.ConceptBehavior");
    /*package*/ static final SConcept ConceptMethodDeclaration$N0 = MetaAdapterFactory.getConcept(0xaf65afd8f0dd4942L, 0x87d963a55f2a9db1L, 0x11d4348057eL, "jetbrains.mps.lang.behavior.structure.ConceptMethodDeclaration");
  }

  private static final class LINKS {
    /*package*/ static final SReferenceLink overriddenMethod$quKH = MetaAdapterFactory.getReferenceLink(0xaf65afd8f0dd4942L, 0x87d963a55f2a9db1L, 0x11d4348057eL, 0x11d4348057fL, "overriddenMethod");
  }
}
