/*
 * Copyright 2000-2011 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.branch;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.ArrayUtil;
import com.intellij.xml.util.XmlStringUtil;
import git4idea.DialogManager;
import git4idea.GitCommit;
import git4idea.repo.GitRepository;
import git4idea.ui.GitCommitListWithDiffPanel;
import git4idea.ui.GitRepositoryComboboxListCellRenderer;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * This dialog is shown when user tries to delete a local branch, which is not fully merged to the current branch.
 * It shows the list of commits not merged to the current branch and the list of branches, which the given branch is merged to.
 */
public class GitBranchIsNotFullyMergedDialog extends DialogWrapper {

  private final Map<GitRepository, List<GitCommit>> myCommits;
  private final GitCommitListWithDiffPanel myCommitListWithDiffPanel;
  private final Collection<GitRepository> myRepositories;
  @NotNull private final String myRemovedBranch;
  @NotNull private final Map<GitRepository, String> myBaseBranches;
  private final GitRepository myInitialRepository;

  /**
   * Show the dialog and get user's answer, whether he wants to force delete the branch.
   *
   * @param commits      the list of commits, which are not merged from the branch being deleted to the current branch,
   *                     grouped by repository.
   * @param baseBranches base branches (which Git reported as not containing commits from the removed branch) per repository.
   * @return true if user decided to restore the branch.
   */
  public static boolean showAndGetAnswer(@NotNull Project project,
                                         @NotNull Map<GitRepository, List<GitCommit>> commits,
                                         @NotNull Map<GitRepository, String> baseBranches,
                                         @NotNull String removedBranch) {
    GitBranchIsNotFullyMergedDialog dialog = new GitBranchIsNotFullyMergedDialog(project, commits, baseBranches, removedBranch);
    DialogManager.show(dialog);
    return dialog.isOK();
  }

  private GitBranchIsNotFullyMergedDialog(@NotNull Project project,
                                          @NotNull Map<GitRepository, List<GitCommit>> commits,
                                          @NotNull Map<GitRepository, String> baseBranches,
                                          @NotNull String removedBranch) {
    super(project, false);
    myCommits = commits;
    myRepositories = commits.keySet();
    myBaseBranches = baseBranches;
    myRemovedBranch = removedBranch;

    myInitialRepository = calcInitiallySelectedRepository();
    myCommitListWithDiffPanel = new GitCommitListWithDiffPanel(project, new ArrayList<>(myCommits.get(myInitialRepository)));

    init();

    setTitle("Branch Was Not Fully Merged");
    setOKButtonText("Restore");
    setOKButtonMnemonic('R');
    getCancelAction().putValue(DEFAULT_ACTION, Boolean.TRUE);
  }

  @NotNull
  private GitRepository calcInitiallySelectedRepository() {
    for (GitRepository repository : myRepositories) {
      if (!myCommits.get(repository).isEmpty()) {
        return repository;
      }
    }
    throw new AssertionError("The dialog shouldn't be shown. Unmerged commits: " + myCommits);
  }

  @NotNull
  private String makeDescription(@NotNull GitRepository repository) {
    String baseBranch = myBaseBranches.get(repository);
    String description;
    if (baseBranch == null) {
      description = String.format("All commits from branch %s were merged", myRemovedBranch);
    }
    else {
      description = String.format("The branch %s was not fully merged to %s.<br/>Below is the list of unmerged commits.",
                                  myRemovedBranch, baseBranch);
    }
    return XmlStringUtil.wrapInHtml(description);
  }

  @Override
  protected JComponent createNorthPanel() {
    JBLabel descriptionLabel = new JBLabel(makeDescription(myInitialRepository));

    JComboBox repositorySelector = new JComboBox(ArrayUtil.toObjectArray(myRepositories, GitRepository.class));
    repositorySelector.setRenderer(new GitRepositoryComboboxListCellRenderer(repositorySelector));
    repositorySelector.setSelectedItem(myInitialRepository);
    repositorySelector.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        GitRepository selectedRepo = (GitRepository)repositorySelector.getSelectedItem();
        descriptionLabel.setText(makeDescription(selectedRepo));
        myCommitListWithDiffPanel.setCommits(myCommits.get(selectedRepo));
      }
    });

    JPanel repoSelectorPanel = new JPanel(new BorderLayout());
    JBLabel label = new JBLabel("Repository: ");
    label.setLabelFor(repoSelectorPanel);
    repoSelectorPanel.add(label, BorderLayout.WEST);
    repoSelectorPanel.add(repositorySelector);

    if (myRepositories.size() < 2) {
      repoSelectorPanel.setVisible(false);
    }

    JPanel northPanel = new JPanel(new BorderLayout());
    northPanel.add(descriptionLabel);
    northPanel.add(repoSelectorPanel, BorderLayout.SOUTH);
    return northPanel;
  }

  @Override
  protected JComponent createCenterPanel() {
    JPanel rootPanel = new JPanel(new BorderLayout());
    rootPanel.add(myCommitListWithDiffPanel);
    return rootPanel;
  }

  @NotNull
  @Override
  protected Action[] createLeftSideActions() {
    return new Action[] { getOKAction() };
  }

  @NotNull
  @Override
  protected Action[] createActions() {
    Action cancelAction = getCancelAction();
    cancelAction.putValue(DEFAULT_ACTION, Boolean.TRUE);
    return new Action[] { cancelAction };
  }

  @Override
  public JComponent getPreferredFocusedComponent() {
    return myCommitListWithDiffPanel.getPreferredFocusComponent();
  }

  @Override
  protected String getDimensionServiceKey() {
    return GitBranchIsNotFullyMergedDialog.class.getName();
  }
}

@@ -1612,24 +1612,33 @@
 rapper %7B%0A%0A  
+@NotNull 
 private fina
@@ -1684,24 +1684,33 @@
 yCommits;%0A  
+@NotNull 
 private fina
@@ -1763,24 +1763,33 @@
 iffPanel;%0A  
+@NotNull 
 private fina
@@ -1951,16 +1951,25 @@
 ches;%0A  
+@NotNull 
 private 

add NotNulls