/*
 * Copyright 2000-2014 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.dvcs;

import com.intellij.dvcs.ui.DvcsBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.CheckinProjectPanel;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.*;
import java.util.List;

public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComponent {

  private static final Logger log = Logger.getInstance(DvcsCommitAdditionalComponent.class);

  protected final JPanel myPanel;
  protected final JCheckBox myAmend;
  @Nullable private String myPreviousMessage;
  @Nullable private String myAmendedMessage;
  @NotNull protected final CheckinProjectPanel myCheckinPanel;
  @Nullable  private  Map<VirtualFile, String> myMessagesForRoots;

  public DvcsCommitAdditionalComponent(@NotNull final Project project, @NotNull CheckinProjectPanel panel) {
    myCheckinPanel = panel;
    myPanel = new JPanel(new GridBagLayout());
    final Insets insets = new Insets(2, 2, 2, 2);
    // add amend checkbox
    GridBagConstraints c = new GridBagConstraints();
    //todo change to MigLayout
    c.gridx = 0;
    c.gridy = 1;
    c.gridwidth = 2;
    c.anchor = GridBagConstraints.CENTER;
    c.insets = insets;
    c.weightx = 1;
    c.fill = GridBagConstraints.HORIZONTAL;

    myAmend = new NonFocusableCheckBox(DvcsBundle.message("commit.amend"));
    myAmend.setMnemonic('m');
    myAmend.setToolTipText(DvcsBundle.message("commit.amend.tooltip"));
    myPreviousMessage = myCheckinPanel.getCommitMessage();

    myAmend.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        if (myAmend.isSelected()) {
            if (myPreviousMessage.equals(myCheckinPanel.getCommitMessage())) { // if user has already typed something, don't revert it
              if (myMessagesForRoots == null) {
                loadMessagesInModalTask(project);      //load all commit messages for all repositories
              }
              String message = constructAmendedMessage();
              if (!StringUtil.isEmptyOrSpaces(message)) {
                myAmendedMessage = message;
                substituteCommitMessage(myAmendedMessage);
              }
            }
        }
        else {
          // there was the amended message, but user has changed it => not reverting
          if (myCheckinPanel.getCommitMessage().equals(myAmendedMessage)) {
            myCheckinPanel.setCommitMessage(myPreviousMessage);
          }
        }
      }
    });
    myPanel.add(myAmend, c);
  }

  private String constructAmendedMessage() {
    Set<VirtualFile> selectedRoots = getVcsRoots(getSelectedFilePaths());        // get only selected files
    LinkedHashSet<String> messages = ContainerUtil.newLinkedHashSet();
    if (myMessagesForRoots != null) {
      for (VirtualFile root : selectedRoots) {
        String message = myMessagesForRoots.get(root);
        if (message != null) {
          messages.add(message);
        }
      }
    }
    return DvcsUtil.joinMessagesOrNull(messages);
  }

  public JComponent getComponent() {
    return myPanel;
  }

  public void refresh() {
    myAmend.setSelected(false);
  }

  private void loadMessagesInModalTask(@NotNull Project project) {
    try {
      myMessagesForRoots =
        ProgressManager.getInstance().runProcessWithProgressSynchronously(new ThrowableComputable<Map<VirtualFile,String>, VcsException>() {
          @Override
          public Map<VirtualFile, String> compute() throws VcsException {
            return getLastCommitMessages();
          }
        }, "Reading commit message...", false, project);
    }
    catch (VcsException e) {
      Messages.showErrorDialog(getComponent(), "Couldn't load commit message of the commit to amend.\n" + e.getMessage(),
                               "Commit Message not Loaded");
      log.info(e);
    }
  }

  private void substituteCommitMessage(@NotNull String newMessage) {
    myPreviousMessage = myCheckinPanel.getCommitMessage();
    if (!myPreviousMessage.trim().equals(newMessage.trim())) {
      myCheckinPanel.setCommitMessage(newMessage);
    }
  }

  @Nullable
  private Map<VirtualFile, String> getLastCommitMessages() throws VcsException {
    Map<VirtualFile, String> messagesForRoots = new HashMap<VirtualFile, String>();
    Collection<VirtualFile> roots = myCheckinPanel.getRoots(); //all committed vcs roots, not only selected
    final Ref<VcsException> exception = Ref.create();
    for (VirtualFile root : roots) {
      String message = getLastCommitMessage(root);
      messagesForRoots.put(root, message);
    }
    if (!exception.isNull()) {
      throw exception.get();
    }
    return messagesForRoots;
  }

  @NotNull
  private List<FilePath> getSelectedFilePaths() {
    return ContainerUtil.map(myCheckinPanel.getFiles(), new Function<File, FilePath>() {
      @Override
      public FilePath fun(File file) {
        return new FilePathImpl(file, file.isDirectory());
      }
    });
  }

  @NotNull
  protected abstract Set<VirtualFile> getVcsRoots(@NotNull Collection<FilePath> files);

  @Nullable
  protected abstract String getLastCommitMessage(@NotNull VirtualFile repo) throws VcsException;

  public boolean isAmend() {
    return myAmend.isSelected();
  }
}
