/*
 * 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 git4idea.update;

import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.CommonShortcuts;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.PanelWithActionsAndCloseButton;
import com.intellij.openapi.vcs.VcsDataKeys;
import com.intellij.openapi.vcs.annotate.ShowAllAffectedGenericAction;
import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ContentsUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import com.intellij.vcsUtil.VcsUtil;
import git4idea.GitFileRevision;
import git4idea.rebase.GitRebaseUtils;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

/**
 * The panel that displays list of skipped commits during update
 */
public class GitSkippedCommits extends PanelWithActionsAndCloseButton {
  /**
   * The current project
   */
  private final Project myProject;
  /**
   * Tree control
   */
  private final Tree myTree;
  /**
   * Get center component
   */
  private JBScrollPane myCenterComponent;

  /**
   * The constructor
   *
   * @param contentManager content manager
   * @param project        the context project
   * @param skippedCommits the map with skipped commits
   */
  public GitSkippedCommits(@NotNull ContentManager contentManager,
                           Project project, SortedMap<VirtualFile, List<GitRebaseUtils.CommitInfo>> skippedCommits) {
    super(contentManager, null);
    myProject = project;
    DefaultMutableTreeNode treeRoot = new DefaultMutableTreeNode("ROOT", true);
    for (Map.Entry<VirtualFile, List<GitRebaseUtils.CommitInfo>> e : skippedCommits.entrySet()) {
      DefaultMutableTreeNode vcsRoot = new DefaultMutableTreeNode(new VcsRoot(e.getKey()));
      int missed = 0;
      for (GitRebaseUtils.CommitInfo c : e.getValue()) {
        if (c != null) {
          vcsRoot.add(new DefaultMutableTreeNode(new Commit(e.getKey(), c)));
        }
        else {
          missed++;
        }
      }
      treeRoot.add(vcsRoot);
      if (missed > 0) {
        vcsRoot.add(new DefaultMutableTreeNode("The " + missed + " commit(s) were not parsed due to unsupported rebase directory format"));
      }
    }
    myTree = new Tree(treeRoot);
    myTree.setCellRenderer(createTreeCellRenderer());
    myTree.setRootVisible(false);
    myCenterComponent = new JBScrollPane(myTree);
    init();
    TreeUtil.expandAll(myTree);
  }

  /**
   * @return new cell renderer
   */
  private DefaultTreeCellRenderer createTreeCellRenderer() {
    return new DefaultTreeCellRenderer() {
      @Override
      public Component getTreeCellRendererComponent(JTree tree,
                                                    Object value,
                                                    boolean sel,
                                                    boolean expanded,
                                                    boolean leaf,
                                                    int row,
                                                    boolean hasFocus) {
        Component r = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row,
                                                         hasFocus);
        Object o = value instanceof DefaultMutableTreeNode ? ((DefaultMutableTreeNode)value).getUserObject() : null;
        if (o instanceof VcsRoot) {
          r.setFont(tree.getFont().deriveFont(Font.BOLD));
          r.setForeground(sel ? textSelectionColor : textNonSelectionColor);
        }
        else if (o instanceof String) {
          r.setForeground(sel ? textSelectionColor : JBColor.RED);
          r.setFont(tree.getFont());
        }
        else {
          r.setForeground(sel ? textSelectionColor : textNonSelectionColor);
          r.setFont(tree.getFont());
        }
        return r;
      }
    };
  }

  @Override
  protected JComponent createCenterPanel() {
    return myCenterComponent;
  }

  @Override
  protected void addActionsTo(DefaultActionGroup group) {
    super.addActionsTo(group);
    ShowAllAffectedGenericAction showCommit = ShowAllAffectedGenericAction.getInstance();
    showCommit.registerCustomShortcutSet(new CustomShortcutSet(
      CommonShortcuts.DOUBLE_CLICK_1.getShortcuts()[0]), myTree);
    group.addAction(showCommit);

  }

  @Override
  public Object getData(String dataId) {
    if (CommonDataKeys.PROJECT.is(dataId)) {
      return myProject;
    }
    TreePath selectionPath = myTree.getSelectionPath();
    DefaultMutableTreeNode node = selectionPath == null ? null : (DefaultMutableTreeNode)selectionPath.getLastPathComponent();
    Object o = node == null ? null : node.getUserObject();
    if (o instanceof Commit) {
      Commit c = (Commit)o;
      if (VcsDataKeys.VCS_VIRTUAL_FILE.is(dataId)) {
        return c.root;
      }
      if (VcsDataKeys.VCS_FILE_REVISION.is(dataId)) {
        return new GitFileRevision(myProject, VcsUtil.getFilePath(c.root.getPath()), c.commitInfo.revision);
      }
    }
    return super.getData(dataId);
  }

  /**
   * Show skipped commits
   *
   * @param project        the context project
   * @param skippedCommits the skipped commits
   */
  public static void showSkipped(final Project project, final SortedMap<VirtualFile, List<GitRebaseUtils.CommitInfo>> skippedCommits) {
    UIUtil.invokeLaterIfNeeded(new Runnable() {
      @Override
      public void run() {
        ContentManager contentManager = ProjectLevelVcsManagerEx.getInstanceEx(project).getContentManager();
        if (contentManager == null) {
          return;
        }
        GitSkippedCommits skipped = new GitSkippedCommits(contentManager, project, skippedCommits);
        Content content = ContentFactory.SERVICE.getInstance().createContent(skipped, "Skipped Commits", true);
        ContentsUtil.addContent(contentManager, content, true);
        ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.VCS).activate(null);
      }
    });
  }

  /**
   * Wrapper for vcs root
   */
  private static class VcsRoot {
    final VirtualFile root;

    public VcsRoot(VirtualFile root) {
      this.root = root;
    }

    @Override
    public String toString() {
      return root.getPath();
    }
  }

  /**
   * Wrapper for commit
   */
  private static class Commit {
    final VirtualFile root;
    final GitRebaseUtils.CommitInfo commitInfo;

    public Commit(VirtualFile root, GitRebaseUtils.CommitInfo commitInfo) {
      this.root = root;
      this.commitInfo = commitInfo;
    }

    @Override
    public String toString() {
      return commitInfo.revision.asString().substring(0, 8) + ": " + commitInfo.subject;
    }
  }
}

@@ -7304,32 +7304,75 @@
  %7D%0A    %7D);%0A  %7D%0A%0A
+  @Override%0A  public void dispose() %7B%0A  %7D%0A%0A
   /**%0A   * Wrapp

fix compilation (implement dispose method)