/*
 * Copyright 2000-2012 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.psi.search;

import com.intellij.JavaTestUtil;
import com.intellij.find.findUsages.JavaFindUsagesHandler;
import com.intellij.find.findUsages.JavaFindUsagesHandlerFactory;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.MethodReferencesSearch;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.PsiTestCase;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.testFramework.fixtures.TempDirTestFixture;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.Processor;
import com.intellij.util.containers.IntArrayList;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class FindUsagesTest extends PsiTestCase{

  @Override
  protected void setUp() throws Exception {
    super.setUp();

    String root = JavaTestUtil.getJavaTestDataPath() + "/psi/search/findUsages/" + getTestName(true);
    PsiTestUtil.removeAllRoots(myModule, IdeaTestUtil.getMockJdk17());
    PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete);
  }

  public void testOverloadConstructors() throws Exception {
    PsiClass aClass = myJavaFacade.findClass("B", GlobalSearchScope.allScope(myProject));
    PsiMethod constructor = aClass.findMethodsByName("B", false)[0];
    PsiMethodCallExpression superCall = (PsiMethodCallExpression) constructor.getBody().getStatements()[0].getFirstChild();
    PsiReferenceExpression superExpr = superCall.getMethodExpression();
    String[] fileNames = {"B.java", "A.java", "A.java", "B.java"};
    int[] starts = {};
    int[] ends = {};
    final ArrayList<PsiFile> filesList = new ArrayList<PsiFile>();
    final IntArrayList startsList = new IntArrayList();
    final IntArrayList endsList = new IntArrayList();
    PsiReference[] refs =
      MethodReferencesSearch.search((PsiMethod)superExpr.resolve(), GlobalSearchScope.projectScope(myProject), false).toArray(PsiReference.EMPTY_ARRAY);
    for (PsiReference ref : refs) {
      addReference(ref, filesList, startsList, endsList);
    }
    checkResult(fileNames, filesList, starts, startsList, ends, endsList);
  }

  public void testSiblingImplement() throws Exception {
    PsiClass anInterface = myJavaFacade.findClass("A.I", GlobalSearchScope.allScope(myProject));
    PsiMethod method = anInterface.getMethods()[0];
    final Collection<PsiMethod> overriders = OverridingMethodsSearch.search(method).findAll();
    assertEquals(1, overriders.size());
  }

  public void testProtectedMethodInPackageLocalClass() throws Throwable {
    PsiMethod method = myJavaFacade.findClass("foo.PackageLocal", GlobalSearchScope.allScope(myProject)).getMethods()[0];
    assertEquals(1, OverridingMethodsSearch.search(method).findAll().size());
    assertEquals(1, ReferencesSearch.search(method).findAll().size());
  }

  public void testLibraryClassUsageFromDecompiledSource() {
    PsiElement decompiled =
      ((PsiCompiledElement)myJavaFacade.findClass("javax.swing.JLabel", GlobalSearchScope.allScope(myProject))).getMirror();
    assertEquals(2, ReferencesSearch.search(decompiled, GlobalSearchScope.projectScope(myProject)).findAll().size());
  }

  public void testImplicitConstructorUsage() throws Throwable {
    PsiMethod[] ctrs = myJavaFacade.findClass("Foo", GlobalSearchScope.allScope(myProject)).getConstructors();
    PsiMethod method = ctrs[0];
    assertEquals(0, method.getParameterList().getParametersCount());
    assertEquals(0, ReferencesSearch.search(method).findAll().size());

    PsiMethod usedMethod = ctrs[1];
    assertEquals(1, usedMethod.getParameterList().getParametersCount());
    assertEquals(1, ReferencesSearch.search(usedMethod).findAll().size());
  }

  private static void addReference(PsiReference ref, ArrayList<PsiFile> filesList, IntArrayList startsList, IntArrayList endsList) {
    PsiElement element = ref.getElement();
    filesList.add(element.getContainingFile());
    TextRange range = element.getTextRange();
    TextRange rangeInElement = ref.getRangeInElement();
    startsList.add(range.getStartOffset() + rangeInElement.getStartOffset());
    endsList.add(range.getStartOffset() + rangeInElement.getEndOffset());
  }

  public void testFieldInJavadoc() throws Exception{
    PsiClass aClass = myJavaFacade.findClass("A", GlobalSearchScope.allScope(myProject));
    PsiField field = aClass.findFieldByName("FIELD", false);
    doTest(field, new String[]{"A.java"}, new int[]{}, new int[]{});
  }

  public void testXml() throws Exception{
    PsiClass aClass = myJavaFacade.findClass("com.Foo", GlobalSearchScope.allScope(myProject));
    doTest(aClass, new String[]{"Test.xml"}, new int[]{32}, new int[]{35});

    final PsiFile nonCodeUsage = PsiFileFactory.getInstance(myProject).createFileFromText("a.xml", StdFileTypes.XML, "<root action='com.Foo'/>", 0, true);
    assertTrue(new UsageInfo(nonCodeUsage, 14, 21, true).getNavigationOffset() > 0);
  }

  public void testNonCodeClassUsages() throws Exception {
    final TempDirTestFixture tdf = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture();
    tdf.setUp();

    try {
      new WriteCommandAction(getProject()) {
        @Override
        protected void run(Result result) throws Throwable {
          final ModifiableModuleModel moduleModel = ModuleManager.getInstance(getProject()).getModifiableModel();
          moduleModel.newModule("independent/independent.iml", StdModuleTypes.JAVA.getId());
          moduleModel.commit();

          tdf.createFile("plugin.xml", "<document>\n" +
                                       "  <action class=\"com.Foo\" />\n" +
                                       "  <action class=\"com.Foo.Bar\" />\n" +
                                       "  <action class=\"com.Foo$Bar\" />\n" +
                                       "</document>");

          PsiTestUtil.addContentRoot(ModuleManager.getInstance(getProject()).findModuleByName("independent"), tdf.getFile(""));
        }
      }.execute();

      GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
      PsiClass foo = myJavaFacade.findClass("com.Foo", scope);
      PsiClass bar = myJavaFacade.findClass("com.Foo.Bar", scope);

      final int[] count = {0};
      Processor<UsageInfo> processor = new Processor<UsageInfo>() {
        @Override
        public boolean process(UsageInfo usageInfo) {
          int navigationOffset = usageInfo.getNavigationOffset();
          assertTrue(navigationOffset > 0);
          String textAfter = usageInfo.getFile().getText().substring(navigationOffset);
          assertTrue(textAfter, textAfter.startsWith("Foo") || textAfter.startsWith("Bar") ||
                                textAfter.startsWith("com.Foo.Bar") // sorry, can't get references with dollar-dot mismatch to work now
          );
          count[0]++;
          return true;
        }
      };
      JavaFindUsagesHandler handler = new JavaFindUsagesHandler(bar, JavaFindUsagesHandlerFactory.getInstance(getProject()));

      count[0] = 0;
      handler.processUsagesInText(foo, processor, scope);
      assertEquals(3, count[0]);

      count[0] = 0;
      handler.processUsagesInText(bar, processor, scope);
      assertEquals(2, count[0]);
    }
    finally {
      tdf.tearDown();
    }
  }

  public static void doTest(PsiElement element, String[] fileNames, int[] starts, int[] ends) throws Exception {
    final ArrayList<PsiFile> filesList = new ArrayList<PsiFile>();
    final IntArrayList startsList = new IntArrayList();
    final IntArrayList endsList = new IntArrayList();
    ReferencesSearch.search(element, GlobalSearchScope.projectScope(element.getProject()), false).forEach(new PsiReferenceProcessorAdapter(new PsiReferenceProcessor() {
        @Override
        public boolean execute(PsiReference ref) {
          addReference(ref, filesList, startsList, endsList);
          return true;
        }
      }));

    checkResult(fileNames, filesList, starts, startsList, ends, endsList);

  }

  private static class SearchResult implements Comparable<SearchResult> {
    String fileName;
    int startOffset;
    int endOffset;

    private SearchResult(final String fileName, final int startOffset, final int endOffset) {
      this.fileName = fileName;
      this.startOffset = startOffset;
      this.endOffset = endOffset;
    }

    @Override
    public int compareTo(final SearchResult o) {
      int rc = fileName.compareTo(o.fileName);
      if (rc != 0) return rc;

      rc = startOffset - o.startOffset;
      if (rc != 0) return rc;

      return endOffset - o.endOffset;
    }

    public String toString() {
      return fileName + "[" + startOffset + ":" + endOffset + "]";
    }

    public boolean equals(final Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      final SearchResult that = (SearchResult)o;

      if (endOffset != that.endOffset) return false;
      if (startOffset != that.startOffset) return false;
      if (fileName != null ? !fileName.equals(that.fileName) : that.fileName != null) return false;

      return true;
    }
  }

  private static void checkResult(String[] fileNames, final ArrayList<PsiFile> filesList, int[] starts, final IntArrayList startsList, int[] ends, final IntArrayList endsList) {
    List<SearchResult> expected = new ArrayList<SearchResult>();
    for (int i = 0; i < fileNames.length; i++) {
      String fileName = fileNames[i];
      expected.add(new SearchResult(fileName, i < starts.length ? starts[i] : -1, i < ends.length ? ends[i] : -1));
    }

    List<SearchResult> actual = new ArrayList<SearchResult>();
    for (int i = 0; i < filesList.size(); i++) {
      PsiFile psiFile = filesList.get(i);
      actual.add(
        new SearchResult(psiFile.getName(), i < starts.length ? startsList.get(i) : -1, i < ends.length ? endsList.get(i) : -1));
    }

    Collections.sort(expected);
    Collections.sort(actual);

    assertEquals("Usages don't match", expected, actual);
  }
}
