/*
 * 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.openapi.roots.ui.configuration.dependencyAnalysis;

import com.intellij.ProjectTopics;
import com.intellij.icons.AllIcons;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.roots.ModuleRootAdapter;
import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ModuleSourceOrderEntry;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.ui.CellAppearanceEx;
import com.intellij.openapi.roots.ui.OrderEntryAppearanceService;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.ui.MasterDetailsComponent;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.*;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.PathUtil;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * The classpath details component
 */
public class AnalyzeDependenciesComponent extends MasterDetailsComponent {
  /**
   * Data key for order path element
   */
  public static DataKey<ModuleDependenciesAnalyzer.OrderPathElement> ORDER_PATH_ELEMENT_KEY = DataKey.create("ORDER_PATH_ELEMENT");
  /**
   * The module being analyzed
   */
  private final Module myModule;
  /**
   * The settings for UI mode
   */
  private final AnalyzeDependenciesSettings mySettings;
  /**
   * The cached analyzed classpaths for this module
   */
  private final HashMap<Pair<ClasspathType, Boolean>, ModuleDependenciesAnalyzer> myClasspaths =
    new HashMap<Pair<ClasspathType, Boolean>, ModuleDependenciesAnalyzer>();

  /**
   * The message bus connection to use
   */
  private MessageBusConnection myMessageBusConnection;

  /**
   * The constructor
   *
   * @param module the module to analyze
   */
  public AnalyzeDependenciesComponent(Module module) {
    myModule = module;
    mySettings = AnalyzeDependenciesSettings.getInstance(myModule.getProject());
    initTree();
    init();
    getSplitter().setProportion(0.3f);
    myMessageBusConnection = myModule.getProject().getMessageBus().connect();
    myMessageBusConnection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
      @Override
      public void rootsChanged(ModuleRootEvent event) {
        myClasspaths.clear();
        updateTree();
      }
    });
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void disposeUIResources() {
    if (myMessageBusConnection != null) {
      myMessageBusConnection.disconnect();
    }
  }

  /**
   * Initialize components
   */
  private void init() {
    myTree.setCellRenderer(new ColoredTreeCellRenderer() {
      @Override
      public void customizeCellRenderer(JTree tree,
                                        Object value,
                                        boolean selected,
                                        boolean expanded,
                                        boolean leaf,
                                        int row,
                                        boolean hasFocus) {
        //if(getBackground() == null) {
        //  setBackground(UIUtil.getTreeTextBackground());
        //}
        if (value instanceof MyNode && !(value instanceof MyRootNode)) {
          final MyNode node = (MyNode)value;
          PathNode<?> n = (PathNode<?>)node.getUserObject();
          CellAppearanceEx a = n.getAppearance(selected, node.isDisplayInBold());
          a.customize(this);
        }
      }
    });
    myTree.setShowsRootHandles(false);
    myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    reloadTree();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected ArrayList<AnAction> createActions(boolean fromPopup) {
    if (!fromPopup) {
      ArrayList<AnAction> rc = new ArrayList<AnAction>();
      rc.add(new ClasspathTypeAction());
      rc.add(new SdkFilterAction());
      rc.add(new UrlModeAction());
      return rc;
    }
    else {
      return super.createActions(fromPopup);
    }
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected void processRemovedItems() {
    // no remove action so far
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected boolean wasObjectStored(Object editableObject) {
    // no modifications so far
    return false;
  }

  /**
   * {@inheritDoc}
   */
  @Nls
  @Override
  public String getDisplayName() {
    return "Classpath Details";
  }

  /**
   * Reload tree
   */
  public void reloadTree() {
    myRoot.removeAllChildren();
    ModuleDependenciesAnalyzer a = getAnalyzer();
    if (mySettings.isUrlMode()) {
      for (ModuleDependenciesAnalyzer.UrlExplanation urlExplanation : a.getUrls()) {
        myRoot.add(new MyNode(new UrlNode(urlExplanation)));
      }
    }
    else {
      for (ModuleDependenciesAnalyzer.OrderEntryExplanation explanation : a.getOrderEntries()) {
        myRoot.add(new MyNode(new OrderEntryNode(explanation)));
      }
    }
    ((DefaultTreeModel)myTree.getModel()).reload(myRoot);
  }

  /**
   * @return the analyzer for the current settings
   */
  public ModuleDependenciesAnalyzer getAnalyzer() {
    final Pair<ClasspathType, Boolean> key = Pair.create(getClasspathType(), mySettings.isSdkIncluded());
    ModuleDependenciesAnalyzer a = myClasspaths.get(key);
    if (a == null) {
      a = new ModuleDependenciesAnalyzer(myModule, !mySettings.isTest(), !mySettings.isRuntime(), mySettings.isSdkIncluded());
      myClasspaths.put(key, a);
    }
    return a;
  }

  /**
   * @return the current classpath type from settings
   */
  private ClasspathType getClasspathType() {
    return mySettings.isRuntime() ?
           (mySettings.isTest() ? ClasspathType.TEST_RUNTIME : ClasspathType.PRODUCTION_RUNTIME) :
           (mySettings.isTest() ? ClasspathType.TEST_COMPILE : ClasspathType.PRODUCTION_COMPILE);
  }


  /**
   * Schedule updating the tree
   */
  void updateTree() {
    // TODO make loading in the background if there will be significant delays on big projects
    reloadTree();
  }

  /**
   * The action that allows navigating to the path element
   */
  static class NavigateAction extends DumbAwareAction {

    /**
     * The constructor
     */
    NavigateAction() {
      super("Navigate to ...", "Navigate to place where path element is defined", null);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void actionPerformed(AnActionEvent e) {
      final Module module = e.getData(LangDataKeys.MODULE);
      if (module == null) {
        return;
      }
      final ModuleDependenciesAnalyzer.OrderPathElement element = e.getData(ORDER_PATH_ELEMENT_KEY);
      if (element != null && element instanceof ModuleDependenciesAnalyzer.OrderEntryPathElement) {
        final ModuleDependenciesAnalyzer.OrderEntryPathElement o = (ModuleDependenciesAnalyzer.OrderEntryPathElement)element;
        final OrderEntry entry = o.entry();
        final Module m = entry.getOwnerModule();
        ProjectStructureConfigurable.getInstance(module.getProject()).selectOrderEntry(m, entry);
      }
    }
  }

  /**
   * Base class for nodes
   *
   * @param <T> the actual explanation type
   */
  abstract class PathNode<T extends ModuleDependenciesAnalyzer.Explanation> extends NamedConfigurable<T> implements DataProvider {
    /**
     * The cut off length, after which URLs are not shown (only suffix)
     */
    public static final int CUTOFF_LENGTH = 80;

    /**
     * The explanation
     */
    protected final T myExplanation;
    /**
     * The tree with explanation
     */
    private Tree myExplanationTree;

    /**
     * The constructor
     *
     * @param explanation the wrapped explanation
     */
    public PathNode(T explanation) {
      myExplanation = explanation;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public T getEditableObject() {
      return myExplanation;
    }

    /**
     * @return a created tree component (to be used as
     */
    private JComponent createTreeComponent() {
      myExplanationTree = new Tree(new DefaultTreeModel(buildTree()));
      myExplanationTree.setRootVisible(false);
      myExplanationTree.setCellRenderer(new ExplanationTreeRenderer());
      DataManager.registerDataProvider(myExplanationTree, this);
      TreeUtil.expandAll(myExplanationTree);
      final NavigateAction navigateAction = new NavigateAction();
      navigateAction.registerCustomShortcutSet(new CustomShortcutSet(CommonShortcuts.DOUBLE_CLICK_1.getShortcuts()[0]), myExplanationTree);
      DefaultActionGroup group = new DefaultActionGroup();
      group.addAction(navigateAction);
      PopupHandler.installUnknownPopupHandler(myExplanationTree, group, ActionManager.getInstance());
      return new JBScrollPane(myExplanationTree);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object getData(@NonNls String dataId) {
      if (CommonDataKeys.PROJECT.is(dataId)) {
        return myModule.getProject();
      }
      if (LangDataKeys.MODULE.is(dataId)) {
        return myModule;
      }
      TreePath selectionPath = myExplanationTree.getSelectionPath();
      DefaultMutableTreeNode node = selectionPath == null ? null : (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
      Object o = node == null ? null : node.getUserObject();
      if (o instanceof ModuleDependenciesAnalyzer.OrderPathElement) {
        if (ORDER_PATH_ELEMENT_KEY.is(dataId)) {
          return o;
        }
      }
      return null;
    }

    /**
     * Build tree for the dependencies
     *
     * @return a tree model
     */
    private DefaultMutableTreeNode buildTree() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("ROOT");
      for (ModuleDependenciesAnalyzer.OrderPath orderPath : myExplanation.paths()) {
        addDependencyPath(root, orderPath, 0);
      }
      return root;
    }

    /**
     * Add the dependency path
     *
     * @param parent    the parent to which path is added
     * @param orderPath the order entry path
     * @param i         the position in the path
     */
    private void addDependencyPath(DefaultMutableTreeNode parent,
                                   ModuleDependenciesAnalyzer.OrderPath orderPath,
                                   int i) {
      if (i >= orderPath.entries().size()) {
        return;
      }
      ModuleDependenciesAnalyzer.OrderPathElement e = orderPath.entries().get(i);
      int sz = parent.getChildCount();
      DefaultMutableTreeNode n;
      if (sz == 0) {
        n = null;
      }
      else {
        n = (DefaultMutableTreeNode)parent.getChildAt(sz - 1);
        if (!n.getUserObject().equals(e)) {
          n = null;
        }
      }
      if (n == null) {
        n = new DefaultMutableTreeNode(e);
        parent.add(n);
      }
      addDependencyPath(n, orderPath, i + 1);
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void setDisplayName(String name) {
      // do nothing
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JComponent createOptionsPanel() {
      final JComponent tree = createTreeComponent();
      JPanel panel = new JPanel(new BorderLayout());
      JLabel paths = new JLabel("Available Through Paths:");
      paths.setDisplayedMnemonic('P');
      paths.setLabelFor(tree);
      panel.add(paths, BorderLayout.NORTH);
      panel.add(tree, BorderLayout.CENTER);
      return panel;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void disposeUIResources() {
      //Do nothing
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getHelpTopic() {
      return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isModified() {
      return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void apply() throws ConfigurationException {
      // Do nothing
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void reset() {
      //Do nothing
    }

    /**
     * Get appearance for rendering in master list
     *
     * @param selected true if selected
     * @param bold     true if bold
     * @return the result appearance
     */
    public abstract CellAppearanceEx getAppearance(boolean selected, boolean bold);

    /**
     * @retrun the string cut so it would fit the banner (the prefix is dropped)
     */
    protected String suffixForBanner(String p) {
      if (p.length() > CUTOFF_LENGTH) {
        p = "..." + p.substring(p.length() - CUTOFF_LENGTH);
      }
      return p;
    }

    /**
     * @retrun the string cut so it would fit the banner (the suffix is dropped)
     */
    protected String prefixForBanner(String p) {
      if (p.length() > CUTOFF_LENGTH) {
        p = p.substring(0, CUTOFF_LENGTH) + "...";
      }
      return p;
    }
  }

  /**
   * Cell renderer for explanation tree
   */
  static class ExplanationTreeRenderer extends ColoredTreeCellRenderer {

    @Override
    public void customizeCellRenderer(JTree tree,
                                      Object value,
                                      boolean selected,
                                      boolean expanded,
                                      boolean leaf,
                                      int row,
                                      boolean hasFocus) {
      DefaultMutableTreeNode n = (DefaultMutableTreeNode)value;
      final Object userObject = n.getUserObject();
      if (!(userObject instanceof ModuleDependenciesAnalyzer.OrderPathElement)) {
        return;
      }
      ModuleDependenciesAnalyzer.OrderPathElement e = (ModuleDependenciesAnalyzer.OrderPathElement)userObject;
      final CellAppearanceEx appearance = e.getAppearance(selected);
      appearance.customize(this);
    }
  }

  /**
   * The entry node in URL node
   */
  class UrlNode extends PathNode<ModuleDependenciesAnalyzer.UrlExplanation> {

    /**
     * The constructor
     *
     * @param url the wrapped explanation
     */
    public UrlNode(ModuleDependenciesAnalyzer.UrlExplanation url) {
      super(url);
      setNameFieldShown(false);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public CellAppearanceEx getAppearance(boolean selected, final boolean isBold) {
      return new CellAppearanceEx() {
        @Override
        public void customize(@NotNull SimpleColoredComponent component) {
          component.setIcon(getIcon());
          final Font font = UIUtil.getTreeFont();
          if (isBold) {
            component.setFont(font.deriveFont(Font.BOLD));
          }
          else {
            component.setFont(font.deriveFont(Font.PLAIN));
          }
          final String p = PathUtil.toPresentableUrl(getEditableObject().url());
          component.append(PathUtil.getFileName(p),
                           isBold ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
          component.append(" (" + PathUtil.getParentPath(p) + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
        }

        @Override
        public void customize(@NotNull final HtmlListCellRenderer renderer) {
          throw new UnsupportedOperationException("Rendering in combo box not supported yet.");
        }

        @NotNull
        @Override
        public String getText() {
          return getDisplayName();
        }
      };
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBannerSlogan() {
      final VirtualFile f = myExplanation.getLocalFile();
      String p = f == null ? myExplanation.url() : f.getPath();
      p = suffixForBanner(p);
      return p;
    }

    /**
     * {@inheritDoc}
     */
    private Icon getIcon() {
      return myExplanation.getIcon();
    }

    /**
     * {@inheritDoc}
     */
    @Nls
    @Override
    public String getDisplayName() {
      return myExplanation.url();
    }
  }

  /**
   * The wrapper for order entries
   */
  class OrderEntryNode extends PathNode<ModuleDependenciesAnalyzer.OrderEntryExplanation> {

    /**
     * The constructor
     *
     * @param orderEntryExplanation the explanation to wrap
     */
    public OrderEntryNode(ModuleDependenciesAnalyzer.OrderEntryExplanation orderEntryExplanation) {
      super(orderEntryExplanation);
      setNameFieldShown(false);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public CellAppearanceEx getAppearance(boolean selected, final boolean isBold) {
      if (myExplanation.entry() instanceof ModuleSourceOrderEntry) {
        ModuleSourceOrderEntry e = (ModuleSourceOrderEntry)myExplanation.entry();
        if (e.getOwnerModule() == myModule) {
          return new CellAppearanceEx() {
            @Override
            public void customize(@NotNull SimpleColoredComponent component) {
              component.setIcon(ModuleType.get(myModule).getIcon());
              component.append("<This Module>", SimpleTextAttributes.SYNTHETIC_ATTRIBUTES);
            }

            @Override
            public void customize(@NotNull final HtmlListCellRenderer renderer) {
              throw new UnsupportedOperationException("Rendering in combo box not supported yet.");
            }

            @NotNull
            @Override
            public String getText() {
              return "<This Module>";
            }
          };
        }
        else {
          return OrderEntryAppearanceService.getInstance().forModule(e.getOwnerModule());
        }
      }
      return OrderEntryAppearanceService.getInstance().forOrderEntry(myModule.getProject(), myExplanation.entry(), selected);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBannerSlogan() {
      if (myExplanation.entry() instanceof ModuleSourceOrderEntry) {
        ModuleSourceOrderEntry e = (ModuleSourceOrderEntry)myExplanation.entry();
        return prefixForBanner("Module " + e.getOwnerModule().getName());
      }
      else {
        final String p = myExplanation.entry().getPresentableName() + " in module " + myExplanation.entry().getOwnerModule().getName();
        return suffixForBanner(p);
      }
    }

    /**
     * {@inheritDoc}
     */
    @Nls
    @Override
    public String getDisplayName() {
      return myExplanation.entry().getPresentableName();
    }
  }

  /**
   * The action that allows including and excluding SDK entries from analysis
   */
  private class SdkFilterAction extends ToggleAction {

    /**
     * The constructor
     */
    public SdkFilterAction() {
      super("Include SDK", "If selected, the SDK classes are included", AllIcons.General.Jdk);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isSelected(AnActionEvent e) {
      return mySettings.isSdkIncluded();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setSelected(AnActionEvent e, boolean state) {
      mySettings.setIncludeSdk(state);
      updateTree();
    }
  }

  /**
   * The action that allows switching class path between URL and order entry modes
   */
  private class UrlModeAction extends ToggleAction {
    /**
     * The constructor
     */
    public UrlModeAction() {
      super("Use URL mode", "If selected, the URLs are displayed, otherwise order entries", AllIcons.Nodes.PpFile);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isSelected(AnActionEvent e) {
      return mySettings.isUrlMode();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setSelected(AnActionEvent e, boolean state) {
      mySettings.setUrlMode(state);
      updateTree();
    }
  }

  /**
   * Classpath type action for the analyze classpath
   */
  private class ClasspathTypeAction extends ComboBoxAction {
    /**
     * The filter action group
     */
    DefaultActionGroup myItems;

    /**
     * {@inheritDoc}
     */
    @NotNull
    @Override
    protected DefaultActionGroup createPopupActionGroup(JComponent button) {
      if (myItems == null) {
        myItems = new DefaultActionGroup(null, true);
        for (final ClasspathType classpathType : ClasspathType.values()) {
          myItems.addAction(new DumbAwareAction(classpathType.getDescription()) {
            @Override
            public void actionPerformed(AnActionEvent e) {
              mySettings.setRuntime(classpathType.isRuntime());
              mySettings.setTest(classpathType.isTest());
              updateTree();
            }
          });
        }
      }
      return myItems;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void update(AnActionEvent e) {
      final Presentation presentation = e.getPresentation();
      updateText(presentation);
    }

    /**
     * Update the text for the combobox
     *
     * @param presentation the presentaiton to update
     */
    private void updateText(Presentation presentation) {
      final ClasspathType classpathType = getClasspathType();
      String t = classpathType.getDescription();
      presentation.setText(t);
    }
  }

  /**
   * The enumeration type that represents classpath entry filter
   */
  private static enum ClasspathType {
    /**
     * The production compile mode
     */
    PRODUCTION_COMPILE(false, false, "Production Compile"),
    /**
     * The production runtime mode
     */
    PRODUCTION_RUNTIME(false, true, "Production Runtime"),
    /**
     * The test runtime mode
     */
    TEST_RUNTIME(true, true, "Test Runtime"),
    /**
     * The test compile mode
     */
    TEST_COMPILE(true, false, "Test Compile");

    /**
     * true, if test mode
     */
    final private boolean myIsTest;
    /**
     * true, if runtime mode
     */
    final private boolean myIsRuntime;
    /**
     * The description text
     */
    final private String myDescription;

    /**
     * The constructor
     *
     * @param isTest      true if the test mode
     * @param isRuntime   true if the runtime ode
     * @param description the description text
     */
    ClasspathType(boolean isTest, boolean isRuntime, String description) {
      myIsTest = isTest;
      myIsRuntime = isRuntime;
      myDescription = description;
    }

    /**
     * @return true if the test mode
     */
    public boolean isTest() {
      return myIsTest;
    }

    /**
     * @return true if the runtime mode
     */
    public boolean isRuntime() {
      return myIsRuntime;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
      return myDescription;
    }

    /**
     * @return the description for the entry
     */
    public String getDescription() {
      return myDescription;
    }
  }
}
