/*
 * Copyright 2000-2014 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.
 */

/*
 * Created by IntelliJ IDEA.
 * User: cdr
 * Date: Jul 31, 2007
 * Time: 2:39:56 PM
 */
package com.intellij.codeInsight.daemon;

import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.InspectionToolRegistrar;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.SkipSlowTestLocally;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import java.util.*;

@SkipSlowTestLocally
public class HighlightStressTest extends LightDaemonAnalyzerTestCase {
  @NotNull
  @Override
  protected LocalInspectionTool[] configureLocalInspectionTools() {
    if ("RandomEditingForUnused".equals(getTestName(false))) {
      return new LocalInspectionTool[]{new UnusedSymbolLocalInspection(), new UnusedImportLocalInspection(),};
    }
    List<InspectionToolWrapper> all = InspectionToolRegistrar.getInstance().createTools();
    List<LocalInspectionTool> locals = new ArrayList<LocalInspectionTool>();
    for (InspectionToolWrapper tool : all) {
      if (tool instanceof LocalInspectionToolWrapper) {
        LocalInspectionTool e = ((LocalInspectionToolWrapper)tool).getTool();
        locals.add(e);
      }
    }
    return locals.toArray(new LocalInspectionTool[locals.size()]);
  }

  @NonNls private static final String text = "import java.util.*; class X { void f ( ) { "
  + "List < String > ls = new ArrayList < String > ( 1 ) ; ls . toString ( ) ; \n"
  + "List < Integer > is = new ArrayList < Integer > ( 1 ) ; is . toString ( ) ; \n"
  + "List i = new ArrayList ( 1 ) ; i . toString ( ) ; \n"
  + "Collection < Number > l2 = new ArrayList < Number > ( 10 ) ; l2 . toString ( ) ; \n"
  + "Collection < Number > l22 = new ArrayList < Number > ( ) ; l22 . toString ( ) ; \n"
  + "Map < Number , String > l3 = new HashMap < Number , String > ( 10 ) ; l3 . toString ( ) ; \n"
  + "Map < String , String > m = new HashMap < String , String > ( ) ; m . toString ( ) ; \n"
  + "Map < String , String > m1 = new HashMap < String , String > ( ) ; m1 . toString ( ) ; \n"
  + "Map < String , String > m2 = new HashMap < String , String > ( ) ; m2 . toString ( ) ; \n"
  + "Map < String , String > m3 = new HashMap < String , String > ( ) ; m3 . toString ( ) ; \n"
  + "Map < String , String > mi = new HashMap < String , String > ( 1 ) ; mi . toString ( ) ; \n"
  + "Map < String , String > mi1 = new HashMap < String , String > ( 1 ) ; mi1 . toString ( ) ; \n"
  + "Map < String , String > mi2 = new HashMap < String , String > ( 1 ) ; mi2 . toString ( ) ; \n"
  + "Map < String , String > mi3 = new HashMap < String , String > ( 1 ) ; mi3 . toString ( ) ; \n"
  + "Map < Number , String > l4 = new HashMap < Number , String > ( ) ; l4 . toString ( ) ; \n"
  + "Map < Number , String > l5 = new HashMap < Number , String > ( l4 ) ; l5 . toString ( ) ; \n"
  + "HashMap < Number , String > l6 = new HashMap < Number , String > ( ) ; l6 . toString ( ) ; \n"
  + "Map < List < Integer > , Map < String , List < String > > > l7 = new HashMap ( 1 ) ; l7 . toString ( ) ; \n"
  + "java . util . Map < java . util . List < Integer > , java . util . Map < String , java . util . List < String > > > l77 = new java . util . HashMap ( 1 ) ; l77 . toString ( ) ; \n"
  + " } } ";

  public void testAllTheseConcurrentThreadsDoNotCrashAnything() throws Exception {
    long time = System.currentTimeMillis();
    for (int i = 0; i < 20/*00000*/; i++) {
      //System.out.println("i = " + i);
      getPsiManager().dropResolveCaches();
      ((PsiManagerEx)getPsiManager()).getFileManager().cleanupForNextTest();
      DaemonCodeAnalyzer.getInstance(getProject()).restart();

      configureFromFileText("Stress.java", text);
      List<HighlightInfo> infos = doHighlighting();
      assertEmpty(DaemonAnalyzerTestCase.filter(infos, HighlightSeverity.ERROR));
      UIUtil.dispatchAllInvocationEvents();
      FileEditorManagerEx.getInstanceEx(getProject()).closeAllFiles();
    }
    System.out.println(System.currentTimeMillis() - time+"ms");
  }

  public void _testHugeFile() throws Exception {
    @NonNls String filePath =  "/psi/resolve/Thinlet.java";
    configureByFile(filePath);
    doHighlighting();

    int N = 42;
    long[] time = new long[N];
    for (int i = 0; i < N; i++) {
      DaemonCodeAnalyzer.getInstance(getProject()).restart();

      long start = System.currentTimeMillis();
      doHighlighting();
      long end = System.currentTimeMillis();
      time[i] = end - start;
      System.out.println("i = " + i + "; time= "+(end-start));

      UIUtil.dispatchAllInvocationEvents();
    }
    System.out.println("Average among the N/3 median times: " + PlatformTestUtil.averageAmongMedians(time, 3) + "ms");

    //System.out.println("JobLauncher.COUNT   = " + JobLauncher.COUNT);
    //System.out.println("JobLauncher.TINY    = " + JobLauncher.TINY_COUNT);
    //System.out.println("JobLauncher.LENGTH  = " + JobLauncher.LENGTH);
    //System.out.println("JobLauncher.ELAPSED = " + JobLauncher.ELAPSED);
    //System.out.println("Ave length : "+(JobLauncher.LENGTH.get()/1.0/JobLauncher.COUNT.get()));
    //System.out.println("Ave elapsed: "+(JobLauncher.ELAPSED.get()/1.0/JobLauncher.COUNT.get()));
    //
    //JobLauncher.lengths.sort();
    //System.out.println("Lengths: "+JobLauncher.lengths);
  }

  public void testRandomEditingPerformance() throws Exception {
    configureFromFileText("Stress.java", text);
    List<HighlightInfo> list = doHighlighting();
    int warnings = list.size();
    Random random = new Random();

    DaemonCodeAnalyzer.getInstance(getProject()).restart();
    int N = 20;
    long[] time = new long[N];

    for (int i = 0; i < N; i++) {
      long start = System.currentTimeMillis();

      System.out.println("i = " + i);
      String s = myFile.getText();
      int offset;
      while (true) {
        offset = random.nextInt(s.length());
        if (s.charAt(offset) == ' ') break;
      }
      myEditor.getCaretModel().moveToOffset(offset);
      type("/*--*/");
      Collection<HighlightInfo> infos = doHighlighting();
      if (warnings != infos.size()) {
        list = new ArrayList<HighlightInfo>(list);
        Collections.sort(list, new Comparator<HighlightInfo>() {
          @Override
          public int compare(HighlightInfo o1, HighlightInfo o2) {
            if (o1.equals(o2)) return 0;
            if (o1.getActualStartOffset() != o2.getActualStartOffset()) return o1.getActualStartOffset() - o2.getActualStartOffset();
            return (o1.getText() + o1.getDescription()).compareTo(o2.getText() + o2.getDescription());
          }
        });
        infos = new ArrayList<HighlightInfo>(infos);
        Collections.sort((ArrayList<HighlightInfo>)infos, new Comparator<HighlightInfo>() {
          @Override
          public int compare(HighlightInfo o1, HighlightInfo o2) {
            if (o1.equals(o2)) return 0;
            if (o1.getActualStartOffset() != o2.getActualStartOffset()) return o1.getActualStartOffset() - o2.getActualStartOffset();
            return (o1.getText() + o1.getDescription()).compareTo(o2.getText() + o2.getDescription());
          }
        });
        System.out.println(">--------------------");
        for (HighlightInfo info : list) {
          System.out.println(info);
        }
        System.out.println("---------------------");
        for (HighlightInfo info : infos) {
          System.out.println(info);
        }
        System.out.println("<--------------------");
      }
      assertEquals(infos.toString(), warnings, infos.size());
      for (HighlightInfo info : infos) {
        assertNotSame(info + "", HighlightSeverity.ERROR, info.getSeverity());
      }
      UIUtil.dispatchAllInvocationEvents();

      long end = System.currentTimeMillis();
      time[i] = end - start;
    }
    FileEditorManagerEx.getInstanceEx(getProject()).closeAllFiles();

    System.out.println("Average among the N/3 median times: " + PlatformTestUtil.averageAmongMedians(time, 3) + "ms");
  }

  public void testRandomEditingForUnused() throws Exception {
    configureFromFileText("Stress.java", "class X {<caret>}");

    PsiShortNamesCache cache = PsiShortNamesCache.getInstance(getProject());
    String[] names = cache.getAllClassNames();

    final StringBuilder imports = new StringBuilder();
    final StringBuilder usages = new StringBuilder();
    int v = 0;
    List<PsiClass> aclasses = new ArrayList<PsiClass>();
    for (String name : names) {
      PsiClass[] classes = cache.getClassesByName(name, GlobalSearchScope.allScope(getProject()));
      if (classes.length == 0) continue;
      PsiClass aClass = classes[0];
      if (!aClass.hasModifierProperty(PsiModifier.PUBLIC)) continue;
      if (aClass.getSuperClass() == null) continue;
      PsiClassType[] superTypes = aClass.getSuperTypes();
      if (superTypes.length == 0 || superTypes[0].resolve() == null) continue;
      String qualifiedName = aClass.getQualifiedName();
      if (qualifiedName.startsWith("java.lang.invoke")) continue; // java.lang.invoke.MethodHandle has weird access attributes in recent rt.jar which causes spurious highlighting errors
      imports.append("import " + qualifiedName + ";\n");
      usages.append("/**/ "+aClass.getName() + " var" + v + " = null; var" + v + ".toString();\n");
      aclasses.add(aClass);
      v++;
      if (v>100) break;
    }
    final String text = imports + "\n class X {{\n" + usages + "}}";
    WriteCommandAction.runWriteCommandAction(null, new Runnable() {
      @Override
      public void run() {
        getEditor().getDocument().setText(text);
      }
    });

    List<HighlightInfo> errors = DaemonAnalyzerTestCase.filter(doHighlighting(), HighlightSeverity.WARNING);
    assertEmpty(errors);
    Random random = new Random();
    int unused = 0;
    for (int i = 0; i < 100; i++) {
      String s = myFile.getText();

      int offset;
      while (true) {
        offset = random.nextInt(s.length());
        if (CharArrayUtil.regionMatches(s, offset, "/**/") || CharArrayUtil.regionMatches(s, offset, "//")) break;
      }

      char next = offset < s.length()-1 ? s.charAt(offset+1) : 0;
      if (next == '/') {
        myEditor.getCaretModel().moveToOffset(offset + 1);
        type("**");
        unused--;
      }
      else if (next == '*') {
        myEditor.getCaretModel().moveToOffset(offset + 1);
        delete();
        delete();
        unused++;
      }
      else {
        continue;
      }
      PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
      getFile().accept(new PsiRecursiveElementVisitor() {
        @Override
        public void visitElement(PsiElement element) {
          assertTrue(element.toString(), element.isValid());
          super.visitElement(element);
        }
      });

      System.out.println("i = " + i + " " + next + " at "+offset);

      List<HighlightInfo> infos = doHighlighting();
      errors = DaemonAnalyzerTestCase.filter(infos, HighlightSeverity.ERROR);
      assertEmpty(errors);
      List<HighlightInfo> warns = DaemonAnalyzerTestCase.filter(infos, HighlightSeverity.WARNING);
      if (unused != warns.size()) {
        assertEquals(warns.toString(), unused, warns.size());
      }
    }
    FileEditorManagerEx.getInstanceEx(getProject()).closeAllFiles();
  }


}
