// 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.jarRepository.settings;

import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.panel.ComponentPanelBuilder;
import com.intellij.ui.CheckboxTree;
import com.intellij.ui.CheckboxTreeBase;
import com.intellij.ui.CheckedTreeNode;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.ui.UI;
import com.intellij.util.ui.tree.TreeUtil;
import org.eclipse.aether.artifact.Artifact;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.aether.ArtifactDependencyNode;

import javax.swing.*;
import java.util.*;

class DependencyExclusionEditor {
  private final CheckboxTree myDependenciesTree;
  private final CheckedTreeNode myRootNode;
  private final JPanel myMainPanel;

  public DependencyExclusionEditor(ArtifactDependencyNode root, JPanel parentComponent) {
    myMainPanel = parentComponent;
    myRootNode = createDependencyTreeNode(root);
    CheckboxTreeBase.CheckPolicy policy = new CheckboxTreeBase.CheckPolicy(false, true, true, false);
    myDependenciesTree = new CheckboxTree(new CheckboxTree.CheckboxTreeCellRenderer() {
      {
        myIgnoreInheritance = true;
      }

      @Override
      public void customizeRenderer(JTree tree,
                                    Object value,
                                    boolean selected,
                                    boolean expanded,
                                    boolean leaf,
                                    int row,
                                    boolean hasFocus) {
        if (!(value instanceof CheckedTreeNode)) return;

        Object userObject = ((CheckedTreeNode)value).getUserObject();
        if (!(userObject instanceof Artifact)) return;

        Artifact artifact = (Artifact)userObject;
        getTextRenderer().append(artifact.getGroupId() + ":" + artifact.getArtifactId(), SimpleTextAttributes.REGULAR_ATTRIBUTES, true);
        getTextRenderer().append(":" + artifact.getVersion(), SimpleTextAttributes.GRAYED_ATTRIBUTES, true);
      }
    }, myRootNode, policy);
    myDependenciesTree.setRootVisible(false);
  }

  @Nullable
  public Set<String> selectExcludedDependencies(List<String> excludedDependencies) {
    uncheckExcludedNodes(myRootNode, new HashSet<>(excludedDependencies), false);
    TreeUtil.expandAll(myDependenciesTree);
    ComponentPanelBuilder panelBuilder =
      UI.PanelFactory.panel(new JBScrollPane(myDependenciesTree))
                     .withLabel("Specify which transitive dependencies should be included into the library.")
                     .moveLabelOnTop();
    DialogBuilder dialogBuilder =
      new DialogBuilder(myMainPanel)
        .title("Configure Transitive Dependencies")
        .centerPanel(panelBuilder.createPanel());
    dialogBuilder.setPreferredFocusComponent(myDependenciesTree);

    if (dialogBuilder.showAndGet()) {
      return collectUncheckedNodes(myRootNode, new LinkedHashSet<>());
    }
    return null;
  }

  private static void uncheckExcludedNodes(CheckedTreeNode node, Set<String> excluded, boolean parentIsExcluded) {
    boolean isExcluded = parentIsExcluded || excluded.contains(getGroupAndArtifactId(node));
    node.setChecked(!isExcluded);
    Enumeration children = node.children();
    while (children.hasMoreElements()) {
      Object child = children.nextElement();
      uncheckExcludedNodes((CheckedTreeNode)child, excluded, isExcluded);
    }
  }

  private static Set<String> collectUncheckedNodes(CheckedTreeNode node, Set<String> result) {
    if (node.isChecked()) {
      Enumeration children = node.children();
      while (children.hasMoreElements()) {
        Object child = children.nextElement();
        collectUncheckedNodes((CheckedTreeNode)child, result);
      }
    }
    else {
      result.add(getGroupAndArtifactId(node));
    }
    return result;
  }

  @NotNull
  private static String getGroupAndArtifactId(CheckedTreeNode node) {
    Artifact artifact = (Artifact)node.getUserObject();
    return artifact.getGroupId() + ":" + artifact.getArtifactId();
  }

  @NotNull
  private static CheckedTreeNode createDependencyTreeNode(ArtifactDependencyNode node) {
    CheckedTreeNode treeNode = new CheckedTreeNode(node.getArtifact());
    for (ArtifactDependencyNode dependency : node.getDependencies()) {
      treeNode.add(createDependencyTreeNode(dependency));
    }
    return treeNode;
  }
}

@@ -230,68 +230,8 @@
 er;%0A
-import com.intellij.openapi.ui.panel.ComponentPanelBuilder;%0A
 impo
@@ -263,16 +263,16 @@
 oxTree;%0A
+
 import c
@@ -389,16 +389,59 @@
 ibutes;%0A
+import com.intellij.ui.components.JBLabel;%0A
 import c
@@ -508,16 +508,18 @@
 util.ui.
+JB
 UI;%0Aimpo
@@ -546,17 +546,97 @@
 .ui.
-tree.Tree
+UIUtil;%0Aimport com.intellij.util.ui.tree.TreeUtil;%0Aimport com.intellij.xml.util.XmlString
 Util
@@ -2626,42 +2626,20 @@
     
-ComponentPanelBuilder panelBuilder
+JPanel panel
  =%0A 
@@ -2647,16 +2647,18 @@
     
+JB
 UI.Panel
 Fact
@@ -2657,21 +2657,75 @@
 anel
-Factory.panel
+s.simplePanel(0, UIUtil.DEFAULT_VGAP)%0A                 .addToCenter
 (new
@@ -2780,21 +2780,53 @@
     
-    .withLabe
+.addToTop(new JBLabel(XmlStringUtil.wrapInHtm
 l(%22S
@@ -2904,46 +2904,9 @@
 y.%22)
-%0A                     .moveLabelOnTop(
+)
 );%0A 
@@ -3027,16 +3027,16 @@
 ncies%22)%0A
+
         
@@ -3057,29 +3057,8 @@
 anel
-Builder.createPanel()
 );%0A 

fix resizing of 'Configure Transitive Dependencies' dialog (IDEA-193045)