/*
 * 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.openapi.vcs.changes.ui;

import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataSink;
import com.intellij.openapi.actionSystem.TypeSafeDataProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.*;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.actions.DiffExtendUIFactory;
import com.intellij.openapi.vcs.checkin.*;
import com.intellij.openapi.vcs.impl.CheckinHandlersManager;
import com.intellij.openapi.vcs.impl.VcsGlobalMessageManager;
import com.intellij.openapi.vcs.ui.CommitMessage;
import com.intellij.openapi.vcs.ui.Refreshable;
import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SplitterWithSecondHideable;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.OnOffListener;
import com.intellij.util.containers.ContainerUtilRt;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

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

/**
 * @author max
 */
public class CommitChangeListDialog extends DialogWrapper implements CheckinProjectPanel, TypeSafeDataProvider {
  private final static String outCommitHelpId = "reference.dialogs.vcs.commit";
  private static final int LAYOUT_VERSION = 2;
  private final CommitContext myCommitContext;
  private final CommitMessage myCommitMessageArea;
  private Splitter mySplitter;
  private final JPanel myAdditionalOptionsPanel;

  private final ChangesBrowser myBrowser;
  private final ChangesBrowserExtender myBrowserExtender;

  private CommitLegendPanel myLegend;
  private final ShortDiffDetails myDiffDetails;

  private final List<RefreshableOnComponent> myAdditionalComponents = new ArrayList<RefreshableOnComponent>();
  private final List<CheckinHandler> myHandlers = new ArrayList<CheckinHandler>();
  private final String myActionName;
  private final Project myProject;
  private final List<CommitExecutor> myExecutors;
  private final Alarm myOKButtonUpdateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
  private String myLastKnownComment = "";
  private final boolean myAllOfDefaultChangeListChangesIncluded;
  @NonNls private static final String SPLITTER_PROPORTION_OPTION = "CommitChangeListDialog.SPLITTER_PROPORTION_" + LAYOUT_VERSION;
  private final CommitExecutorAction[] myExecutorActions;
  private final boolean myShowVcsCommit;
  private final Map<AbstractVcs, JPanel> myPerVcsOptionsPanels = new HashMap<AbstractVcs, JPanel>();

  @Nullable
  private final AbstractVcs myVcs;
  private final boolean myIsAlien;
  private boolean myDisposed = false;
  private final JLabel myWarningLabel;

  private final Map<String, CheckinChangeListSpecificComponent> myCheckinChangeListSpecificComponents;

  private final Map<String, String> myListComments;
  private String myLastSelectedListName;
  private ChangeInfoCalculator myChangesInfoCalculator;

  private final PseudoMap<Object, Object> myAdditionalData;
  private String myHelpId;

  private SplitterWithSecondHideable myDetailsSplitter;
  private static final String DETAILS_SPLITTER_PROPORTION_OPTION = "CommitChangeListDialog.DETAILS_SPLITTER_PROPORTION_" + LAYOUT_VERSION;
  private static final String DETAILS_SHOW_OPTION = "CommitChangeListDialog.DETAILS_SHOW_OPTION_";
  private JPanel myDetailsPanel;
  private final FileAndDocumentListenersForShortDiff myListenersForShortDiff;
  private final String myOkActionText;
  private final ZipperUpdater myZipperUpdater;
  private final Runnable myRefreshDetails;
  private CommitAction myCommitAction;
  @Nullable private CommitResultHandler myResultHandler;

  private static class MyUpdateButtonsRunnable implements Runnable {
    private CommitChangeListDialog myDialog;

    private MyUpdateButtonsRunnable(final CommitChangeListDialog dialog) {
      myDialog = dialog;
    }

    public void cancel() {
      myDialog = null;
    }

    @Override
    public void run() {
      if (myDialog != null) {
        myDialog.updateButtons();
        myDialog.updateLegend();
      }
    }

    public void restart(final CommitChangeListDialog dialog) {
      myDialog = dialog;
      run();
    }
  }

  private final MyUpdateButtonsRunnable myUpdateButtonsRunnable = new MyUpdateButtonsRunnable(this);

  public static boolean commitChanges(final Project project, final List<Change> changes, final LocalChangeList initialSelection,
                                      final List<CommitExecutor> executors, final boolean showVcsCommit, final String comment,
                                      @Nullable CommitResultHandler customResultHandler, boolean cancelIfNoChanges) {
    if (cancelIfNoChanges && changes.isEmpty() && !ApplicationManager.getApplication().isUnitTestMode()) {
      Messages.showInfoMessage(project, VcsBundle.message("commit.dialog.no.changes.detected.text"),
                               VcsBundle.message("commit.dialog.no.changes.detected.title"));
      return false;
    }

    for (BaseCheckinHandlerFactory factory : getCheckInFactories(project)) {
      BeforeCheckinDialogHandler handler = factory.createSystemReadyHandler(project);
      if (handler != null && !handler.beforeCommitDialogShown(project, changes, executors, showVcsCommit)) {
        return false;
      }
    }

    final ChangeListManager manager = ChangeListManager.getInstance(project);
    CommitChangeListDialog dialog = new CommitChangeListDialog(project, changes, initialSelection, executors, showVcsCommit, manager.getDefaultChangeList(), manager.getChangeListsCopy(), null,
                                                               false, comment, customResultHandler);
    if (!ApplicationManager.getApplication().isUnitTestMode()) {
      dialog.show();
    }
    else {
      dialog.doOKAction();
    }
    return dialog.isOK();
  }

  private static List<BaseCheckinHandlerFactory> getCheckInFactories(Project project) {
    return CheckinHandlersManager.getInstance().getRegisteredCheckinHandlerFactories(
      ProjectLevelVcsManager.getInstance(project).getAllActiveVcss());
  }

  @NotNull
  public List<RefreshableOnComponent> getAdditionalComponents() {
    return Collections.unmodifiableList(myAdditionalComponents);
  }

  public static void commitPaths(final Project project, Collection<FilePath> paths, final LocalChangeList initialSelection,
                                 @Nullable final CommitExecutor executor, final String comment) {
    final ChangeListManager manager = ChangeListManager.getInstance(project);
    final Collection<Change> changes = new HashSet<Change>();
    for (FilePath path : paths) {
      changes.addAll(manager.getChangesIn(path));
    }

    commitChanges(project, changes, initialSelection, executor, comment);
  }

  public static boolean commitChanges(final Project project, final Collection<Change> changes, final LocalChangeList initialSelection,
                                      @Nullable final CommitExecutor executor, final String comment) {
    if (executor == null) {
      return commitChanges(project, changes, initialSelection, collectExecutors(project, changes), true, comment, null);
    }
    else {
      return commitChanges(project, changes, initialSelection, Collections.singletonList(executor), false, comment, null);
    }
  }

  public static List<CommitExecutor> collectExecutors(Project project, Collection<Change> changes) {
    List<CommitExecutor> result = new ArrayList<CommitExecutor>();
    for (AbstractVcs<?> vcs : getAffectedVcses(project, changes)) {
      result.addAll(vcs.getCommitExecutors());
    }
    result.addAll(ChangeListManager.getInstance(project).getRegisteredExecutors());
    return result;
  }

  /**
   * Shows the commit dialog, and performs the selected action: commit, commit & push, create patch, etc.
   * @param customResultHandler If this is not null, after commit is completed, custom result handler is called instead of
     *                            showing the default notification in case of commit or failure.
     * @return true if user agreed to commit, false if he pressed "Cancel".
     */
    public static boolean commitChanges(final Project project, final Collection<Change> changes, final LocalChangeList initialSelection,
                                        final List<CommitExecutor> executors, final boolean showVcsCommit, final String comment,
                                        @Nullable CommitResultHandler customResultHandler) {
      return commitChanges(project, new ArrayList<Change>(changes), initialSelection, executors, showVcsCommit, comment,
                           customResultHandler, true);
    }

    public static void commitAlienChanges(final Project project, final List<Change> changes, final AbstractVcs vcs,
                                        final String changelistName, final String comment) {
    final LocalChangeList lcl = new AlienLocalChangeList(changes, changelistName);
    new CommitChangeListDialog(project, changes, null, null, true, AlienLocalChangeList.DEFAULT_ALIEN, Collections.singletonList(lcl), vcs,
                               true, comment, null).show();
  }

  private CommitChangeListDialog(final Project project,
                                 final List<Change> changes,
                                 final LocalChangeList initialSelection,
                                 final List<CommitExecutor> executors,
                                 final boolean showVcsCommit, final LocalChangeList defaultChangeList,
                                 final List<LocalChangeList> changeLists, @Nullable final AbstractVcs singleVcs, final boolean isAlien,
                                 final String comment, @Nullable CommitResultHandler customResultHandler) {
    super(project, true);
    myCommitContext = new CommitContext();
    myProject = project;
    myExecutors = executors;
    myShowVcsCommit = showVcsCommit;
    myVcs = singleVcs;
    myResultHandler = customResultHandler;
    myListComments = new HashMap<String, String>();
    myAdditionalData = new PseudoMap<Object, Object>();
    myDiffDetails = new ShortDiffDetails(myProject, new Getter<Change[]>() {
      @Override
      public Change[] get() {
        final List<Change> selectedChanges = myBrowser.getViewer().getSelectedChanges();
        return selectedChanges.toArray(new Change[selectedChanges.size()]);
      }
    }, VcsChangeDetailsManager.getInstance(myProject));

    if (!myShowVcsCommit && ((myExecutors == null) || myExecutors.size() == 0)) {
      throw new IllegalArgumentException("nothing found to execute commit with");
    }

    myAllOfDefaultChangeListChangesIncluded = new HashSet<Change>(changes).containsAll(new HashSet<Change>(defaultChangeList.getChanges()));

    myIsAlien = isAlien;
    if (isAlien) {
      AlienChangeListBrowser browser = new AlienChangeListBrowser(project, changeLists, changes, initialSelection, true, true, singleVcs);
      myBrowser = browser;
      myBrowserExtender = browser;
    } else {
      MultipleChangeListBrowser browser = new MultipleChangeListBrowser(project, changeLists, changes, getDisposable(), initialSelection, true, true,
                                                                        new Runnable() {
                                                                          @Override
                                                                          public void run() {
                                                                            updateWarning();
                                                                          }
                                                                        },
        new Runnable() {
          @Override
          public void run() {
            for (CheckinHandler handler : myHandlers) {
              handler.includedChangesChanged();
            }
          }
        }) {
        @Override
        protected void afterDiffRefresh() {
          myBrowser.rebuildList();
          myBrowser.setDataIsDirty(false);
          ApplicationManager.getApplication().invokeLater(new Runnable() {
            @Override
            public void run() {
              IdeFocusManager.findInstance().requestFocus(myBrowser.getViewer().getPreferredFocusedComponent(), true);
            }
          });
        }
      };
      myBrowser = browser;
      myBrowser.setAlwayExpandList(false);
      myBrowserExtender = browser.getExtender();
    }
    myDiffDetails.setParent(myBrowser);
    myZipperUpdater = new ZipperUpdater(30, Alarm.ThreadToUse.SWING_THREAD, getDisposable());
    myRefreshDetails = new Runnable() {
      @Override
      public void run() {
        myDiffDetails.refresh();
      }
    };
    myListenersForShortDiff = new FileAndDocumentListenersForShortDiff(myDiffDetails) {
      @Override
      protected void updateDetails() {
        myZipperUpdater.queue(myRefreshDetails);
      }
      @Override
      protected boolean updateSynchronously() {
        return false;
      }
    };
    myListenersForShortDiff.on();

    myBrowser.getViewer().addSelectionListener(new Runnable() {
      @Override
      public void run() {
        myZipperUpdater.queue(myRefreshDetails);
      }
    });

    myBrowserExtender.addToolbarActions(this);

    myBrowserExtender.addSelectedListChangeListener(new SelectedListChangeListener() {
      @Override
      public void selectedListChanged() {
        updateOnListSelection();
      }
    });
    myBrowser.setDiffExtendUIFactory(new DiffExtendUIFactory() {
      @Override
      public List<? extends AnAction> createActions(final Change change) {
        return myBrowser.createDiffActions(change);
      }

      @Override
      @Nullable
      public JComponent createBottomComponent() {
        return new DiffCommitMessageEditor(CommitChangeListDialog.this);
      }
    });

    myCommitMessageArea = new CommitMessage(project);

    if (!VcsConfiguration.getInstance(project).CLEAR_INITIAL_COMMIT_MESSAGE) {
      setComment(project, initialSelection, comment);
    }

    myActionName = VcsBundle.message("commit.dialog.title");

    myAdditionalOptionsPanel = new JPanel();

    myAdditionalOptionsPanel.setLayout(new BorderLayout());
    Box optionsBox = Box.createVerticalBox();

    boolean hasVcsOptions = false;
    Box vcsCommitOptions = Box.createVerticalBox();
    final List<AbstractVcs> vcses = new ArrayList<AbstractVcs>(getAffectedVcses());
    Collections.sort(vcses, new Comparator<AbstractVcs>() {
      @Override
      public int compare(AbstractVcs o1, AbstractVcs o2) {
        return o1.getKeyInstanceMethod().getName().compareToIgnoreCase(o2.getKeyInstanceMethod().getName());
      }
    });
    myCheckinChangeListSpecificComponents = new HashMap<String, CheckinChangeListSpecificComponent>();
    for (AbstractVcs vcs : vcses) {
      final CheckinEnvironment checkinEnvironment = vcs.getCheckinEnvironment();
      if (checkinEnvironment != null) {
        final RefreshableOnComponent options = checkinEnvironment.createAdditionalOptionsPanel(this, myAdditionalData);
        if (options != null) {
          JPanel vcsOptions = new JPanel(new BorderLayout());
          vcsOptions.add(options.getComponent(), BorderLayout.CENTER);
          vcsOptions.setBorder(IdeBorderFactory.createTitledBorder(vcs.getDisplayName(), true));
          vcsCommitOptions.add(vcsOptions);
          myPerVcsOptionsPanels.put(vcs, vcsOptions);
          myAdditionalComponents.add(options);
          if (options instanceof CheckinChangeListSpecificComponent) {
            myCheckinChangeListSpecificComponents.put(vcs.getName(), (CheckinChangeListSpecificComponent) options);
          }
          hasVcsOptions = true;
        }
      }
    }

    if (hasVcsOptions) {
      vcsCommitOptions.add(Box.createVerticalGlue());
      optionsBox.add(vcsCommitOptions);
    }

    boolean beforeVisible = false;
    boolean afterVisible = false;
    Box beforeBox = Box.createVerticalBox();
    Box afterBox = Box.createVerticalBox();
    for (BaseCheckinHandlerFactory factory : getCheckInFactories(project)) {
      final CheckinHandler handler = factory.createHandler(this, myCommitContext);
      if (CheckinHandler.DUMMY.equals(handler)) continue;

      myHandlers.add(handler);
      final RefreshableOnComponent beforePanel = handler.getBeforeCheckinConfigurationPanel();
      if (beforePanel != null) {
        beforeBox.add(beforePanel.getComponent());
        beforeVisible = true;
        myAdditionalComponents.add(beforePanel);
      }

      final RefreshableOnComponent afterPanel = handler.getAfterCheckinConfigurationPanel(getDisposable());
      if (afterPanel != null) {
        afterBox.add(afterPanel.getComponent());
        afterVisible = true;
        myAdditionalComponents.add(afterPanel);
      }
    }

    final String actionName = getCommitActionName();
    final String borderTitleName = actionName.replace("_", "").replace("&", "");
    if (beforeVisible) {
      beforeBox.add(Box.createVerticalGlue());
      JPanel beforePanel = new JPanel(new BorderLayout());
      beforePanel.add(beforeBox);
      beforePanel.setBorder(IdeBorderFactory.createTitledBorder(
        VcsBundle.message("border.standard.checkin.options.group", borderTitleName), true));
      optionsBox.add(beforePanel);
    }

    if (afterVisible) {
      afterBox.add(Box.createVerticalGlue());
      JPanel afterPanel = new JPanel(new BorderLayout());
      afterPanel.add(afterBox);
      afterPanel.setBorder(IdeBorderFactory.createTitledBorder(
        VcsBundle.message("border.standard.after.checkin.options.group", borderTitleName), true));
      optionsBox.add(afterPanel);
    }

    if (hasVcsOptions || beforeVisible || afterVisible) {
      optionsBox.add(Box.createVerticalGlue());
      myAdditionalOptionsPanel.add(optionsBox, BorderLayout.NORTH);
    }

    myOkActionText = actionName;

    if (myShowVcsCommit) {
      setTitle(myActionName);
    }
    else {
      setTitle(trimEllipsis(myExecutors.get(0).getActionText()));
    }

    restoreState();

    if (myExecutors != null) {
      myExecutorActions = new CommitExecutorAction[myExecutors.size()];

      for (int i = 0; i < myExecutors.size(); i++) {
        final CommitExecutor commitExecutor = myExecutors.get(i);
        myExecutorActions[i] = new CommitExecutorAction(commitExecutor, i == 0 && !myShowVcsCommit);
      }
    } else {
      myExecutorActions = null;
    }

    myWarningLabel = new JLabel();
    myWarningLabel.setUI(new MultiLineLabelUI());
    myWarningLabel.setForeground(Color.red);

    updateWarning();

    init();
    updateButtons();
    updateVcsOptionsVisibility();

    updateOnListSelection();
    myCommitMessageArea.requestFocusInMessage();

    for (EditChangelistSupport support : Extensions.getExtensions(EditChangelistSupport.EP_NAME, project)) {
      support.installSearch(myCommitMessageArea.getEditorField(), myCommitMessageArea.getEditorField());
    }

    showDetailsIfSaved();
  }

  private void setComment(Project project, LocalChangeList initialSelection, String comment) {
    if (comment != null) {
      setCommitMessage(comment);
      myLastKnownComment = comment;
      myLastSelectedListName = initialSelection == null ? myBrowser.getSelectedChangeList().getName() : initialSelection.getName();
    } else {
      updateComment();

      if (StringUtil.isEmptyOrSpaces(myCommitMessageArea.getComment())) {
        setCommitMessage(VcsConfiguration.getInstance(project).LAST_COMMIT_MESSAGE);
        final String messageFromVcs = getInitialMessageFromVcs();
        if (messageFromVcs != null) {
          myCommitMessageArea.setText(messageFromVcs);
        }
      }
    }
  }

  private void showDetailsIfSaved() {
    String value = PropertiesComponent.getInstance().getValue(DETAILS_SHOW_OPTION);
    if (value != null) {
      Boolean asBoolean = Boolean.valueOf(value);
      if (Boolean.TRUE.equals(asBoolean)) {
        myDetailsSplitter.initOn();
      }
    }
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        myZipperUpdater.queue(myRefreshDetails);
      }
    });
  }

  private void updateOnListSelection() {
    updateComment();
    updateVcsOptionsVisibility();
    for (CheckinChangeListSpecificComponent component : myCheckinChangeListSpecificComponents.values()) {
      component.onChangeListSelected((LocalChangeList) myBrowser.getSelectedChangeList());
    }
  }

  private void updateWarning() {
    // check for null since can be called from constructor before field initialization
    if (myWarningLabel != null) {
      myWarningLabel.setVisible(false);
      @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
      final VcsException updateException = ((ChangeListManagerImpl)ChangeListManager.getInstance(myProject)).getUpdateException();
      if (updateException != null) {
        final String[] messages = updateException.getMessages();
        if (messages != null && messages.length > 0) {
          final String message = messages[0];
          myWarningLabel.setText("Warning: not all local changes may be shown due to an error: " + message);
          myWarningLabel.setVisible(true);
        }
      }
    }
  }

  private void updateVcsOptionsVisibility() {
    Collection<AbstractVcs> affectedVcses = getAffectedVcses(myProject, myBrowser.getSelectedChangeList().getChanges());
    for (Map.Entry<AbstractVcs, JPanel> entry : myPerVcsOptionsPanels.entrySet()) {
      entry.getValue().setVisible(affectedVcses.contains(entry.getKey()));
    }
  }

  @Override
  protected String getHelpId() {
    return myHelpId;
  }

  private class CommitAction extends AbstractAction implements OptionAction {

    private Action[] myOptions = new Action[0];

    private CommitAction() {
      super(myOkActionText);
      putValue(DEFAULT_ACTION, Boolean.TRUE);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
      doOKAction();
    }

    @NotNull
    @Override
    public Action[] getOptions() {
      return myOptions;
    }

    public void setOptions(Action[] actions) {
      myOptions = actions;
    }
  }

  @Override
  protected void doOKAction() {
    if (!saveDialogState()) return;
    saveComments(true);
    final DefaultListCleaner defaultListCleaner = new DefaultListCleaner();

    final Runnable callCommit = new Runnable() {
      @Override
      public void run() {
        try {
          CheckinHandler.ReturnResult result = runBeforeCommitHandlers(new Runnable() {
            @Override
            public void run() {
              CommitChangeListDialog.super.doOKAction();
              doCommit(myResultHandler);
            }
          }, null);

          if (result == CheckinHandler.ReturnResult.COMMIT) {
            defaultListCleaner.clean();
          }
        }
        catch (InputException ex) {
          ex.show();
        }
      }
    };
    if (myBrowser.isDataIsDirty()) {
      ensureDataIsActual(callCommit);
    } else {
      callCommit.run();
    }
  }

  @NotNull
  @Override
  protected Action getOKAction() {
    return new CommitAction();
  }

  @Override
  @NotNull
  protected Action[] createActions() {
    final List<Action> actions = new ArrayList<Action>();

    myCommitAction = null;
    if (myShowVcsCommit) {
      myCommitAction = new CommitAction();
      actions.add(myCommitAction);
      myHelpId = outCommitHelpId;
    }
    if (myExecutors != null) {
      if (myCommitAction != null) {
        myCommitAction.setOptions(myExecutorActions);
      } else {
        actions.addAll(Arrays.asList(myExecutorActions));
      }
      for (CommitExecutor executor : myExecutors) {
        if (myHelpId != null) break;
        if (executor instanceof CommitExecutorWithHelp) {
          myHelpId = ((CommitExecutorWithHelp) executor).getHelpId();
        }
      }
    }
    actions.add(getCancelAction());
    if (myHelpId != null) {
      actions.add(getHelpAction());
    }

    return actions.toArray(new Action[actions.size()]);
  }

  private void execute(final CommitExecutor commitExecutor) {
    if (!saveDialogState()) return;
    saveComments(true);
    final CommitSession session = commitExecutor.createCommitSession();
    if (session instanceof CommitSessionContextAware) {
      ((CommitSessionContextAware)session).setContext(myCommitContext);
    }
    if (session == CommitSession.VCS_COMMIT) {
      doOKAction();
      return;
    }
    boolean isOK = true;
    if (SessionDialog.createConfigurationUI(session, getIncludedChanges(), getCommitMessage())!= null) {
      DialogWrapper sessionDialog = new SessionDialog(commitExecutor.getActionText(),
                                                      getProject(),
                                                      session,
                                                      getIncludedChanges(),
                                                      getCommitMessage());
      sessionDialog.show();
      isOK = sessionDialog.isOK();
    }
    if (isOK) {
      final DefaultListCleaner defaultListCleaner = new DefaultListCleaner();
      runBeforeCommitHandlers(new Runnable() {
        @Override
        public void run() {
          boolean success = false;
          try {
            final boolean completed = ProgressManager.getInstance().runProcessWithProgressSynchronously(
              new Runnable() {
              @Override
              public void run() {
                session.execute(getIncludedChanges(), getCommitMessage());
              }
            }, commitExecutor.getActionText(), true, getProject());

            if (completed) {
              for (CheckinHandler handler : myHandlers) {
                handler.checkinSuccessful();
              }

              success = true;
              defaultListCleaner.clean();
              close(OK_EXIT_CODE);
            }
            else {
              session.executionCanceled();
            }
          }
          catch (Throwable e) {
            Messages.showErrorDialog(VcsBundle.message("error.executing.commit", commitExecutor.getActionText(), e.getLocalizedMessage()),
                                     commitExecutor.getActionText());

            for (CheckinHandler handler : myHandlers) {
              handler.checkinFailed(Arrays.asList(new VcsException(e)));
            }
          }
          finally {
            if (myResultHandler != null) {
              if (success) {
                myResultHandler.onSuccess(getCommitMessage());
              }
              else {
                myResultHandler.onFailure();
              }
            }
          }
        }
      }, commitExecutor);


    }
    else {
      session.executionCanceled();
    }
  }

  @Nullable
  private String getInitialMessageFromVcs() {
    final List<Change> list = getIncludedChanges();
    final Ref<String> result = new Ref<String>();
    ChangesUtil.processChangesByVcs(myProject, list, new ChangesUtil.PerVcsProcessor<Change>() {
      @Override
      public void process(final AbstractVcs vcs, final List<Change> items) {
        if (result.isNull()) {
          CheckinEnvironment checkinEnvironment = vcs.getCheckinEnvironment();
          if (checkinEnvironment != null) {
            final Collection<FilePath> paths = ChangesUtil.getPaths(items);
            String defaultMessage = checkinEnvironment.getDefaultMessageFor(paths.toArray(new FilePath[paths.size()]));
            if (defaultMessage != null) {
              result.set(defaultMessage);
            }
          }
        }
      }
    });
    return result.get();
  }

  private void saveCommentIntoChangeList() {
    if (myLastSelectedListName != null) {
      final String actualCommentText = myCommitMessageArea.getComment();
      final String saved = myListComments.get(myLastSelectedListName);
      if (! Comparing.equal(saved, actualCommentText)) {
        myListComments.put(myLastSelectedListName, actualCommentText);
      }
    }
  }

  private static boolean isDefaultList(final LocalChangeList list) {
    return VcsBundle.message("changes.default.changelist.name").equals(list.getName());
  }

  private void updateComment() {
    if (VcsConfiguration.getInstance(getProject()).CLEAR_INITIAL_COMMIT_MESSAGE) return;
    final LocalChangeList list = (LocalChangeList) myBrowser.getSelectedChangeList();
    if (list == null || (list.getName().equals(myLastSelectedListName))) {
      return;
    } else if (myLastSelectedListName != null) {
      saveCommentIntoChangeList();
    }
    myLastSelectedListName = list.getName();

    String listComment = list.getComment();
    if (StringUtil.isEmptyOrSpaces(listComment)) {
      final String listTitle = list.getName();
      if (! isDefaultList(list)) {
        listComment = listTitle;
      }
      else {
        // use last know comment; it is already stored in list
        listComment = myLastKnownComment;
      }
    }

    myCommitMessageArea.setText(listComment);
  }


  @Override
  public void dispose() {
    myDisposed = true;
    myBrowser.dispose();
    Disposer.dispose(myCommitMessageArea);
    Disposer.dispose(myOKButtonUpdateAlarm);
    myUpdateButtonsRunnable.cancel();
    myListenersForShortDiff.off();
    super.dispose();
    Disposer.dispose(myDiffDetails);
    PropertiesComponent.getInstance().setValue(SPLITTER_PROPORTION_OPTION, String.valueOf(mySplitter.getProportion()));
    float usedProportion = myDetailsSplitter.getUsedProportion();
    if (usedProportion > 0) {
      PropertiesComponent.getInstance().setValue(DETAILS_SPLITTER_PROPORTION_OPTION, String.valueOf(usedProportion));
    }
    PropertiesComponent.getInstance().setValue(DETAILS_SHOW_OPTION, String.valueOf(myDetailsSplitter.isOn()));
  }

  @Override
  public String getCommitActionName() {
    String name = null;
    for (AbstractVcs vcs : getAffectedVcses()) {
      final CheckinEnvironment checkinEnvironment = vcs.getCheckinEnvironment();
      if (name == null && checkinEnvironment != null) {
        name = checkinEnvironment.getCheckinOperationName();
      }
      else {
        name = VcsBundle.getString("commit.dialog.default.commit.operation.name");
      }
    }
    return name != null ? name : VcsBundle.getString("commit.dialog.default.commit.operation.name");
  }

  @Override
  public boolean isCheckSpelling() {
    VcsConfiguration configuration = VcsConfiguration.getInstance(myProject);
    return configuration == null || configuration.CHECK_COMMIT_MESSAGE_SPELLING;
  }

  @Override
  public void setCheckSpelling(boolean checkSpelling) {
    VcsConfiguration configuration = VcsConfiguration.getInstance(myProject);
    if (configuration != null) {
      configuration.CHECK_COMMIT_MESSAGE_SPELLING = checkSpelling;
    }
    myCommitMessageArea.setCheckSpelling(checkSpelling);
  }

  private boolean checkComment() {
    if (VcsConfiguration.getInstance(myProject).FORCE_NON_EMPTY_COMMENT && (getCommitMessage().length() == 0)) {
      int requestForCheckin = Messages.showYesNoDialog(VcsBundle.message("confirmation.text.check.in.with.empty.comment"),
                                                       VcsBundle.message("confirmation.title.check.in.with.empty.comment"),
                                                       Messages.getWarningIcon());
      return requestForCheckin == Messages.YES;
    }
    else {
      return true;
    }
  }

  private void stopUpdate() {
    myDisposed = true;
    myUpdateButtonsRunnable.cancel();
  }

  private void restartUpdate() {
    myDisposed = false;
    myUpdateButtonsRunnable.restart(this);
  }

  private CheckinHandler.ReturnResult runBeforeCommitHandlers(final Runnable okAction, final CommitExecutor executor) {
    final Computable<CheckinHandler.ReturnResult> proceedRunnable = new Computable<CheckinHandler.ReturnResult>() {
      @Override
      public CheckinHandler.ReturnResult compute() {
        FileDocumentManager.getInstance().saveAllDocuments();

        for (CheckinHandler handler : myHandlers) {
          if (!(handler.acceptExecutor(executor))) continue;
          final CheckinHandler.ReturnResult result = handler.beforeCheckin(executor, myAdditionalData);
          if (result == CheckinHandler.ReturnResult.COMMIT) continue;
          if (result == CheckinHandler.ReturnResult.CANCEL) {
            restartUpdate();
            return CheckinHandler.ReturnResult.CANCEL;
          }

          if (result == CheckinHandler.ReturnResult.CLOSE_WINDOW) {
            final ChangeList changeList = myBrowser.getSelectedChangeList();
            CommitHelper.moveToFailedList(changeList,
                             getCommitMessage(),
                             getIncludedChanges(),
                             VcsBundle.message("commit.dialog.rejected.commit.template", changeList.getName()),
                             myProject);
            doCancelAction();
            return CheckinHandler.ReturnResult.CLOSE_WINDOW;
          }
        }

        okAction.run();
        return CheckinHandler.ReturnResult.COMMIT;
      }
    };

    stopUpdate();
    final Ref<CheckinHandler.ReturnResult> compoundResultRef = Ref.create();
    Runnable runnable = new Runnable() {
      @Override
      public void run() {
        compoundResultRef.set(proceedRunnable.compute());
      }
    };
    for(final CheckinHandler handler: myHandlers) {
      if (handler instanceof CheckinMetaHandler) {
        final Runnable previousRunnable = runnable;
        runnable = new Runnable() {
          @Override
          public void run() {
            ((CheckinMetaHandler)handler).runCheckinHandlers(previousRunnable);
          }
        };
      }
    }
    runnable.run();
    return compoundResultRef.get();
  }

  private boolean saveDialogState() {
    if (!checkComment()) {
      return false;
    }

    saveCommentIntoChangeList();
    VcsConfiguration.getInstance(myProject).saveCommitMessage(getCommitMessage());
    try {
      saveState();
    }
    catch(InputException ex) {
      ex.show();
      return false;
    }
    return true;
  }

  private class DefaultListCleaner {
    private final boolean myToClean;

    private DefaultListCleaner() {
      final int selectedSize = getIncludedChanges().size();
      final ChangeList selectedList = myBrowser.getSelectedChangeList();
      final int totalSize = selectedList.getChanges().size();
      myToClean = (totalSize == selectedSize) && (isDefaultList((LocalChangeList) selectedList));
    }

    void clean() {
      if (myToClean) {
        final ChangeListManager clManager = ChangeListManager.getInstance(myProject);
        clManager.editComment(VcsBundle.message("changes.default.changelist.name"), "");
      }
    }
  }

  private void saveComments(final boolean isOk) {
    final ChangeListManager clManager = ChangeListManager.getInstance(myProject);
    if (isOk) {
      final int selectedSize = getIncludedChanges().size();
      final ChangeList selectedList = myBrowser.getSelectedChangeList();
      final int totalSize = selectedList.getChanges().size();
      if (totalSize > selectedSize) {
        myListComments.remove(myLastSelectedListName);
      }
    }
    for (Map.Entry<String, String> entry : myListComments.entrySet()) {
      final String name = entry.getKey();
      final String value = entry.getValue();
      clManager.editComment(name, value);
    }
  }

  @Override
  public void doCancelAction() {
    for (CheckinChangeListSpecificComponent component : myCheckinChangeListSpecificComponents.values()) {
      component.saveState();
    }
    saveCommentIntoChangeList();
    saveComments(false);
    //VcsConfiguration.getInstance(myProject).saveCommitMessage(getCommitMessage());
    super.doCancelAction();
  }

  private void doCommit(@Nullable CommitResultHandler customResultHandler) {
    final CommitHelper helper = new CommitHelper(
      myProject,
      myBrowser.getSelectedChangeList(),
      getIncludedChanges(),
      myActionName,
      getCommitMessage(),
      myHandlers,
      myAllOfDefaultChangeListChangesIncluded, false, myAdditionalData, customResultHandler);

    if (myIsAlien) {
      helper.doAlienCommit(myVcs);
    } else {
      helper.doCommit();
    }
  }

  @Nullable
  @Override
  protected JComponent createNorthPanel() {
    final JComponent banner = VcsGlobalMessageManager.getInstance(myProject).getMessageBanner();
    return banner != null ? banner : super.createNorthPanel();
  }

  @Override
  @Nullable
  protected JComponent createCenterPanel() {
    JPanel rootPane = new JPanel(new BorderLayout());

    mySplitter = new Splitter(true);
    mySplitter.setHonorComponentsMinimumSize(true);
    mySplitter.setFirstComponent(myBrowser);
    mySplitter.setSecondComponent(myCommitMessageArea);
    initMainSplitter();

    rootPane.add(mySplitter, BorderLayout.CENTER);

    myChangesInfoCalculator = new ChangeInfoCalculator();
    myLegend = new CommitLegendPanel(myChangesInfoCalculator);
    JPanel legendPanel = new JPanel(new BorderLayout());
    legendPanel.add(myLegend.getComponent(), BorderLayout.EAST);
    myBrowser.getBottomPanel().add(legendPanel, BorderLayout.SOUTH);

    JPanel infoPanel = new JPanel(new BorderLayout());
    infoPanel.add(myAdditionalOptionsPanel, BorderLayout.CENTER);
    rootPane.add(infoPanel, BorderLayout.EAST);
    infoPanel.setBorder(IdeBorderFactory.createEmptyBorder(0, 10, 0, 0));

    final JPanel wrapper = new JPanel(new GridBagLayout());
    final GridBagConstraints gb = new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
                                                                   new Insets(0, 0, 0, 0), 0, 0);
    final JPanel panel = new JPanel(new BorderLayout());
    panel.add(wrapper, BorderLayout.WEST);
    rootPane.add(panel, BorderLayout.SOUTH);

    myWarningLabel.setBorder(BorderFactory.createEmptyBorder(5,5,0,5));
    wrapper.add(myWarningLabel, gb);

    myDetailsSplitter = new SplitterWithSecondHideable(true, "Details", rootPane,
                                                      new OnOffListener<Integer>() {
                                                        @Override
                                                        public void on(Integer integer) {
                                                          if (integer == 0) return;
                                                          mySplitter.skipNextLayouting();
                                                          myDetailsSplitter.getComponent().skipNextLayouting();
                                                          final Dimension dialogSize = getSize();
                                                          setSize(dialogSize.width, dialogSize.height + integer);
                                                          repaint();
                                                        }

                                                        @Override
                                                        public void off(Integer integer) {
                                                          if (integer == 0) return;
                                                          mySplitter.skipNextLayouting();
                                                          myDetailsSplitter.getComponent().skipNextLayouting();
                                                          final Dimension dialogSize = getSize();
                                                          setSize(dialogSize.width, dialogSize.height - integer);
                                                          repaint();
                                                        }
                                                      }) {
      @Override
      protected RefreshablePanel createDetails() {
        initDetails();
        return myDiffDetails;
      }

      @Override
      protected float getSplitterInitialProportion() {
        float value = 0;
        final String remembered = PropertiesComponent.getInstance().getValue(DETAILS_SPLITTER_PROPORTION_OPTION);
        if (remembered != null) {
          try {
            value = Float.valueOf(remembered);
          } catch (NumberFormatException e) {
            //
          }
        }
        if (value <= 0.05 || value >= 0.95) {
          return 0.6f;
        }
        return value;
      }
    };

    return myDetailsSplitter.getComponent();
  }

  private void initMainSplitter() {
    final String s = PropertiesComponent.getInstance().getValue(SPLITTER_PROPORTION_OPTION);
    if (s != null) {
      try {
        mySplitter.setProportion(Float.valueOf(s).floatValue());
      } catch (NumberFormatException e) {
        //
      }
    } else {
      mySplitter.setProportion(0.5f);
    }
  }

  private void initDetails() {
    if (myDetailsPanel == null) {
      myDetailsPanel = myDiffDetails.getPanel();
    }
  }

  public Collection<AbstractVcs> getAffectedVcses() {
    if (! myShowVcsCommit) {
      return Collections.emptySet();
    }
    return myBrowserExtender.getAffectedVcses();
  }

  private static Collection<AbstractVcs> getAffectedVcses(Project project, final Collection<Change> changes) {
    Set<AbstractVcs> result = new THashSet<AbstractVcs>();
    for (Change change : changes) {
      ContainerUtilRt.addIfNotNull(result, ChangesUtil.getVcsForChange(change, project));
    }
    return result;
  }

  @Override
  public Collection<VirtualFile> getRoots() {
    Set<VirtualFile> result = new HashSet<VirtualFile>();
    for (Change change : myBrowser.getCurrentDisplayedChanges()) {
      final FilePath filePath = ChangesUtil.getFilePath(change);
      VirtualFile root = ProjectLevelVcsManager.getInstance(myProject).getVcsRootFor(filePath);
      if (root != null) {
        result.add(root);
      }
    }
    return result;
  }

  @Override
  public JComponent getComponent() {
    return mySplitter;
  }

  @Override
  public boolean hasDiffs() {
    return !getIncludedChanges().isEmpty();
  }

  @Override
  public Collection<VirtualFile> getVirtualFiles() {
    List<VirtualFile> result = new ArrayList<VirtualFile>();
    for (Change change: getIncludedChanges()) {
      final FilePath path = ChangesUtil.getFilePath(change);
      final VirtualFile vFile = path.getVirtualFile();
      if (vFile != null) {
        result.add(vFile);
      }
    }

    return result;
  }

  @Override
  public Collection<Change> getSelectedChanges() {
    return new ArrayList<Change>(getIncludedChanges());
  }

  @Override
  public Collection<File> getFiles() {
    List<File> result = new ArrayList<File>();
    for (Change change: getIncludedChanges()) {
      final FilePath path = ChangesUtil.getFilePath(change);
      final File file = path.getIOFile();
      result.add(file);
    }

    return result;
  }

  @Override
  public Project getProject() {
    return myProject;
  }

  @Override
  public boolean vcsIsAffected(String name) {
    // tod +- performance?
    if (! ProjectLevelVcsManager.getInstance(myProject).checkVcsIsActive(name)) return false;
    final Collection<AbstractVcs> affected = myBrowserExtender.getAffectedVcses();
    for (AbstractVcs vcs : affected) {
      if (Comparing.equal(vcs.getName(), name)) return true;
    }
    return false;
  }

  @Override
  public void setCommitMessage(final String currentDescription) {
    setCommitMessageText(currentDescription);
    myCommitMessageArea.requestFocusInMessage();
  }

  public Object getContextInfo(Object object) {
    // todo
    return null;
  }

  @Override
  public void setWarning(String s) {
    // todo
  }

  private void setCommitMessageText(final String currentDescription) {
    myLastKnownComment = currentDescription;
    myCommitMessageArea.setText(currentDescription);
  }

  @Override
  public String getCommitMessage() {
    return myCommitMessageArea.getComment();
  }

  @Override
  public void refresh() {
    ChangeListManager.getInstance(myProject).invokeAfterUpdate(new Runnable() {
      @Override
      public void run() {
        myBrowser.rebuildList();
        for (RefreshableOnComponent component : myAdditionalComponents) {
          component.refresh();
        }
      }
    }, InvokeAfterUpdateMode.SILENT, "commit dialog", ModalityState.current());   // title not shown for silently
  }

  @Override
  public void saveState() {
    for (RefreshableOnComponent component : myAdditionalComponents) {
      component.saveState();
    }
  }

  @Override
  public void restoreState() {
    for (RefreshableOnComponent component : myAdditionalComponents) {
      component.restoreState();
    }
  }

  private void updateButtons() {
    if (myDisposed) return;
    final boolean enabled = hasDiffs();
    setOKActionEnabled(enabled);
    if (myCommitAction != null) {
      myCommitAction.setEnabled(enabled);
    }
    if (myExecutorActions != null) {
      for (CommitExecutorAction executorAction : myExecutorActions) {
        executorAction.updateEnabled(enabled);
      }
    }
    myOKButtonUpdateAlarm.cancelAllRequests();
    myOKButtonUpdateAlarm.addRequest(myUpdateButtonsRunnable, 300, ModalityState.stateForComponent(myBrowser));
  }

  private void updateLegend() {
    if (myDisposed) return;
    myChangesInfoCalculator.update(myBrowser.getCurrentDisplayedChanges(), myBrowserExtender.getCurrentIncludedChanges());
    myLegend.update();
  }

  @NotNull
  private List<Change> getIncludedChanges() {
    return myBrowserExtender.getCurrentIncludedChanges();
  }

  @Override
  @NonNls
  protected String getDimensionServiceKey() {
    return "CommitChangelistDialog" + LAYOUT_VERSION;
  }

  @Override
  public JComponent getPreferredFocusedComponent() {
    return myCommitMessageArea.getEditorField();
  }

  @Override
  public void calcData(DataKey key, DataSink sink) {
    if (key == Refreshable.PANEL_KEY) {
      sink.put(Refreshable.PANEL_KEY, this);
    }
    else {
      myBrowser.calcData(key, sink);
    }
  }

  static String trimEllipsis(final String title) {
    if (title.endsWith("...")) {
      return title.substring(0, title.length() - 3);
    }
    else {
      return title;
    }
  }

  private void ensureDataIsActual(final Runnable runnable) {
    ChangeListManager.getInstance(myProject).invokeAfterUpdate(runnable, InvokeAfterUpdateMode.SYNCHRONOUS_CANCELLABLE,
                                                               "Refreshing changelists...", ModalityState.current());
  }

  private class CommitExecutorAction extends AbstractAction {
    private final CommitExecutor myCommitExecutor;

    public CommitExecutorAction(final CommitExecutor commitExecutor, final boolean isDefault) {
      super(commitExecutor.getActionText());
      myCommitExecutor = commitExecutor;
      if (isDefault) {
        putValue(DEFAULT_ACTION, Boolean.TRUE);
      }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
      final Runnable callExecutor = new Runnable() {
        @Override
        public void run() {
          execute(myCommitExecutor);
        }
      };
      if (myBrowser.isDataIsDirty()) {
        ensureDataIsActual(callExecutor);
      } else {
        callExecutor.run();
      }
    }

    public void updateEnabled(boolean hasDiffs) {
      setEnabled(hasDiffs
                 || (myCommitExecutor instanceof CommitExecutorBase) && !((CommitExecutorBase)myCommitExecutor).areChangesRequired());
    }
  }

  private static class DiffCommitMessageEditor extends CommitMessage implements Disposable {
    private CommitChangeListDialog myCommitDialog;

    public DiffCommitMessageEditor(final CommitChangeListDialog dialog) {
      super(dialog.getProject());
      getEditorField().setText(dialog.getCommitMessage());
      myCommitDialog = dialog;
      myCommitDialog.setMessageConsumer(new Consumer<String>() {
        @Override
        public void consume(String s) {
          getEditorField().setText(s);
        }
      });
    }

    @Override
    public void dispose() {
      if (myCommitDialog != null) {
        myCommitDialog.setMessageConsumer(null);
        final String text = getEditorField().getText();
        if (! Comparing.equal(myCommitDialog.getCommitMessage(), text)) {
          myCommitDialog.setCommitMessage(text);
        }
        myCommitDialog = null;
      }
    }

    @Override
    public Dimension getPreferredSize() {
      // we don't want to be squeezed to one line
      return new Dimension(400, 120);
    }
  }

  public void setMessageConsumer(Consumer<String> messageConsumer) {
    myCommitMessageArea.setMessageConsumer(messageConsumer);
  }
}
