// 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.vcs.log.statistics;

import com.intellij.internal.statistic.beans.MetricEvent;
import com.intellij.internal.statistic.beans.MetricEventFactoryKt;
import com.intellij.internal.statistic.service.fus.collectors.ProjectUsagesCollector;
import com.intellij.internal.statistic.service.fus.collectors.UsageDescriptorKeyValidator;
import com.intellij.internal.statistic.utils.PluginInfoDetectorKt;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.VcsLogFilterCollection;
import com.intellij.vcs.log.impl.*;
import com.intellij.vcs.log.ui.VcsLogUiImpl;
import com.intellij.vcs.log.ui.highlighters.VcsLogHighlighterFactory;
import com.intellij.vcs.log.ui.table.GraphTableModel;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;

import java.util.*;

import static com.intellij.internal.statistic.beans.MetricEventUtilKt.addBoolIfDiffers;
import static com.intellij.internal.statistic.beans.MetricEventUtilKt.addIfDiffers;
import static com.intellij.vcs.log.impl.CommonUiProperties.*;
import static com.intellij.vcs.log.impl.MainVcsLogUiProperties.*;
import static com.intellij.vcs.log.ui.VcsLogUiImpl.LOG_HIGHLIGHTER_FACTORY_EP;

public class VcsLogFeaturesCollector extends ProjectUsagesCollector {
  @NotNull
  @Override
  public Set<MetricEvent> getMetrics(@NotNull Project project) {
    VcsProjectLog projectLog = VcsProjectLog.getInstance(project);
    if (projectLog != null) {
      VcsLogUiImpl ui = projectLog.getMainLogUi();
      if (ui != null) {
        MainVcsLogUiProperties properties = ui.getProperties();
        VcsLogUiProperties defaultProperties = createDefaultPropertiesInstance();

        Set<MetricEvent> metricEvents = ContainerUtil.newHashSet(new MetricEvent("uiInitialized"));

        addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(SHOW_DETAILS), "details");
        addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(SHOW_DIFF_PREVIEW), "diffPreview");
        addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(SHOW_CHANGES_FROM_PARENTS), "parentChanges");
        addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(SHOW_ONLY_AFFECTED_CHANGES), "onlyAffectedChanges");
        addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(SHOW_LONG_EDGES), "long.edges");

        addIfDiffers(metricEvents, properties, defaultProperties, getter(BEK_SORT_TYPE), "sort");

        if (ui.getColorManager().hasMultiplePaths()) {
          addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(SHOW_ROOT_NAMES), "roots");
        }

        addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(COMPACT_REFERENCES_VIEW), "labels.compact");
        addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(SHOW_TAG_NAMES), "labels.showTagNames");

        addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(TEXT_FILTER_REGEX), "textFilter.regex");
        addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(TEXT_FILTER_MATCH_CASE), "textFilter.matchCase");

        for (VcsLogHighlighterFactory factory : LOG_HIGHLIGHTER_FACTORY_EP.getExtensions(project)) {
          if (factory.showMenuItem()) {
            addBoolIfDiffers(metricEvents, properties, defaultProperties, getter(VcsLogHighlighterProperty.get(factory.getId())),
                             "highlighter." + getFactoryIdSafe(factory));
          }
        }

        for (VcsLogFilterCollection.FilterKey<?> key : VcsLogFilterCollection.STANDARD_KEYS) {
          if (properties.getFilterValues(key.getName()) != null) {
            metricEvents.add(MetricEventFactoryKt.newBooleanMetric(key.getName() + "Filter", true));
          }
        }

        Set<Integer> currentColumns = new HashSet<>(properties.get(COLUMN_ORDER));
        Set<Integer> defaultColumns = new HashSet<>(defaultProperties.get(COLUMN_ORDER));
        for (int column : GraphTableModel.DYNAMIC_COLUMNS) {
          addBoolIfDiffers(metricEvents, currentColumns, defaultColumns, p -> p.contains(column),
                           StringUtil.toLowerCase(GraphTableModel.COLUMN_NAMES[column]) + "Column");
        }

        List<String> tabs = projectLog.getTabsManager().getTabs();
        metricEvents.add(MetricEventFactoryKt.newCounterMetric("additionalTabs", tabs.size()));

        return metricEvents;
      }
    }
    return Collections.emptySet();
  }

  @NotNull
  private static String getFactoryIdSafe(@NotNull VcsLogHighlighterFactory factory) {
    if (PluginInfoDetectorKt.getPluginInfo(factory.getClass()).isDevelopedByJetBrains()) {
      return UsageDescriptorKeyValidator.ensureProperKey(factory.getId());
    }
    return "THIRD_PARTY";
  }

  @NotNull
  private static <T> Function1<VcsLogUiProperties, T> getter(@NotNull VcsLogUiProperty<? extends T> property) {
    return p -> {
      if (!p.exists(property)) return null;
      return p.get(property);
    };
  }

  @NotNull
  private static VcsLogUiProperties createDefaultPropertiesInstance() {
    return new VcsLogUiPropertiesImpl(new VcsLogApplicationSettings()) {
      @NotNull private final State myState = new State();

      @NotNull
      @Override
      public State getState() {
        return myState;
      }

      @Override
      public void addRecentlyFilteredGroup(@NotNull String filterName, @NotNull Collection<String> values) {
        throw new UnsupportedOperationException();
      }

      @NotNull
      @Override
      public List<List<String>> getRecentlyFilteredGroups(@NotNull String filterName) {
        throw new UnsupportedOperationException();
      }

      @Override
      public void loadState(@NotNull Object state) {
        throw new UnsupportedOperationException();
      }
    };
  }

  @NotNull
  @Override
  public String getGroupId() {
    return "vcs.log.ui";
  }
}

@@ -297,24 +297,90 @@
 tFactoryKt;%0A
+import com.intellij.internal.statistic.eventLog.FeatureUsageData;%0A
 import com.i
@@ -1117,16 +1117,107 @@
 til.*;%0A%0A
+import static com.intellij.internal.statistic.beans.MetricEventFactoryKt.newBooleanMetric;%0A
 import s
@@ -3822,12 +3822,47 @@
 hter
-.%22 +
+%22, new FeatureUsageData().addData(%22id%22,
  get
@@ -3884,16 +3884,17 @@
 actory))
+)
 ;%0A      
@@ -4105,76 +4105,94 @@
 add(
-MetricEventFactoryKt.newBooleanMetric(key.getName() + %22Filter%22, true
+newBooleanMetric(%22filter%22, true, new FeatureUsageData().addData(%22name%22, key.getName())
 ));%0A
@@ -4444,24 +4444,116 @@
 _COLUMNS) %7B%0A
+          String columnName = StringUtil.toLowerCase(GraphTableModel.COLUMN_NAMES%5Bcolumn%5D);%0A
           ad
@@ -4669,79 +4669,68 @@
     
-StringUtil.toLowerCase(GraphTableModel.COLUMN_NAMES%5Bcolumn%5D) + %22Column%22
+%22column%22, new FeatureUsageData().addData(%22name%22, columnName)
 );%0A 

move highlighters, filters and columns names or ids to the data