package org.zalando.intellij.swagger.reference.usage;

import com.intellij.json.psi.JsonProperty;
import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.util.Processor;
import java.util.Optional;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.psi.YAMLKeyValue;
import org.zalando.intellij.swagger.traversal.path.PathExpressionUtil;

public class SpecReferenceSearch
    extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {

  private static final boolean CASE_SENSITIVE = false;
  private static final boolean REQUIRE_READ_ACTION = true;

  public SpecReferenceSearch() {
    super(REQUIRE_READ_ACTION);
  }

  @Override
  public void processQuery(
      @NotNull final ReferencesSearch.SearchParameters queryParameters,
      @NotNull final Processor<? super PsiReference> consumer) {
    final PsiElement elementToSearch = queryParameters.getElementToSearch();

    if (elementToSearch instanceof YAMLKeyValue || elementToSearch instanceof JsonProperty) {
      Optional.ofNullable(((PsiNamedElement) elementToSearch).getName())
          .ifPresent(
              word ->
                  queryParameters
                      .getOptimizer()
                      .searchWord(
                          PathExpressionUtil.escapeJsonPointer(word),
                          GlobalSearchScope.allScope(queryParameters.getProject()),
                          CASE_SENSITIVE,
                          elementToSearch));
    }
  }
}

@@ -150,16 +150,106 @@
 orBase;%0A
+import com.intellij.openapi.project.Project;%0Aimport com.intellij.openapi.vfs.VirtualFile;%0A
 import c
@@ -612,16 +612,71 @@
 yValue;%0A
+import org.zalando.intellij.swagger.index.IndexFacade;%0A
 import o
@@ -967,16 +967,51 @@
  = true;
+%0A  private IndexFacade indexFacade;
 %0A%0A  publ
@@ -1033,16 +1033,45 @@
 eSearch(
+final IndexFacade indexFacade
 ) %7B%0A    
@@ -1097,16 +1097,53 @@
 ACTION);
+%0A%0A    this.indexFacade = indexFacade;
 %0A  %7D%0A%0A  
@@ -1403,100 +1403,391 @@
     
-if (elementToSearch instanceof YAMLKeyValue %7C%7C elementToSearch instanceof JsonProperty
+final Project project = queryParameters.getProject();%0A%0A    if (indexFacade.isIndexReady(project)) %7B%0A      if (isSpec(elementToSearch, project)) %7B%0A        process(queryParameters, elementToSearch, project);%0A      %7D%0A    %7D%0A  %7D%0A%0A  private void process(%0A      final ReferencesSearch.SearchParameters queryParameters,%0A      final PsiElement elementToSearch,%0A      final Project project
 ) %7B%0A
-  
     
@@ -1861,18 +1861,16 @@
         
-  
 .ifPrese
@@ -1873,18 +1873,16 @@
 resent(%0A
-  
         
@@ -1892,19 +1892,144 @@
  word -%3E
+ %7B
 %0A  
+            final String escaped = PathExpressionUtil.escapeJsonPointer(word);%0A%0A              if (!escaped.equals(word)) %7B%0A
         
@@ -2072,18 +2072,16 @@
         
-  
 .getOpti
@@ -2088,18 +2088,16 @@
 mizer()%0A
-  
         
@@ -2149,56 +2149,17 @@
     
-  PathExpressionUtil.escapeJsonPointer(word),%0A  
+escaped,%0A
     
@@ -2209,41 +2209,18 @@
 ope(
-queryParameters.getP
+p
 roject
-()
 ),%0A
-  
     
@@ -2283,34 +2283,486 @@
     
-  elementToSearch));%0A    %7D
+elementToSearch);%0A              %7D%0A            %7D);%0A  %7D%0A%0A  private boolean isSpec(final PsiElement elementToSearch, final Project project) %7B%0A    if (elementToSearch instanceof YAMLKeyValue %7C%7C elementToSearch instanceof JsonProperty) %7B%0A      final VirtualFile virtualFile = elementToSearch.getContainingFile().getVirtualFile();%0A%0A      return indexFacade.isMainSpecFile(virtualFile, project)%0A          %7C%7C indexFacade.isPartialSpecFile(virtualFile, project);%0A    %7D%0A%0A    return false;
 %0A  %7D

Fix high CPU usage