/*
 * Copyright 2000-2009 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.cyclicDependencies.ui;

import com.intellij.CommonBundle;
import com.intellij.analysis.AnalysisScopeBundle;
import com.intellij.cyclicDependencies.CyclicDependenciesBuilder;
import com.intellij.cyclicDependencies.actions.CyclicDependenciesHandler;
import com.intellij.icons.AllIcons;
import com.intellij.ide.actions.ContextHelpAction;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packageDependencies.DependenciesToolWindow;
import com.intellij.packageDependencies.DependencyUISettings;
import com.intellij.packageDependencies.ui.*;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiPackage;
import com.intellij.ui.*;
import com.intellij.ui.content.Content;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.EditSourceOnDoubleClickHandler;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.util.*;
import java.util.List;

/**
 * User: anna
 * Date: Jan 31, 2005
 */
public class CyclicDependenciesPanel extends JPanel implements Disposable, DataProvider {
  private static final HashSet<PsiFile> EMPTY_FILE_SET = new HashSet<PsiFile>(0);

  private final HashMap<PsiPackage, Set<List<PsiPackage>>> myDependencies;
  private final MyTree myLeftTree = new MyTree();
  private final MyTree myRightTree = new MyTree();
  private final DependenciesUsagesPanel myUsagesPanel;

  private final TreeExpansionMonitor myRightTreeExpansionMonitor;
  private final TreeExpansionMonitor myLeftTreeExpansionMonitor;

  private final Project myProject;
  private final CyclicDependenciesBuilder myBuilder;
  private Content myContent;
  private final DependenciesPanel.DependencyPanelSettings mySettings = new DependenciesPanel.DependencyPanelSettings();
  public static final String DEFAULT_PACKAGE_ABBREVIATION = AnalysisScopeBundle.message("dependencies.tree.node.default.package.abbreviation");


  public CyclicDependenciesPanel(Project project, final CyclicDependenciesBuilder builder) {
    super(new BorderLayout());
    myDependencies = builder.getCyclicDependencies();
    myBuilder = builder;
    myProject = project;
    myUsagesPanel =
    new DependenciesUsagesPanel(myProject, Collections.singletonList(builder.getForwardBuilder()));

    Disposer.register(this, myUsagesPanel);

    mySettings.UI_SHOW_MODULES = false; //exist without modules - and doesn't with

    final Splitter treeSplitter = new Splitter();
    Disposer.register(this, new Disposable(){
      public void dispose() {
        treeSplitter.dispose();
      }
    });
    treeSplitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myLeftTree));
    treeSplitter.setSecondComponent(ScrollPaneFactory.createScrollPane(myRightTree));

    final Splitter splitter = new Splitter(true);
    Disposer.register(this, new Disposable() {
      public void dispose() {
        splitter.dispose();
      }
    });
    splitter.setFirstComponent(treeSplitter);
    splitter.setSecondComponent(myUsagesPanel);
    add(splitter, BorderLayout.CENTER);
    add(createToolbar(), BorderLayout.NORTH);

    myRightTreeExpansionMonitor = PackageTreeExpansionMonitor.install(myRightTree, myProject);
    myLeftTreeExpansionMonitor = PackageTreeExpansionMonitor.install(myLeftTree, myProject);

    updateLeftTreeModel();
    updateRightTreeModel();

    myLeftTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent e) {
        updateRightTreeModel();
        myUsagesPanel.setToInitialPosition();
      }
    });

    myRightTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent e) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            Set<PsiFile> searchIn = getSelectedScope(myRightTree);
            final PackageNode selectedPackageNode = getSelectedPackage(myRightTree);
            if (selectedPackageNode == null) {
              return;
            }
            final PackageDependenciesNode nextPackageNode = getNextPackageNode(selectedPackageNode);
            Set<PsiFile> searchFor = new HashSet<PsiFile>();
            Set<PackageNode> packNodes = new HashSet<PackageNode>();
            getPackageNodesHierarchy(selectedPackageNode, packNodes);
            for (PackageNode packageNode : packNodes) {
              searchFor.addAll(myBuilder.getDependentFilesInPackage((PsiPackage)packageNode.getPsiElement(),
                                                                    ((PsiPackage)nextPackageNode.getPsiElement())));
            }
            if (searchIn.isEmpty() || searchFor.isEmpty()) {
              myUsagesPanel.setToInitialPosition();
            }
            else {
              myBuilder.setRootNodeNameInUsageView(AnalysisScopeBundle.message("cyclic.dependencies.usage.view.root.node.text", ((PsiPackage)nextPackageNode.getPsiElement()).getQualifiedName(), ((PsiPackage)selectedPackageNode.getPsiElement()).getQualifiedName()));
              myUsagesPanel.findUsages(searchIn, searchFor);
            }
          }
        });
      }
    });

    initTree(myLeftTree);
    initTree(myRightTree);

    mySettings.UI_FILTER_LEGALS = false;
    mySettings.UI_FLATTEN_PACKAGES = false;

    TreeUtil.selectFirstNode(myLeftTree);
  }

  private static void getPackageNodesHierarchy(PackageNode node, Set<PackageNode> result){
    result.add(node);
    for (int i = 0; i < node.getChildCount(); i++){
      final TreeNode child = node.getChildAt(i);
      if (child instanceof PackageNode){
        final PackageNode packNode = (PackageNode)child;
        if (!result.contains(packNode)){
          getPackageNodesHierarchy(packNode, result);
        }
      }
    }
  }

  @Nullable
  private static PackageDependenciesNode getNextPackageNode(DefaultMutableTreeNode node) {
    DefaultMutableTreeNode child = node;
    while (node != null) {
      if (node instanceof CycleNode) {
        final TreeNode packageDependenciesNode = child.getNextSibling() != null
                                                 ? child.getNextSibling()
                                                 : node.getChildAt(0);
        if (packageDependenciesNode instanceof PackageNode){
          return (PackageNode)packageDependenciesNode;
        }
        if (packageDependenciesNode instanceof ModuleNode){
          return (PackageNode)packageDependenciesNode.getChildAt(0);
        }
      }
      child = node;
      node = (DefaultMutableTreeNode)node.getParent();
    }
    return null;
  }

  private static PackageDependenciesNode hideEmptyMiddlePackages(PackageDependenciesNode node, StringBuffer result){
    if (node.getChildCount() == 0 || node.getChildCount() > 1 || (node.getChildCount() == 1 && node.getChildAt(0) instanceof FileNode)){
      result.append(result.length() != 0 ? "." : "").append(node.toString().equals(DEFAULT_PACKAGE_ABBREVIATION) ? "" : node.toString());//toString()
    } else {
      if (node.getChildCount() == 1){
        PackageDependenciesNode child = (PackageDependenciesNode)node.getChildAt(0);
        if (!(node instanceof PackageNode)){  //e.g. modules node
          node.removeAllChildren();
          child = hideEmptyMiddlePackages(child, result);
          node.add(child);
        } else {
          if (child instanceof PackageNode){
            node.removeAllChildren();
            result.append(result.length() != 0 ? "." : "")
              .append(node.toString().equals(DEFAULT_PACKAGE_ABBREVIATION) ? "" : node.toString());
            node = hideEmptyMiddlePackages(child, result);
            ((PackageNode)node).setPackageName(result.toString());//toString()
          }
        }
      }
    }
    return node;
  }

  private JComponent createToolbar() {
    DefaultActionGroup group = new DefaultActionGroup();
    group.add(new CloseAction());
    group.add(new RerunAction(this));
    group.add(new ShowFilesAction());
    group.add(new HideOutOfCyclePackagesAction());
    group.add(new GroupByScopeTypeAction());
    group.add(new ContextHelpAction("dependency.viewer.tool.window"));

    ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
    return toolbar.getComponent();
  }

  private void rebuild() {
    updateLeftTreeModel();
    updateRightTreeModel();
  }

  private void initTree(final MyTree tree) {
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.setCellRenderer(new MyTreeCellRenderer(tree == myLeftTree));
    tree.setRootVisible(false);
    tree.setShowsRootHandles(true);
    UIUtil.setLineStyleAngled(tree);

    TreeUtil.installActions(tree);
    SmartExpander.installOn(tree);
    EditSourceOnDoubleClickHandler.install(tree);
    new TreeSpeedSearch(tree);

    PopupHandler.installUnknownPopupHandler(tree, createTreePopupActions(), ActionManager.getInstance());


  }

  private void updateLeftTreeModel() {
    final Set<PsiPackage> psiPackages = myDependencies.keySet();
    final Set<PsiFile> psiFiles = new HashSet<PsiFile>();
    for (PsiPackage psiPackage : psiPackages) {
      final Set<List<PsiPackage>> cycles = myDependencies.get(psiPackage);
      if (!mySettings.UI_FILTER_OUT_OF_CYCLE_PACKAGES || cycles != null && !cycles.isEmpty()) {
        psiFiles.addAll(getPackageFiles(psiPackage));
      }
    }
    boolean showFiles = mySettings.UI_SHOW_FILES; //do not show files in the left tree
    mySettings.UI_FLATTEN_PACKAGES = true;
    mySettings.UI_SHOW_FILES = false;
    myLeftTreeExpansionMonitor.freeze();
    myLeftTree.setModel(TreeModelBuilder.createTreeModel(myProject, false, psiFiles, new Marker() {
      public boolean isMarked(VirtualFile file) {
        return false;
      }
    }, mySettings));
    myLeftTreeExpansionMonitor.restore();
    expandFirstLevel(myLeftTree);
    mySettings.UI_SHOW_FILES = showFiles;
    mySettings.UI_FLATTEN_PACKAGES = false;
  }

  private static ActionGroup createTreePopupActions() {
    DefaultActionGroup group = new DefaultActionGroup();
    group.add(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE));
    group.add(ActionManager.getInstance().getAction(IdeActions.GROUP_VERSION_CONTROLS));
    return group;
  }

  private void updateRightTreeModel() {
    PackageDependenciesNode root = new RootNode(myProject);
    final PackageNode packageNode = getSelectedPackage(myLeftTree);
    if (packageNode != null) {
      boolean group = mySettings.UI_GROUP_BY_SCOPE_TYPE;
      mySettings.UI_GROUP_BY_SCOPE_TYPE = false;
      final PsiPackage aPackage = (PsiPackage)packageNode.getPsiElement();
      final Set<List<PsiPackage>> cyclesOfPackages = myDependencies.get(aPackage);
      for (List<PsiPackage> packCycle : cyclesOfPackages) {
        PackageDependenciesNode[] nodes = new PackageDependenciesNode[packCycle.size()];
        for (int i = packCycle.size() - 1; i >= 0; i--) {
          final PsiPackage psiPackage = packCycle.get(i);
          PsiPackage nextPackage = packCycle.get(i == 0 ? packCycle.size() - 1 : i - 1);
          PsiPackage prevPackage = packCycle.get(i == packCycle.size() - 1 ? 0 : i + 1);
          final Set<PsiFile> dependentFilesInPackage = myBuilder.getDependentFilesInPackage(prevPackage, psiPackage, nextPackage);

          final PackageDependenciesNode pack = (PackageDependenciesNode)TreeModelBuilder
            .createTreeModel(myProject, false, dependentFilesInPackage, new Marker() {
              public boolean isMarked(VirtualFile file) {
                return false;
              }
            }, mySettings).getRoot();
          nodes[i] = hideEmptyMiddlePackages((PackageDependenciesNode)pack.getChildAt(0), new StringBuffer());
        }

        PackageDependenciesNode cycleNode = new CycleNode(myProject);
        for (PackageDependenciesNode node : nodes) {
          node.setEquals(true);
          cycleNode.insert(node, 0);
        }
        root.add(cycleNode);
      }
      mySettings.UI_GROUP_BY_SCOPE_TYPE = group;
    }
    myRightTreeExpansionMonitor.freeze();
    myRightTree.setModel(new TreeModel(root, -1, -1));
    myRightTreeExpansionMonitor.restore();
    expandFirstLevel(myRightTree);
  }

  private HashSet<PsiFile> getPackageFiles(final PsiPackage psiPackage) {
    final HashSet<PsiFile> psiFiles = new HashSet<PsiFile>();
    final PsiClass[] classes = psiPackage.getClasses();
    for (PsiClass aClass : classes) {
      final PsiFile file = aClass.getContainingFile();
      if (myBuilder.getScope().contains(file)) {
        psiFiles.add(file);
      }
    }
    return psiFiles;
  }

  private static void expandFirstLevel(Tree tree) {
    PackageDependenciesNode root = (PackageDependenciesNode)tree.getModel().getRoot();
    int count = root.getChildCount();
    if (count < 10) {
      for (int i = 0; i < count; i++) {
        PackageDependenciesNode child = (PackageDependenciesNode)root.getChildAt(i);
        expandNodeIfNotTooWide(tree, child);
      }
    }
  }

  private static void expandNodeIfNotTooWide(Tree tree, PackageDependenciesNode node) {
    int count = node.getChildCount();
    if (count > 5) return;
    tree.expandPath(new TreePath(node.getPath()));
  }

  @Nullable
  private static PackageNode getSelectedPackage(final Tree tree) {
    TreePath[] paths = tree.getSelectionPaths();
    if (paths == null || paths.length != 1) return null;
    PackageDependenciesNode node = (PackageDependenciesNode)paths[0].getLastPathComponent();
    if (node.isRoot()) return null;
    if (node instanceof PackageNode) {
      return (PackageNode)node;
    }
    if (node instanceof FileNode) {
      return (PackageNode)node.getParent();
    }
    if (node instanceof ModuleNode){
      return (PackageNode)node.getChildAt(0);
    }
    return null;
  }

  private static Set<PsiFile> getSelectedScope(final Tree tree) {
    TreePath[] paths = tree.getSelectionPaths();
    if (paths == null || paths.length != 1) return EMPTY_FILE_SET;
    PackageDependenciesNode node = (PackageDependenciesNode)paths[0].getLastPathComponent();
    if (node.isRoot()) return EMPTY_FILE_SET;
    Set<PsiFile> result = new HashSet<PsiFile>();
    node.fillFiles(result, true);
    return result;
  }

  public void setContent(Content content) {
    myContent = content;
  }

  public void dispose() {
    TreeModelBuilder.clearCaches(myProject);
  }

  @Nullable
  @NonNls
  public Object getData(@NonNls String dataId) {
    if (PlatformDataKeys.HELP_ID.is(dataId)) {
      return "dependency.viewer.tool.window";
    }
    return null;
  }

  private class MyTreeCellRenderer extends ColoredTreeCellRenderer {
    private final boolean myLeftTree;

    public MyTreeCellRenderer(boolean isLeftTree) {
      myLeftTree = isLeftTree;
    }

    public void customizeCellRenderer(JTree tree,
                                      Object value,
                                      boolean selected,
                                      boolean expanded,
                                      boolean leaf,
                                      int row,
                                      boolean hasFocus) {
      SimpleTextAttributes attributes = SimpleTextAttributes.REGULAR_ATTRIBUTES;

      final PackageDependenciesNode node;
      if (value instanceof PackageDependenciesNode){
        node = (PackageDependenciesNode)value;
        if (myLeftTree && !mySettings.UI_FILTER_OUT_OF_CYCLE_PACKAGES) {
          final PsiElement element = node.getPsiElement();
          if (element instanceof PsiPackage) {
            final PsiPackage aPackage = (PsiPackage)element;
            final Set<List<PsiPackage>> packageDependencies = myDependencies.get(aPackage);
            if (packageDependencies != null && !packageDependencies.isEmpty()) {
                attributes = SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
            }
          }
        }
      } else {
        node = (PackageDependenciesNode)((DefaultMutableTreeNode)value).getUserObject(); //cycle node children
      }
      append(node.toString(), attributes);
      setIcon(node.getIcon());
    }
  }

  private final class CloseAction extends AnAction implements DumbAware {
    public CloseAction() {
      super(CommonBundle.message("action.close"), AnalysisScopeBundle.message("action.close.dependency.description"),
            AllIcons.Actions.Cancel);
    }

    public void actionPerformed(AnActionEvent e) {
      Disposer.dispose(myUsagesPanel);
      DependenciesToolWindow.getInstance(myProject).closeContent(myContent);
      mySettings.copyToApplicationDependencySettings();
    }
  }

  private final class ShowFilesAction extends ToggleAction {
    ShowFilesAction() {
      super(AnalysisScopeBundle.message("action.show.files"), AnalysisScopeBundle.message("action.show.files.description"),
            AllIcons.FileTypes.Java);
    }

    public boolean isSelected(AnActionEvent event) {
      return mySettings.UI_SHOW_FILES;
    }

    public void setSelected(AnActionEvent event, boolean flag) {
      DependencyUISettings.getInstance().UI_SHOW_FILES = flag;
      mySettings.UI_SHOW_FILES = flag;
      rebuild();
    }
  }

  private final class HideOutOfCyclePackagesAction extends ToggleAction {
    @NonNls public static final String SHOW_PACKAGES_FROM_CYCLES_ONLY = "Hide packages without cyclic dependencies";

    HideOutOfCyclePackagesAction() {
      super(SHOW_PACKAGES_FROM_CYCLES_ONLY, SHOW_PACKAGES_FROM_CYCLES_ONLY, AllIcons.General.Filter);
    }

    @Override
    public boolean isSelected(AnActionEvent e) {
      return mySettings.UI_FILTER_OUT_OF_CYCLE_PACKAGES;
    }

    @Override
    public void setSelected(AnActionEvent e, boolean state) {
      DependencyUISettings.getInstance().UI_FILTER_OUT_OF_CYCLE_PACKAGES = state;
      mySettings.UI_FILTER_OUT_OF_CYCLE_PACKAGES = state;
      rebuild();
    }
  }

  private final class GroupByScopeTypeAction extends ToggleAction {
    GroupByScopeTypeAction() {
      super(AnalysisScopeBundle.message("action.group.by.scope.type"), AnalysisScopeBundle.message("action.group.by.scope.type.description"),
            AllIcons.Actions.GroupByTestProduction);
    }

    public boolean isSelected(AnActionEvent event) {
      return mySettings.UI_GROUP_BY_SCOPE_TYPE;
    }

    public void setSelected(AnActionEvent event, boolean flag) {
      DependencyUISettings.getInstance().UI_GROUP_BY_SCOPE_TYPE = flag;
      mySettings.UI_GROUP_BY_SCOPE_TYPE = flag;
      rebuild();
    }
  }

  private class RerunAction extends AnAction {
    public RerunAction(JComponent comp) {
      super(CommonBundle.message("action.rerun"), AnalysisScopeBundle.message("action.rerun.dependency"), AllIcons.Actions.Rerun);
      registerCustomShortcutSet(CommonShortcuts.getRerun(), comp);
    }

    public void update(AnActionEvent e) {
      e.getPresentation().setEnabled(myBuilder.getScope().isValid());
    }

    public void actionPerformed(AnActionEvent e) {
      DependenciesToolWindow.getInstance(myProject).closeContent(myContent);
      mySettings.copyToApplicationDependencySettings();
      SwingUtilities.invokeLater(new Runnable() {
        public void run() {
          new CyclicDependenciesHandler(myProject, myBuilder.getScope()).analyze();
        }
      });
    }
  }

  private static class MyTree extends Tree implements DataProvider {
    public Object getData(String dataId) {
      PackageDependenciesNode node = getSelectedNode();
      if (CommonDataKeys.NAVIGATABLE.is(dataId)) {
        return node;
      }
      return null;
    }

    @Nullable
    public PackageDependenciesNode getSelectedNode() {
      TreePath[] paths = getSelectionPaths();
      if (paths == null || paths.length != 1) return null;
      final Object lastPathComponent = paths[0].getLastPathComponent();
      if (lastPathComponent instanceof PackageDependenciesNode) {
        return (PackageDependenciesNode)lastPathComponent;
      } else {
        return (PackageDependenciesNode)((DefaultMutableTreeNode)lastPathComponent).getUserObject();
      }
    }
  }
}
