// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.libraryJar;

import com.intellij.internal.statistic.beans.MetricEvent;
import com.intellij.internal.statistic.eventLog.FeatureUsageData;
import com.intellij.internal.statistic.service.fus.collectors.ProjectUsagesCollector;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.JarUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.ProjectScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashSet;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Andrey Cheptsov
 */
public class FUSLibraryJarUsagesCollector extends ProjectUsagesCollector {
  private static final String DIGIT_VERSION_PATTERN_PART = "(\\d+.\\d+|\\d+)";
  private static final Pattern JAR_FILE_NAME_PATTERN = Pattern.compile("[\\w|\\-|\\.]+-(" + DIGIT_VERSION_PATTERN_PART + "[\\w|\\.]*)jar");

  @NotNull
  @Override
  public String getGroupId() {
    return "javaLibraryJars";
  }

  @Override
  public int getVersion() {
    return 2;
  }

  @NotNull
  @Override
  public Set<MetricEvent> getMetrics(@NotNull Project project) {
    LibraryJarDescriptor[] descriptors = LibraryJarStatisticsService.getInstance().getTechnologyDescriptors();
    Set<MetricEvent> result = new HashSet<>(descriptors.length);

    ApplicationManager.getApplication().runReadAction(() -> {
      for (LibraryJarDescriptor descriptor : descriptors) {
        String className = descriptor.myClass;
        if (className == null) continue;

        PsiClass[] psiClasses = JavaPsiFacade.getInstance(project).findClasses(className, ProjectScope.getLibrariesScope(project));
        for (PsiClass psiClass : psiClasses) {
          VirtualFile jarFile = JarFileSystem.getInstance().getVirtualFileForJar(psiClass.getContainingFile().getVirtualFile());
          if (jarFile != null) {
            String version = getVersionByJarManifest(jarFile);
            if (version == null) version = getVersionByJarFileName(jarFile.getName());
            if (StringUtil.isNotEmpty(version)) {
              final FeatureUsageData data = new FeatureUsageData().addVersionByString(version).addData("library", descriptor.myName);
              result.add(new MetricEvent("used.library", data));
            }
          }
        }
      }
    });

    return result;
  }

  @Nullable
  private static String getVersionByJarManifest(@NotNull VirtualFile file) {
    return JarUtil.getJarAttribute(VfsUtilCore.virtualToIoFile(file), Attributes.Name.IMPLEMENTATION_VERSION);
  }

  @Nullable
  private static String getVersionByJarFileName(@NotNull String fileName) {
    Matcher fileNameMatcher = JAR_FILE_NAME_PATTERN.matcher(fileName);
    if (!fileNameMatcher.matches()) return null;

    return StringUtil.trimTrailing(fileNameMatcher.group(1), '.');
  }
}
@@ -437,34 +437,26 @@
 ication.
-ApplicationManager
+ReadAction
 ;%0Aimport
@@ -844,16 +844,67 @@
 tScope;%0A
+import com.intellij.util.containers.ContainerUtil;%0A
 import o
@@ -1874,72 +1874,8 @@
 );%0A%0A
-    ApplicationManager.getApplication().runReadAction(() -%3E %7B%0A  
     
@@ -1930,26 +1930,24 @@
 rs) %7B%0A      
-  
 String class
@@ -1975,26 +1975,24 @@
 lass;%0A      
- 
- 
 if (classNam
@@ -2013,16 +2013,73 @@
 tinue;%0A%0A
+      MetricEvent event = ReadAction.nonBlocking(() -%3E %7B%0A
         
@@ -2765,17 +2765,13 @@
   re
-sult.add(
+turn 
 new 
@@ -2803,17 +2803,16 @@
 %22, data)
-)
 ;%0A      
@@ -2851,17 +2851,110 @@
     
+ 
-%7D%0A    %7D);
+ return null;%0A      %7D).executeSynchronously();%0A      ContainerUtil.addIfNotNull(result, event);%0A    %7D
 %0A%0A  

use non-blocking read action in FUSLibraryJarUsagesCollector EA-231468