/*
 * 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 org.jetbrains.idea.svn;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandAdapter;
import com.intellij.openapi.command.CommandEvent;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.actions.VcsContextFactory;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vfs.LocalFileOperationsHandler;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
import com.intellij.util.Processor;
import com.intellij.util.ThrowableConsumer;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcsUtil.ActionWithTempFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.api.NodeKind;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.jetbrains.idea.svn.info.Info;
import org.jetbrains.idea.svn.status.Status;
import org.jetbrains.idea.svn.status.StatusType;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.wc.SVNMoveClient;

import java.io.File;
import java.io.IOException;
import java.util.*;

public class SvnFileSystemListener extends CommandAdapter implements LocalFileOperationsHandler {
  private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnFileSystemListener");
  private final LocalFileSystem myLfs;

  private static class AddedFileInfo {
    private final VirtualFile myDir;
    private final String myName;
    @Nullable private final File myCopyFrom;
    private final boolean myRecursive;

    public AddedFileInfo(final VirtualFile dir, final String name, @Nullable final File copyFrom, boolean recursive) {
      myDir = dir;
      myName = name;
      myCopyFrom = copyFrom;
      myRecursive = recursive;
    }
  }

  private static class MovedFileInfo {
    private final Project myProject;
    private final File mySrc;
    private final File myDst;

    private MovedFileInfo(final Project project, final File src, final File dst) {
      myProject = project;
      mySrc = src;
      myDst = dst;
    }
  }

  private final MultiMap<Project, AddedFileInfo> myAddedFiles = new MultiMap<Project, AddedFileInfo>();
  private final MultiMap<Project, File> myDeletedFiles = new MultiMap<Project, File>();
  private final List<MovedFileInfo> myMovedFiles = new ArrayList<MovedFileInfo>();
  private final Map<Project, List<VcsException>> myMoveExceptions = new HashMap<Project, List<VcsException>>();
  private final List<VirtualFile> myFilesToRefresh = new ArrayList<VirtualFile>();
  @Nullable private File myStorageForUndo;
  private final List<Couple<File>> myUndoStorageContents = new ArrayList<Couple<File>>();
  private boolean myUndoingMove = false;

  public SvnFileSystemListener() {
    myLfs = LocalFileSystem.getInstance();
  }

  private void addToMoveExceptions(@NotNull final Project project, @NotNull final Exception e) {
    List<VcsException> exceptionList = myMoveExceptions.get(project);
    if (exceptionList == null) {
      exceptionList = new ArrayList<VcsException>();
      myMoveExceptions.put(project, exceptionList);
    }
    exceptionList.add(handleMoveException(e));
  }

  private VcsException handleMoveException(@NotNull Exception e) {
    VcsException vcsException;
    if (e instanceof SVNException && SVNErrorCode.ENTRY_EXISTS.equals(((SVNException)e).getErrorMessage().getErrorCode())) {
      vcsException = createMoveTargetExistsError(e);
    }
    else if (e instanceof SvnBindException && ((SvnBindException)e).contains(SVNErrorCode.ENTRY_EXISTS)) {
      vcsException = createMoveTargetExistsError(e);
    }
    else if (e instanceof VcsException) {
      vcsException = (VcsException)e;
    }
    else {
      vcsException = new VcsException(e);
    }
    return vcsException;
  }

  private static VcsException createMoveTargetExistsError(@NotNull Exception e) {
    return new VcsException(Arrays.asList("Target of move operation is already under version control.",
                                          "Subversion move had not been performed. ", e.getMessage()));
  }

  @Nullable
  public File copy(final VirtualFile file, final VirtualFile toDir, final String copyName) throws IOException {
    SvnVcs vcs = getVCS(toDir);
    if (vcs == null) {
      vcs = getVCS(file);
    }
    if (vcs == null) {
      return null;
    }

    File srcFile = new File(file.getPath());
    File destFile = new File(new File(toDir.getPath()), copyName);
    final boolean dstDirUnderControl = SvnUtil.isSvnVersioned(vcs.getProject(), destFile.getParentFile());
    if (! dstDirUnderControl && !isPendingAdd(vcs.getProject(), toDir)) {
      return null;
    }

    if (! SvnUtil.isSvnVersioned(vcs.getProject(), srcFile.getParentFile())) {
      myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(toDir, copyName, null, false));
      return null;
    }

    final Status fileStatus = getFileStatus(vcs, srcFile);
    if (fileStatus != null && fileStatus.is(StatusType.STATUS_ADDED)) {
      myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(toDir, copyName, null, false));
      return null;
    }

    if (sameRoot(vcs, file.getParent(), toDir)) {
      myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(toDir, copyName, srcFile, false));
      return null;
    }

    myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(toDir, copyName, null, false));
    return null;
  }

  private boolean sameRoot(final SvnVcs vcs, final VirtualFile srcDir, final VirtualFile dstDir) {
    final UUIDHelper helper = new UUIDHelper(vcs);
    final String srcUUID = helper.getRepositoryUUID(vcs.getProject(), srcDir);
    final String dstUUID = helper.getRepositoryUUID(vcs.getProject(), dstDir);

    return srcUUID != null && dstUUID != null && srcUUID.equals(dstUUID);
  }

  private class UUIDHelper {
    private final SvnVcs myVcs;

    private UUIDHelper(final SvnVcs vcs) {
      myVcs = vcs;
    }

    /**
     * passed dir must be under VC control (it is assumed)
     */
    @Nullable
    public String getRepositoryUUID(final Project project, final VirtualFile dir) {
      try {
        final Info info1 = new RepeatSvnActionThroughBusy() {
          @Override
          protected void executeImpl() {
            myT = myVcs.getInfo(new File(dir.getPath()));
          }
        }.compute();
        if (info1 == null || info1.getRepositoryUUID() == null) {
          // go deeper if current parent was added (if parent was added, it theoretically could NOT know its repo UUID)
          final VirtualFile parent = dir.getParent();
          if (parent == null) {
            return null;
          }
          if (isPendingAdd(project, parent)) {
            return getRepositoryUUID(project, parent);
          }
        } else {
          return info1.getRepositoryUUID();
        }
      }
      catch (VcsException e) {
        // go to return default
      }
      return null;
    }
  }

  public boolean move(VirtualFile file, VirtualFile toDir) throws IOException {
    File srcFile = getIOFile(file);
    File dstFile = new File(getIOFile(toDir), file.getName());

    final SvnVcs vcs = getVCS(toDir);
    final SvnVcs sourceVcs = getVCS(file);
    if (vcs == null && sourceVcs == null) return false;

    if (vcs == null) {
      return false;
    }

    FileDocumentManager.getInstance().saveAllDocuments();
    if (sourceVcs == null) {
      return createItem(toDir, file.getName(), file.isDirectory(), true);
    }

    if (isPendingAdd(vcs.getProject(), toDir)) {

      myMovedFiles.add(new MovedFileInfo(sourceVcs.getProject(), srcFile, dstFile));
      return true; 
    }
    else {
      final VirtualFile oldParent = file.getParent();
      myFilesToRefresh.add(oldParent);
      myFilesToRefresh.add(toDir);
      return doMove(sourceVcs, srcFile, dstFile);
    }
  }

  public boolean rename(VirtualFile file, String newName) throws IOException {
    File srcFile = getIOFile(file);
    File dstFile = new File(srcFile.getParentFile(), newName);
    SvnVcs vcs = getVCS(file);
    if (vcs != null) {
      FileDocumentManager.getInstance().saveAllDocuments();

      myFilesToRefresh.add(file.getParent());
      return doMove(vcs, srcFile, dstFile);
    }
    return false;
  }

  private boolean doMove(@NotNull SvnVcs vcs, final File src, final File dst) {
    long srcTime = src.lastModified();
    try {
      final boolean isUndo = isUndo(vcs);
      final String list = isUndo ? null : SvnChangelistListener.getCurrentMapping(vcs, src);

      WorkingCopyFormat format = vcs.getWorkingCopyFormat(src);
      final boolean is17OrLater = format.isOrGreater(WorkingCopyFormat.ONE_DOT_SEVEN);
      if (is17OrLater) {
        Status srcStatus = getFileStatus(vcs, src);
        final File toDir = dst.getParentFile();
        Status dstStatus = getFileStatus(vcs, toDir);
        final boolean srcUnversioned = srcStatus == null || srcStatus.is(StatusType.STATUS_UNVERSIONED);
        if (srcUnversioned && (dstStatus == null || dstStatus.is(StatusType.STATUS_UNVERSIONED))) {
          return false;
        }
        if (srcUnversioned) {
          Status dstWasStatus = getFileStatus(vcs, dst);
          if (dstWasStatus == null || dstWasStatus.is(StatusType.STATUS_UNVERSIONED)) {
            return false;
          }
        }
        if (for17move(vcs, src, dst, isUndo, srcStatus)) return false;
      } else {
        if (for16move(vcs, src, dst, isUndo)) return false;
      }

      if (! isUndo && list != null) {
        SvnChangelistListener.putUnderList(vcs.getProject(), list, dst);
      }
      dst.setLastModified(srcTime);
    }
    catch(VcsException e) {
      addToMoveExceptions(vcs.getProject(), e);
      return false;
    }
    return true;
  }

  private final static Set<StatusType> ourStatusesForUndoMove = new HashSet<StatusType>();
  static {
    ourStatusesForUndoMove.add(StatusType.STATUS_ADDED);
  }

  private boolean for17move(final SvnVcs vcs, final File src, final File dst, boolean undo, Status srcStatus) throws VcsException {
    if (srcStatus != null && srcStatus.getCopyFromURL() == null) {
      undo = false;
    }
    if (undo) {
      myUndoingMove = true;
      createRevertAction(vcs, dst, true).execute();
      copyUnversionedMembersOfDirectory(src, dst);
      if (srcStatus == null || srcStatus.is(StatusType.STATUS_UNVERSIONED)) {
        FileUtil.delete(src);
      } else {
        createRevertAction(vcs, src, true).execute();
      }
      restoreFromUndoStorage(dst);
    } else {
      if (doUsualMove(vcs, src)) return true;
      // check destination directory
      final Status dstParentStatus = getFileStatus(vcs, dst.getParentFile());
      if (dstParentStatus == null || dstParentStatus.is(StatusType.STATUS_UNVERSIONED)) {
        try {
          copyFileOrDir(src, dst);
        }
        catch (IOException e) {
          throw new SvnBindException(e);
        }
        createDeleteAction(vcs, src, true).execute();
        return false;
      }
      moveFileWithSvn(vcs, src, dst);
    }
    return false;
  }

  public static void moveFileWithSvn(final SvnVcs vcs, final File src, final File dst) throws VcsException {
    new RepeatSvnActionThroughBusy() {
      @Override
      protected void executeImpl() throws VcsException {
        vcs.getFactory(src).createCopyMoveClient().copy(src, dst, false, true);
      }
    }.execute();
  }

  private void copyUnversionedMembersOfDirectory(final File src, final File dst) throws SvnBindException {
    if (src.isDirectory()) {
      final SvnBindException[] exc = new SvnBindException[1];
      FileUtil.processFilesRecursively(src, new Processor<File>() {
        @Override
        public boolean process(File file) {
          String relativePath = FileUtil.getRelativePath(src, file);
          File newFile = new File(dst, relativePath);
          if (!newFile.exists()) {
            try {
              copyFileOrDir(src, dst);
            }
            catch (IOException e) {
              exc[0] = new SvnBindException(e);
              return false;
            }
          }
          return true;
        }
      });
      if (exc[0] != null) {
        throw exc[0];
      }
    }
  }

  private void copyFileOrDir(File src, File dst) throws IOException {
    if (src.isDirectory()) {
      FileUtil.copyDir(src, dst);
    } else {
      FileUtil.copy(src, dst);
    }
  }

  private boolean doUsualMove(SvnVcs vcs, File src) {
    // if src is not under version control, do usual move.
    Status srcStatus = getFileStatus(vcs, src);
    return srcStatus == null ||
           srcStatus.is(StatusType.STATUS_UNVERSIONED, StatusType.STATUS_OBSTRUCTED, StatusType.STATUS_MISSING, StatusType.STATUS_EXTERNAL);
  }

  private boolean for16move(SvnVcs vcs, final File src, final File dst, boolean undo) throws VcsException {
    final SVNMoveClient mover = vcs.getSvnKitManager().createMoveClient();
    if (undo) {
      myUndoingMove = true;
      restoreFromUndoStorage(dst);
      new RepeatSvnActionThroughBusy() {
        @Override
        protected void executeImpl() throws VcsException {
          try {
            mover.undoMove(src, dst);
          }
          catch (SVNException e) {
            throw new SvnBindException(e);
          }
        }
      }.execute();
    }
    else {
      // if src is not under version control, do usual move.
      if (doUsualMove(vcs, src)) return true;
      new RepeatSvnActionThroughBusy() {
        @Override
        protected void executeImpl() throws VcsException {
          try {
            mover.doMove(src, dst);
          }
          catch (SVNException e) {
            throw new SvnBindException(e);
          }
        }
      }.execute();
    }
    return false;
  }

  private void restoreFromUndoStorage(final File dst) {
    String normPath = FileUtil.toSystemIndependentName(dst.getPath());
    for (Iterator<Couple<File>> it = myUndoStorageContents.iterator(); it.hasNext();) {
      Couple<File> e = it.next();
      final String p = FileUtil.toSystemIndependentName(e.first.getPath());
      if (p.startsWith(normPath)) {
        try {
          FileUtil.rename(e.second, e.first);
        }
        catch (IOException ex) {
          LOG.error(ex);
          FileUtil.asyncDelete(e.second);
        }
        it.remove();
      }
    }
    if (myStorageForUndo != null) {
      final File[] files = myStorageForUndo.listFiles();
      if (files == null || files.length == 0) {
        FileUtil.asyncDelete(myStorageForUndo);
        myStorageForUndo = null;
      }
    }
  }


  public boolean createFile(VirtualFile dir, String name) throws IOException {
    return createItem(dir, name, false, false);
  }

  public boolean createDirectory(VirtualFile dir, String name) throws IOException {
    return createItem(dir, name, true, false);
  }

  /**
   * delete file or directory (both 'undo' and 'do' modes)
   * unversioned: do nothing, return false
   * obstructed: do nothing, return false
   * external or wc root: do nothing, return false
   * missing: do nothing, return false
   * <p/>
   * versioned: schedule for deletion, return true
   * added: schedule for deletion (make unversioned), return true
   * copied, but not scheduled: schedule for deletion, return true
   * replaced: schedule for deletion, return true
   * <p/>
   * deleted: do nothing, return true (strange)
   */
  public boolean delete(VirtualFile file) throws IOException {
    final SvnVcs vcs = getVCS(file);
    if (vcs != null && SvnUtil.isAdminDirectory(file)) {
      return true;
    }
    if (vcs == null) return false;
    final VcsShowConfirmationOption.Value value = vcs.getDeleteConfirmation().getValue();
    if (VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY.equals(value)) return false;

    final File ioFile = getIOFile(file);
    if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioFile.getParentFile())) {
      return false;
    }
    if (SvnUtil.isWorkingCopyRoot(ioFile)) {
      return false;
    }

    Status status = getFileStatus(vcs, ioFile);

    if (status == null ||
        status.is(StatusType.STATUS_UNVERSIONED, StatusType.STATUS_OBSTRUCTED, StatusType.STATUS_MISSING, StatusType.STATUS_EXTERNAL,
                  StatusType.STATUS_IGNORED)) {
      return false;
    }
    else if (status.is(StatusType.STATUS_DELETED)) {
      if (isUndo(vcs)) {
        moveToUndoStorage(file);
      }
      return true;
    }
    else {
      if (vcs != null) {
        if (isAboveSourceOfCopyOrMove(vcs.getProject(), ioFile)) {
          myDeletedFiles.putValue(vcs.getProject(), ioFile);
          return true;
        }
        if (status.is(StatusType.STATUS_ADDED)) {
          try {
            createRevertAction(vcs, ioFile, false).execute();
          }
          catch (VcsException e) {
            // ignore
          }
        }
        else {
          myDeletedFiles.putValue(vcs.getProject(), ioFile);
          // packages deleted from disk should not be deleted from svn (IDEADEV-16066)
          if (file.isDirectory() || isUndo(vcs)) return true;
        }
      }
      return false;
    }
  }

  @NotNull
  private RepeatSvnActionThroughBusy createRevertAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean recursive) {
    return new RepeatSvnActionThroughBusy() {
      @Override
      protected void executeImpl() throws VcsException {
        vcs.getFactory(file).createRevertClient().revert(new File[]{file}, Depth.allOrFiles(recursive), null);
      }
    };
  }

  @NotNull
  private RepeatSvnActionThroughBusy createDeleteAction(@NotNull final SvnVcs vcs, @NotNull final File file, final boolean force) {
    return new RepeatSvnActionThroughBusy() {
      @Override
      protected void executeImpl() throws VcsException {
        vcs.getFactory(file).createDeleteClient().delete(file, force, false, null);
      }
    };
  }

  private boolean isAboveSourceOfCopyOrMove(final Project p, File ioFile) {
    for (MovedFileInfo file : myMovedFiles) {
      if (FileUtil.isAncestor(ioFile, file.mySrc, false)) return true;
    }
    for (AddedFileInfo info : myAddedFiles.get(p)) {
      if (info.myCopyFrom != null && FileUtil.isAncestor(ioFile, info.myCopyFrom, false)) return true;
    }
    return false;
  }

  private void moveToUndoStorage(final VirtualFile file) {
    if (myStorageForUndo == null) {
      try {
        myStorageForUndo = FileUtil.createTempDirectory("svnUndoStorage", "");
      }
      catch (IOException e) {
        LOG.error(e);
        return; 
      }
    }
    final File tmpFile = FileUtil.findSequentNonexistentFile(myStorageForUndo, "tmp", "");
    myUndoStorageContents.add(0, Couple.of(new File(file.getPath()), tmpFile));
    new File(file.getPath()).renameTo(tmpFile);
  }

  /**
   * add file or directory:
   * <p/>
   * parent directory is:
   * unversioned: do nothing, return false
   * versioned:
   * entry is:
   * null: create entry, schedule for addition
   * missing: do nothing, return false
   * deleted, 'do' mode: try to create entry and it schedule for addition if kind is the same, otherwise do nothing, return false.
   * deleted: 'undo' mode: try to revert non-recursively, if kind is the same, otherwise do nothing, return false.
   * anything else: return false.
   */
  private boolean createItem(VirtualFile dir, String name, boolean directory, final boolean recursive) {
    SvnVcs vcs = getVCS(dir);
    if (vcs == null) {
      return false;
    }
    final VcsShowConfirmationOption.Value value = vcs.getAddConfirmation().getValue();
    if (VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY.equals(value)) return false;

    if (isUndo(vcs) && SvnUtil.isAdminDirectory(dir, name)) {
      return false;      
    }
    File ioDir = getIOFile(dir);
    boolean pendingAdd = isPendingAdd(vcs.getProject(), dir);
    if (! SvnUtil.isSvnVersioned(vcs.getProject(), ioDir) && ! pendingAdd) {
      return false;
    }
    final File targetFile = new File(ioDir, name);
    Status status = getFileStatus(vcs, targetFile);

    if (status == null || status.getContentsStatus() == StatusType.STATUS_NONE ||
        status.getContentsStatus() == StatusType.STATUS_UNVERSIONED) {
      myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(dir, name, null, recursive));
      return false;
    }
    else if (status.is(StatusType.STATUS_MISSING)) {
      return false;
    }
    else if (status.is(StatusType.STATUS_DELETED)) {
      NodeKind kind = status.getKind();
      // kind differs.
      if (directory && !kind.isDirectory() || !directory && !kind.isFile()) {
        return false;
      }
      try {
        if (isUndo(vcs)) {
          createRevertAction(vcs, targetFile, false).execute();
          return true;
        }
        myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(dir, name, null, recursive));
        return false;
      }
      catch (VcsException e) {
        SVNFileUtil.deleteAll(targetFile, true);
        return false;
      }
    }
    return false;
  }

  private boolean isPendingAdd(final Project project, final VirtualFile dir) {
    final Collection<AddedFileInfo> addedFileInfos = myAddedFiles.get(project);
    for(AddedFileInfo i: addedFileInfos) {
      if (Comparing.equal(i.myDir, dir.getParent()) && i.myName.equals(dir.getName())) {
        return true;
      }
    }
    return false;
  }

  public void commandStarted(CommandEvent event) {
    myUndoingMove = false;
    final Project project = event.getProject();
    if (project == null) return;
    commandStarted(project);
  }

  void commandStarted(final Project project) {
    myUndoingMove = false;
    myMoveExceptions.remove(project);
  }

  public void commandFinished(CommandEvent event) {
    final Project project = event.getProject();
    if (project == null) return;
    commandFinished(project);
  }

  void commandFinished(final Project project) {
    checkOverwrites(project);
    if (myAddedFiles.containsKey(project)) {
      processAddedFiles(project);
    }
    processMovedFiles(project);
    if (myDeletedFiles.containsKey(project)) {
      processDeletedFiles(project);
    }

    final List<VcsException> exceptionList = myMoveExceptions.get(project);
    if (exceptionList != null && ! exceptionList.isEmpty()) {
      AbstractVcsHelper.getInstance(project).showErrors(exceptionList, SvnBundle.message("move.files.errors.title"));
    }

    if (!myFilesToRefresh.isEmpty()) {
      refreshFiles(project);
    }
  }

  private void checkOverwrites(final Project project) {
    final Collection<AddedFileInfo> addedFileInfos = myAddedFiles.get(project);
    final Collection<File> deletedFiles = myDeletedFiles.get(project);
    if (addedFileInfos.isEmpty() || deletedFiles.isEmpty()) return;
    final Iterator<AddedFileInfo> iterator = addedFileInfos.iterator();
    while (iterator.hasNext()) {
      AddedFileInfo addedFileInfo = iterator.next();
      final File ioFile = new File(addedFileInfo.myDir.getPath(), addedFileInfo.myName);
      if (deletedFiles.remove(ioFile)) {
        iterator.remove();
      }
    }
  }

  private void refreshFiles(final Project project) {
    final List<VirtualFile> toRefreshFiles = new ArrayList<VirtualFile>();
    final List<VirtualFile> toRefreshDirs = new ArrayList<VirtualFile>();
    for (VirtualFile file : myFilesToRefresh) {
      if (file == null) continue;
      if (file.isDirectory()) {
        toRefreshDirs.add(file);
      } else {
        toRefreshFiles.add(file);
      }
    }
    // if refresh asynchronously, local changes would also be notified that they are dirty asynchronously,
    // and commit could be executed while not all changes are visible
    filterOutInvalid(myFilesToRefresh);
    RefreshQueue.getInstance().refresh(true, true, new Runnable() {
      public void run() {
        if (project.isDisposed()) return;
        filterOutInvalid(toRefreshFiles);
        filterOutInvalid(toRefreshDirs);

        final VcsDirtyScopeManager vcsDirtyScopeManager = VcsDirtyScopeManager.getInstance(project);
        vcsDirtyScopeManager.filesDirty(toRefreshFiles, toRefreshDirs);
      }
    }, myFilesToRefresh);
    myFilesToRefresh.clear();
  }

  private static void filterOutInvalid(final Collection<VirtualFile> files) {
    for (Iterator<VirtualFile> iterator = files.iterator(); iterator.hasNext();) {
      final VirtualFile file = iterator.next();
      if (! file.isValid() || ! file.exists()) {
        LOG.info("Refresh root is not valid: " + file.getPath());
        iterator.remove();
      }
    }
  }

  private void processAddedFiles(Project project) {
    SvnVcs vcs = SvnVcs.getInstance(project);
    List<VirtualFile> addedVFiles = new ArrayList<VirtualFile>();
    Map<VirtualFile, File> copyFromMap = new HashMap<VirtualFile, File>();
    final Set<VirtualFile> recursiveItems = new HashSet<VirtualFile>();
    fillAddedFiles(project, vcs, addedVFiles, copyFromMap, recursiveItems);
    if (addedVFiles.isEmpty()) return;
    final VcsShowConfirmationOption.Value value = vcs.getAddConfirmation().getValue();
    if (value != VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY) {
      final AbstractVcsHelper vcsHelper = AbstractVcsHelper.getInstance(project);
      final Collection<VirtualFile> filesToProcess = promptAboutAddition(vcs, addedVFiles, value, vcsHelper);
      if (filesToProcess != null && !filesToProcess.isEmpty()) {
        final List<VcsException> exceptions = new ArrayList<VcsException>();
        runInBackground(project, "Adding files to Subversion",
                        createAdditionRunnable(project, vcs, copyFromMap, filesToProcess, exceptions));
        if (!exceptions.isEmpty()) {
          vcsHelper.showErrors(exceptions, SvnBundle.message("add.files.errors.title"));
        }
      }
    }
  }

  private void runInBackground(final Project project, final String name, final Runnable runnable) {
    if (ApplicationManager.getApplication().isDispatchThread()) {
      ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, name, false, project);
    } else {
      runnable.run();
    }
  }

  private Runnable createAdditionRunnable(final Project project,
                               final SvnVcs vcs,
                               final Map<VirtualFile, File> copyFromMap,
                               final Collection<VirtualFile> filesToProcess,
                               final List<VcsException> exceptions) {
    return new Runnable() {
      @Override
      public void run() {
        for(VirtualFile file: filesToProcess) {
          final File ioFile = new File(file.getPath());
          try {
            final File copyFrom = copyFromMap.get(file);
            if (copyFrom != null) {
              try {
                new ActionWithTempFile(ioFile) {
                  protected void executeInternal() throws VcsException {
                    // not recursive
                    new RepeatSvnActionThroughBusy() {
                      @Override
                      protected void executeImpl() throws VcsException {
                        vcs.getFactory(copyFrom).createCopyMoveClient().copy(copyFrom, ioFile, true, false);
                      }
                    }.execute();
                  }
                }.execute();
              }
              catch (VcsException e) {
                exceptions.add(e);
              }
            }
            else {
              new RepeatSvnActionThroughBusy() {
                @Override
                protected void executeImpl() throws VcsException {
                  vcs.getFactory(ioFile).createAddClient().add(ioFile, null, false, false, true, null);
                }
              }.execute();
            }
            VcsDirtyScopeManager.getInstance(project).fileDirty(file);
          }
          catch (VcsException e) {
            exceptions.add(e);
          }
        }
      }
    };
  }

  private Collection<VirtualFile> promptAboutAddition(SvnVcs vcs,
                                                      List<VirtualFile> addedVFiles,
                                                      VcsShowConfirmationOption.Value value,
                                                      AbstractVcsHelper vcsHelper) {
    Collection<VirtualFile> filesToProcess;
    if (value == VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY) {
      filesToProcess = addedVFiles;
    }
    else {
      final String singleFilePrompt;
      if (addedVFiles.size() == 1 && addedVFiles.get(0).isDirectory()) {
        singleFilePrompt = SvnBundle.getString("confirmation.text.add.dir");
      }
      else {
        singleFilePrompt = SvnBundle.getString("confirmation.text.add.file");
      }
      filesToProcess = vcsHelper.selectFilesToProcess(addedVFiles, SvnBundle.message("confirmation.title.add.multiple.files"),
                                                      null,
                                                      SvnBundle.message("confirmation.title.add.file"), singleFilePrompt,
                                                      vcs.getAddConfirmation());
    }
    return filesToProcess;
  }

  private void fillAddedFiles(Project project,
                              SvnVcs vcs,
                              List<VirtualFile> addedVFiles,
                              Map<VirtualFile, File> copyFromMap,
                              Set<VirtualFile> recursiveItems) {
    final Collection<AddedFileInfo> addedFileInfos = myAddedFiles.remove(project);
    final ChangeListManager changeListManager = ChangeListManager.getInstance(project);

    for (AddedFileInfo addedFileInfo : addedFileInfos) {
      final File ioFile = new File(getIOFile(addedFileInfo.myDir), addedFileInfo.myName);
      VirtualFile addedFile = addedFileInfo.myDir.findChild(addedFileInfo.myName);
      if (addedFile == null) {
        addedFile = myLfs.refreshAndFindFileByIoFile(ioFile);
      }
      if (addedFile != null) {
        final Status fileStatus = getFileStatus(vcs, ioFile);
        if (fileStatus == null || !fileStatus.is(StatusType.STATUS_IGNORED)) {
          boolean isIgnored = changeListManager.isIgnoredFile(addedFile);
          if (!isIgnored) {
            addedVFiles.add(addedFile);
            copyFromMap.put(addedFile, addedFileInfo.myCopyFrom);
            if (addedFileInfo.myRecursive) {
              recursiveItems.add(addedFile);
            }
          }
        }
      }
    }
  }

  private void processDeletedFiles(Project project) {
    final List<Pair<FilePath, WorkingCopyFormat>> deletedFiles = new ArrayList<Pair<FilePath, WorkingCopyFormat>>();
    final Collection<FilePath> filesToProcess = new ArrayList<FilePath>();
    List<VcsException> exceptions = new ArrayList<VcsException>();
    final AbstractVcsHelper vcsHelper = AbstractVcsHelper.getInstance(project);

    try {
      fillDeletedFiles(project, deletedFiles, filesToProcess);
      if (deletedFiles.isEmpty() && filesToProcess.isEmpty() || myUndoingMove) return;
      SvnVcs vcs = SvnVcs.getInstance(project);
      final VcsShowConfirmationOption.Value value = vcs.getDeleteConfirmation().getValue();
      if (value != VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY) {
        if (! deletedFiles.isEmpty()) {
          final Collection<FilePath> confirmed = promptAboutDeletion(deletedFiles, vcs, value, vcsHelper);
          if (confirmed != null) {
            filesToProcess.addAll(confirmed);
          }
        }
        if (filesToProcess != null && ! filesToProcess.isEmpty()) {
          runInBackground(project, "Deleting files from Subversion", createDeleteRunnable(project, vcs, filesToProcess, exceptions));
        }
        final List<FilePath> deletedFilesFiles = ObjectsConvertor.convert(deletedFiles, new Convertor<Pair<FilePath, WorkingCopyFormat>, FilePath>() {
          @Override
          public FilePath convert(Pair<FilePath, WorkingCopyFormat> o) {
            return o.getFirst();
          }
        });
        for (FilePath file : deletedFilesFiles) {
          final FilePath parent = file.getParentPath();
          if (parent != null) {
            myFilesToRefresh.add(parent.getVirtualFile());
          }
        }
        if (filesToProcess != null) {
          deletedFilesFiles.removeAll(filesToProcess);
        }
        for (FilePath file : deletedFilesFiles) {
          FileUtil.delete(file.getIOFile());
        }
      }
    } catch (VcsException e) {
      exceptions.add(e);
    }
    if (! exceptions.isEmpty()) {
      vcsHelper.showErrors(exceptions, SvnBundle.message("delete.files.errors.title"));
    }
  }

  private Runnable createDeleteRunnable(final Project project,
                                        final SvnVcs vcs,
                                        final Collection<FilePath> filesToProcess,
                                        final List<VcsException> exceptions) {
    return new Runnable() {
      public void run() {
        for(FilePath file: filesToProcess) {
          VirtualFile vFile = file.getVirtualFile();  // for deleted directories
          final File ioFile = new File(file.getPath());
          try {
            createDeleteAction(vcs, ioFile, true).execute();
            if (vFile != null && vFile.isValid() && vFile.isDirectory()) {
              vFile.refresh(true, true);
              VcsDirtyScopeManager.getInstance(project).dirDirtyRecursively(vFile);
            }
            else {
              VcsDirtyScopeManager.getInstance(project).fileDirty(file);
            }
          }
          catch (VcsException e) {
            exceptions.add(e);
          }
        }
      }
    };
  }

  private Collection<FilePath> promptAboutDeletion(List<Pair<FilePath, WorkingCopyFormat>> deletedFiles,
                                                   SvnVcs vcs,
                                                   VcsShowConfirmationOption.Value value,
                                                   AbstractVcsHelper vcsHelper) {
    final Convertor<Pair<FilePath, WorkingCopyFormat>, FilePath> convertor =
      new Convertor<Pair<FilePath, WorkingCopyFormat>, FilePath>() {
        @Override
        public FilePath convert(Pair<FilePath, WorkingCopyFormat> o) {
          return o.getFirst();
        }
      };
    Collection<FilePath> filesToProcess;
    if (value == VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY) {
      filesToProcess = ObjectsConvertor.convert(deletedFiles, convertor);
    } else {

      final String singleFilePrompt;
      if (deletedFiles.size() == 1 && deletedFiles.get(0).getFirst().isDirectory()) {
        singleFilePrompt = deletedFiles.get(0).getSecond().isOrGreater(WorkingCopyFormat.ONE_DOT_SEVEN) ?
                           SvnBundle.getString("confirmation.text.delete.dir.17") :
                           SvnBundle.getString("confirmation.text.delete.dir");
      }
      else {
        singleFilePrompt = SvnBundle.getString("confirmation.text.delete.file");
      }
      final Collection<FilePath> files = vcsHelper
        .selectFilePathsToProcess(ObjectsConvertor.convert(deletedFiles, convertor), SvnBundle.message("confirmation.title.delete.multiple.files"), null,
                                  SvnBundle.message("confirmation.title.delete.file"), singleFilePrompt, vcs.getDeleteConfirmation());
      filesToProcess = files == null ? null : new ArrayList<FilePath>(files);
    }
    return filesToProcess;
  }

  private void fillDeletedFiles(Project project, List<Pair<FilePath, WorkingCopyFormat>> deletedFiles, Collection<FilePath> deleteAnyway)
    throws VcsException {
    final SvnVcs vcs = SvnVcs.getInstance(project);
    final Collection<File> files = myDeletedFiles.remove(project);
    for (final File file : files) {
      final Status status = new RepeatSvnActionThroughBusy() {
        @Override
        protected void executeImpl() throws VcsException {
          myT = vcs.getFactory(file).createStatusClient().doStatus(file, false);
        }
      }.compute();
      boolean isAdded = StatusType.STATUS_ADDED.equals(status.getNodeStatus());
      final FilePath filePath = VcsContextFactory.SERVICE.getInstance().createFilePathOn(file);
      if (isAdded) {
        deleteAnyway.add(filePath);
      } else {
        deletedFiles.add(Pair.create(filePath, vcs.getWorkingCopyFormat(file)));
      }
    }
  }

  private void processMovedFiles(final Project project) {
    if (myMovedFiles.isEmpty()) return;

    final Runnable runnable = new Runnable() {
      public void run() {
        for (Iterator<MovedFileInfo> iterator = myMovedFiles.iterator(); iterator.hasNext();) {
          MovedFileInfo movedFileInfo = iterator.next();
          if (movedFileInfo.myProject == project) {
            doMove(SvnVcs.getInstance(project), movedFileInfo.mySrc, movedFileInfo.myDst);
            iterator.remove();
          }
        }
      }
    };
    runInBackground(project, "Moving files in Subversion", runnable);
  }

  @Nullable
  private static SvnVcs getVCS(VirtualFile file) {
    Project[] projects = ProjectManager.getInstance().getOpenProjects();
    for (Project project : projects) {
      AbstractVcs vcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(file);
      if (vcs instanceof SvnVcs) {
        return (SvnVcs)vcs;
      }
    }
    return null;
  }


  private static File getIOFile(VirtualFile vf) {
    return new File(vf.getPath()).getAbsoluteFile();
  }

  @Nullable
  private static Status getFileStatus(@NotNull final SvnVcs vcs, @NotNull final File file) {
    try {
      return new RepeatSvnActionThroughBusy() {
        @Override
        protected void executeImpl() throws VcsException {
          myT = vcs.getFactory(file).createStatusClient().doStatus(file, false);
        }
      }.compute();
    }
    catch (VcsException e) {
      return null;
    }
  }

  private static boolean isUndoOrRedo(@NotNull final Project project) {
    final UndoManager undoManager = UndoManager.getInstance(project);
    return undoManager.isUndoInProgress() || undoManager.isRedoInProgress();
  }

  private static boolean isUndo(SvnVcs vcs) {
    if (vcs == null || vcs.getProject() == null) {
      return false;
    }
    Project p = vcs.getProject();
    return UndoManager.getInstance(p).isUndoInProgress();
  }

  public void afterDone(final ThrowableConsumer<LocalFileOperationsHandler, IOException> invoker) {
  }
}
