/*
 * Copyright 2000-2013 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.ide.FrameStateListener;
import com.intellij.ide.FrameStateManager;
import com.intellij.idea.RareLogger;
import com.intellij.notification.*;
import com.intellij.notification.impl.NotificationsConfigurationImpl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.util.PopupUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.annotate.AnnotationProvider;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.checkin.CheckinEnvironment;
import com.intellij.openapi.vcs.diff.DiffProvider;
import com.intellij.openapi.vcs.history.VcsHistoryProvider;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.merge.MergeProvider;
import com.intellij.openapi.vcs.rollback.RollbackEnvironment;
import com.intellij.openapi.vcs.update.UpdateEnvironment;
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.Consumer;
import com.intellij.util.Processor;
import com.intellij.util.ThreeState;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.SoftHashMap;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.messages.Topic;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.actions.CleanupWorker;
import org.jetbrains.idea.svn.actions.ShowPropertiesDiffWithLocalAction;
import org.jetbrains.idea.svn.actions.SvnMergeProvider;
import org.jetbrains.idea.svn.annotate.SvnAnnotationProvider;
import org.jetbrains.idea.svn.api.ClientFactory;
import org.jetbrains.idea.svn.api.CmdClientFactory;
import org.jetbrains.idea.svn.api.SvnKitClientFactory;
import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment;
import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
import org.jetbrains.idea.svn.commandLine.SvnExecutableChecker;
import org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator;
import org.jetbrains.idea.svn.dialogs.WCInfo;
import org.jetbrains.idea.svn.history.LoadedRevisionsCache;
import org.jetbrains.idea.svn.history.SvnChangeList;
import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider;
import org.jetbrains.idea.svn.history.SvnHistoryProvider;
import org.jetbrains.idea.svn.lowLevel.PrimitivePool;
import org.jetbrains.idea.svn.networking.SSLProtocolExceptionParser;
import org.jetbrains.idea.svn.portable.SvnWcClientI;
import org.jetbrains.idea.svn.properties.PropertyClient;
import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment;
import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment;
import org.jetbrains.idea.svn.update.SvnUpdateEnvironment;
import org.tmatesoft.sqljet.core.SqlJetErrorCode;
import org.tmatesoft.sqljet.core.SqlJetException;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.internal.util.SVNSSLUtil;
import org.tmatesoft.svn.core.internal.util.jna.SVNJNAUtil;
import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil;
import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminArea14;
import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.*;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import org.tmatesoft.svn.util.SVNDebugLog;
import org.tmatesoft.svn.util.SVNDebugLogAdapter;
import org.tmatesoft.svn.util.SVNLogType;

import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLProtocolException;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.security.cert.CertificateException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

@SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
public class SvnVcs extends AbstractVcs<CommittedChangeList> {
  private static final String DO_NOT_LISTEN_TO_WC_DB = "svn.do.not.listen.to.wc.db";
  private static final String KEEP_CONNECTIONS_KEY = "svn.keep.connections";
  private static final Logger REFRESH_LOG = Logger.getInstance("#svn_refresh");
  public static boolean ourListenToWcDb = true;

  private static final int ourLogUsualInterval = 20 * 1000;
  private static final int ourLogRareInterval = 30 * 1000;

  private static final Set<SVNErrorCode> ourLogRarely = new HashSet<SVNErrorCode>(
    Arrays.asList(new SVNErrorCode[]{SVNErrorCode.WC_UNSUPPORTED_FORMAT, SVNErrorCode.WC_CORRUPT, SVNErrorCode.WC_CORRUPT_TEXT_BASE,
      SVNErrorCode.WC_NOT_FILE, SVNErrorCode.WC_NOT_DIRECTORY, SVNErrorCode.WC_PATH_NOT_FOUND}));

  private static final Logger LOG = wrapLogger(Logger.getInstance("org.jetbrains.idea.svn.SvnVcs"));
  @NonNls public static final String VCS_NAME = "svn";
  public static final String VCS_DISPLAY_NAME = "Subversion";

  private static final VcsKey ourKey = createKey(VCS_NAME);
  public static final Topic<Runnable> WC_CONVERTED = new Topic<Runnable>("WC_CONVERTED", Runnable.class);
  private final Map<String, Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>> myPropertyCache =
    new SoftHashMap<String, Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>>();

  private final SvnConfiguration myConfiguration;
  private final SvnEntriesFileListener myEntriesFileListener;

  private CheckinEnvironment myCheckinEnvironment;
  private RollbackEnvironment myRollbackEnvironment;
  private UpdateEnvironment mySvnUpdateEnvironment;
  private UpdateEnvironment mySvnIntegrateEnvironment;
  private VcsHistoryProvider mySvnHistoryProvider;
  private AnnotationProvider myAnnotationProvider;
  private DiffProvider mySvnDiffProvider;
  private final VcsShowConfirmationOption myAddConfirmation;
  private final VcsShowConfirmationOption myDeleteConfirmation;
  private EditFileProvider myEditFilesProvider;
  private SvnCommittedChangesProvider myCommittedChangesProvider;
  private final VcsShowSettingOption myCheckoutOptions;

  private ChangeProvider myChangeProvider;
  private MergeProvider myMergeProvider;
  private final WorkingCopiesContent myWorkingCopiesContent;

  @NonNls public static final String LOG_PARAMETER_NAME = "javasvn.log";
  @NonNls public static final String TRACE_NATIVE_CALLS = "javasvn.log.native";
  public static final String pathToEntries = SvnUtil.SVN_ADMIN_DIR_NAME + File.separatorChar + SvnUtil.ENTRIES_FILE_NAME;
  public static final String pathToDirProps = SvnUtil.SVN_ADMIN_DIR_NAME + File.separatorChar + SvnUtil.DIR_PROPS_FILE_NAME;
  private final SvnChangelistListener myChangeListListener;

  private SvnCopiesRefreshManager myCopiesRefreshManager;
  private SvnFileUrlMappingImpl myMapping;
  private final MyFrameStateListener myFrameStateListener;

  //Consumer<Boolean>
  public static final Topic<Consumer> ROOTS_RELOADED = new Topic<Consumer>("ROOTS_RELOADED", Consumer.class);
  private VcsListener myVcsListener;

  private SvnBranchPointsCalculator mySvnBranchPointsCalculator;

  private final RootsToWorkingCopies myRootsToWorkingCopies;
  private final SvnAuthenticationNotifier myAuthNotifier;
  private static RareLogger.LogFilter[] ourLogFilters;
  private final SvnLoadedBrachesStorage myLoadedBranchesStorage;

  public static final String SVNKIT_HTTP_SSL_PROTOCOLS = "svnkit.http.sslProtocols";
  private static boolean ourSSLProtocolsExplicitlySet = false;
  private final SvnExecutableChecker myChecker;

  public static final Processor<Exception> ourBusyExceptionProcessor = new Processor<Exception>() {
    @Override
    public boolean process(Exception e) {
      if (e instanceof SVNException) {
        final SVNErrorCode errorCode = ((SVNException)e).getErrorMessage().getErrorCode();
        if (SVNErrorCode.WC_LOCKED.equals(errorCode)) {
          return true;
        } else if (SVNErrorCode.SQLITE_ERROR.equals(errorCode)) {
          Throwable cause = ((SVNException)e).getErrorMessage().getCause();
          if (cause instanceof SqlJetException) {
            return SqlJetErrorCode.BUSY.equals(((SqlJetException)cause).getErrorCode());
          }
        }
      }
      return false;
    }
  };
  private SvnCheckoutProvider myCheckoutProvider;

  private final ClientFactory cmdClientFactory;
  private final ClientFactory svnKitClientFactory;

  private final boolean myLogExceptions;

  static {
    System.setProperty("svnkit.log.native.calls", "true");
    if (Boolean.getBoolean(DO_NOT_LISTEN_TO_WC_DB)) {
      ourListenToWcDb = false;
    }
    final JavaSVNDebugLogger logger = new JavaSVNDebugLogger(Boolean.getBoolean(LOG_PARAMETER_NAME), Boolean.getBoolean(TRACE_NATIVE_CALLS), LOG);
    SVNDebugLog.setDefaultLog(logger);

    SVNJNAUtil.setJNAEnabled(true);
    SvnHttpAuthMethodsDefaultChecker.check();

    SVNAdminAreaFactory.setSelector(new SvnFormatSelector());

    DAVRepositoryFactory.setup();
    SVNRepositoryFactoryImpl.setup();
    FSRepositoryFactory.setup();

    // non-optimized writing is fast enough on Linux/MacOS, and somewhat more reliable
    if (SystemInfo.isWindows) {
      SVNAdminArea14.setOptimizedWritingEnabled(true);
    }

    if (!SVNJNAUtil.isJNAPresent()) {
      LOG.warn("JNA is not found by svnkit library");
    }
    initLogFilters();

    ourSSLProtocolsExplicitlySet = System.getProperty(SVNKIT_HTTP_SSL_PROTOCOLS) != null;
  }

  public static boolean isSSLProtocolExplicitlySet() {
    return ourSSLProtocolsExplicitlySet;
  }

  public SvnVcs(final Project project, MessageBus bus, SvnConfiguration svnConfiguration, final SvnLoadedBrachesStorage storage) {
    super(project, VCS_NAME);

    cmdClientFactory = new CmdClientFactory(this);
    svnKitClientFactory = new SvnKitClientFactory(this);

    myLoadedBranchesStorage = storage;
    myRootsToWorkingCopies = new RootsToWorkingCopies(this);
    myConfiguration = svnConfiguration;
    myAuthNotifier = new SvnAuthenticationNotifier(this);

    dumpFileStatus(FileStatus.ADDED);
    dumpFileStatus(FileStatus.DELETED);
    dumpFileStatus(FileStatus.MERGE);
    dumpFileStatus(FileStatus.MODIFIED);
    dumpFileStatus(FileStatus.NOT_CHANGED);
    dumpFileStatus(FileStatus.UNKNOWN);

    dumpFileStatus(SvnFileStatus.REPLACED);
    dumpFileStatus(SvnFileStatus.EXTERNAL);
    dumpFileStatus(SvnFileStatus.OBSTRUCTED);

    refreshSSLProperty();

    final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
    myAddConfirmation = vcsManager.getStandardConfirmation(VcsConfiguration.StandardConfirmation.ADD, this);
    myDeleteConfirmation = vcsManager.getStandardConfirmation(VcsConfiguration.StandardConfirmation.REMOVE, this);
    myCheckoutOptions = vcsManager.getStandardOption(VcsConfiguration.StandardOption.CHECKOUT, this);

    if (myProject.isDefault()) {
      myChangeListListener = null;
      myEntriesFileListener = null;
    }
    else {
      myEntriesFileListener = new SvnEntriesFileListener(project);
      upgradeIfNeeded(bus);

      myChangeListListener = new SvnChangelistListener(myProject, this);

      myVcsListener = new VcsListener() {
        @Override
        public void directoryMappingChanged() {
          invokeRefreshSvnRoots();
        }
      };
    }

    myFrameStateListener = project.isDefault() ? null : new MyFrameStateListener(ChangeListManager.getInstance(project),
                                                                                 VcsDirtyScopeManager.getInstance(project));
    myWorkingCopiesContent = new WorkingCopiesContent(this);

    // remove used some time before old notification group ids
    correctNotificationIds();
    myChecker = new SvnExecutableChecker(myProject);

    Application app = ApplicationManager.getApplication();
    myLogExceptions = app != null && (app.isInternal() || app.isUnitTestMode());
  }

  private void correctNotificationIds() {
    boolean notEmpty = NotificationsConfigurationImpl.getNotificationsConfigurationImpl().isRegistered("SVN_NO_JNA") ||
                       NotificationsConfigurationImpl.getNotificationsConfigurationImpl().isRegistered("SVN_NO_CRYPT32") ||
                       NotificationsConfigurationImpl.getNotificationsConfigurationImpl().isRegistered("SubversionId");
    if (notEmpty) {
      NotificationsConfigurationImpl.remove("SVN_NO_JNA", "SVN_NO_CRYPT32", "SubversionId");
      NotificationsConfiguration.getNotificationsConfiguration().register(getDisplayName(), NotificationDisplayType.BALLOON);
    }
  }

  public void postStartup() {
    if (myProject.isDefault()) return;
    myCopiesRefreshManager = new SvnCopiesRefreshManager((SvnFileUrlMappingImpl) getSvnFileUrlMapping());
    if (! myConfiguration.isCleanupRun()) {
      ApplicationManager.getApplication().invokeLater(new Runnable() {
        @Override
        public void run() {
          cleanup17copies();
          myConfiguration.setCleanupRun(true);
        }
      }, ModalityState.NON_MODAL, myProject.getDisposed());
    } else {
      invokeRefreshSvnRoots();
    }

    myWorkingCopiesContent.activate();
  }

  private void cleanup17copies() {
    final Runnable callCleanupWorker = new Runnable() {
      public void run() {
        if (myProject.isDisposed()) return;
        new CleanupWorker(new VirtualFile[]{}, myProject, "action.Subversion.cleanup.progress.title") {
          @Override
          protected void chanceToFillRoots() {
            final List<WCInfo> infos = getAllWcInfos();
            final LocalFileSystem lfs = LocalFileSystem.getInstance();
            final List<VirtualFile> roots = new ArrayList<VirtualFile>(infos.size());
            for (WCInfo info : infos) {
              if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(info.getFormat())) {
                final VirtualFile file = lfs.refreshAndFindFileByIoFile(new File(info.getPath()));
                if (file == null) {
                  LOG.info("Wasn't able to find virtual file for wc root: " + info.getPath());
                } else {
                  roots.add(file);
                }
              }
            }
            myRoots = roots.toArray(new VirtualFile[roots.size()]);
          }
        }.execute();
      }
    };

    myCopiesRefreshManager.waitRefresh(new Runnable() {
      @Override
      public void run() {
        ApplicationManager.getApplication().invokeLater(callCleanupWorker, ModalityState.any());
      }
    });
  }

  public boolean checkCommandLineVersion() {
    boolean isValid = true;

    if (!isProject16() && (myConfiguration.isCommandLine() || isProject18())) {
      isValid = myChecker.checkExecutableAndNotifyIfNeeded();
    }

    return isValid;
  }

  public void invokeRefreshSvnRoots() {
    if (REFRESH_LOG.isDebugEnabled()) {
      REFRESH_LOG.debug("refresh: ", new Throwable());
    }
    if (myCopiesRefreshManager != null) {
      myCopiesRefreshManager.asynchRequest();
    }
  }

  @Override
  public boolean checkImmediateParentsBeforeCommit() {
    return true;
  }

  private void upgradeIfNeeded(final MessageBus bus) {
    final MessageBusConnection connection = bus.connect();
    connection.subscribe(ChangeListManagerImpl.LISTS_LOADED, new LocalChangeListsLoadedListener() {
      @Override
      public void processLoadedLists(final List<LocalChangeList> lists) {
        if (lists.isEmpty()) return;
        SvnConfiguration.SvnSupportOptions supportOptions = null;
        try {
          ChangeListManager.getInstance(myProject).setReadOnly(SvnChangeProvider.ourDefaultListName, true);
          supportOptions = myConfiguration.getSupportOptions(myProject);

          if (!supportOptions.changeListsSynchronized()) {
            processChangeLists(lists);
          }
        }
        catch (ProcessCanceledException e) {
          //
        }
        finally {
          if (supportOptions != null) {
            supportOptions.upgrade();
          }
        }

        connection.disconnect();
      }
    });
  }

  public void processChangeLists(final List<LocalChangeList> lists) {
    final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstanceChecked(myProject);
    plVcsManager.startBackgroundVcsOperation();
    try {
      for (LocalChangeList list : lists) {
        if (!list.isDefault()) {
          final Collection<Change> changes = list.getChanges();
          for (Change change : changes) {
            correctListForRevision(plVcsManager, change.getBeforeRevision(), list.getName());
            correctListForRevision(plVcsManager, change.getAfterRevision(), list.getName());
          }
        }
      }
    }
    finally {
      final Application appManager = ApplicationManager.getApplication();
      if (appManager.isDispatchThread()) {
        appManager.executeOnPooledThread(new Runnable() {
          @Override
          public void run() {
            plVcsManager.stopBackgroundVcsOperation();
          }
        });
      }
      else {
        plVcsManager.stopBackgroundVcsOperation();
      }
    }
  }

  private void correctListForRevision(@NotNull final ProjectLevelVcsManager plVcsManager,
                                      @Nullable final ContentRevision revision,
                                      @NotNull final String name) {
    if (revision != null) {
      final FilePath path = revision.getFile();
      final AbstractVcs vcs = plVcsManager.getVcsFor(path);
      if (vcs != null && VCS_NAME.equals(vcs.getName())) {
        try {
          getFactory(path.getIOFile()).createChangeListClient().add(name, path.getIOFile(), null);
        }
        catch (VcsException e) {
          // left in default list
        }
      }
    }
  }

  @Override
  public void activate() {
    final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
    if (!myProject.isDefault()) {
      ChangeListManager.getInstance(myProject).addChangeListListener(myChangeListListener);
      vcsManager.addVcsListener(myVcsListener);
    }

    SvnApplicationSettings.getInstance().svnActivated();
    if (myEntriesFileListener != null) {
      VirtualFileManager.getInstance().addVirtualFileListener(myEntriesFileListener);
    }
    // this will initialize its inner listener for committed changes upload
    LoadedRevisionsCache.getInstance(myProject);
    FrameStateManager.getInstance().addListener(myFrameStateListener);

    myAuthNotifier.init();
    mySvnBranchPointsCalculator = new SvnBranchPointsCalculator(myProject);
    mySvnBranchPointsCalculator.activate();

    if (SystemInfo.isWindows) {
      if (!SVNJNAUtil.isJNAPresent()) {
        Notifications.Bus.notify(new Notification(getDisplayName(), "Subversion plugin: no JNA",
                                                  "A problem with JNA initialization for SVNKit library. Encryption is not available.",
                                                  NotificationType.WARNING), myProject);
      }
      else if (!SVNJNAUtil.isWinCryptEnabled()) {
        Notifications.Bus.notify(new Notification(getDisplayName(), "Subversion plugin: no encryption",
                                                  "A problem with encryption module (Crypt32.dll) initialization for SVNKit library. " +
                                                  "Encryption is not available.",
                                                  NotificationType.WARNING), myProject);
      }
    }

    final SvnConfiguration.UseAcceleration accelerationType = SvnConfiguration.getInstance(myProject).myUseAcceleration;
    if (SvnConfiguration.UseAcceleration.javaHL.equals(accelerationType)) {
      CheckJavaHL.runtimeCheck(myProject);
    }
    else if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
      checkCommandLineVersion();
    }

    // do one time after project loaded
    StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() {
      @Override
      public void run() {
        postStartup();

        // for IDEA, it takes 2 minutes - and anyway this can be done in background, no sense...
        // once it could be mistaken about copies for 2 minutes on start...

        /*if (! myMapping.getAllWcInfos().isEmpty()) {
          invokeRefreshSvnRoots();
          return;
        }
        ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
          public void run() {
            myCopiesRefreshManager.getCopiesRefresh().ensureInit();
          }
        }, SvnBundle.message("refreshing.working.copies.roots.progress.text"), true, myProject);*/
      }
    });

    vcsManager.addVcsListener(myRootsToWorkingCopies);

    myLoadedBranchesStorage.activate();
  }

  private static void initLogFilters() {
    if (ourLogFilters != null) return;
    ourLogFilters = new RareLogger.LogFilter[]{new RareLogger.LogFilter() {
      @Override
      public Object getKey(@NotNull org.apache.log4j.Level level,
                           @NonNls String message,
                           @Nullable Throwable t,
                           @NonNls String... details) {
        SVNException svnExc = null;
        if (t instanceof SVNException) {
          svnExc = (SVNException)t;
        }
        else if (t instanceof VcsException && t.getCause() instanceof SVNException) {
          svnExc = (SVNException)t.getCause();
        }
        if (svnExc != null) {
          // only filter a few cases
          if (ourLogRarely.contains(svnExc.getErrorMessage().getErrorCode())) {
            return svnExc.getErrorMessage().getErrorCode();
          }
        }
        return null;
      }

      @Override
      @NotNull
      public Integer getAllowedLoggingInterval(org.apache.log4j.Level level, String message, Throwable t, String[] details) {
        SVNException svnExc = null;
        if (t instanceof SVNException) {
          svnExc = (SVNException)t;
        }
        else if (t instanceof VcsException && t.getCause() instanceof SVNException) {
          svnExc = (SVNException)t.getCause();
        }
        if (svnExc != null) {
          if (ourLogRarely.contains(svnExc.getErrorMessage().getErrorCode())) {
            return ourLogRareInterval;
          }
          else {
            return ourLogUsualInterval;
          }
        }
        return 0;
      }
    }};
  }

  public static Logger wrapLogger(final Logger logger) {
    initLogFilters();
    return RareLogger.wrap(logger, Boolean.getBoolean("svn.logger.fairsynch"), ourLogFilters);
  }

  public RootsToWorkingCopies getRootsToWorkingCopies() {
    return myRootsToWorkingCopies;
  }

  public SvnAuthenticationNotifier getAuthNotifier() {
    return myAuthNotifier;
  }

  @Override
  public void deactivate() {
    FrameStateManager.getInstance().removeListener(myFrameStateListener);

    final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
    if (myVcsListener != null) {
      vcsManager.removeVcsListener(myVcsListener);
    }

    if (myEntriesFileListener != null) {
      VirtualFileManager.getInstance().removeVirtualFileListener(myEntriesFileListener);
    }
    SvnApplicationSettings.getInstance().svnDeactivated();
    if (myCommittedChangesProvider != null) {
      myCommittedChangesProvider.deactivate();
    }
    if (myChangeListListener != null && !myProject.isDefault()) {
      ChangeListManager.getInstance(myProject).removeChangeListListener(myChangeListListener);
    }
    vcsManager.removeVcsListener(myRootsToWorkingCopies);
    myRootsToWorkingCopies.clear();

    myAuthNotifier.stop();
    myAuthNotifier.clear();

    mySvnBranchPointsCalculator.deactivate();
    mySvnBranchPointsCalculator = null;
    myWorkingCopiesContent.deactivate();
    myLoadedBranchesStorage.deactivate();
  }

  public VcsShowConfirmationOption getAddConfirmation() {
    return myAddConfirmation;
  }

  public VcsShowConfirmationOption getDeleteConfirmation() {
    return myDeleteConfirmation;
  }

  public VcsShowSettingOption getCheckoutOptions() {
    return myCheckoutOptions;
  }

  @Override
  public EditFileProvider getEditFileProvider() {
    if (myEditFilesProvider == null) {
      myEditFilesProvider = new SvnEditFileProvider(this);
    }
    return myEditFilesProvider;
  }

  @Override
  @NotNull
  public ChangeProvider getChangeProvider() {
    if (myChangeProvider == null) {
      myChangeProvider = new SvnChangeProvider(this);
    }
    return myChangeProvider;
  }

  public SVNRepository createRepository(String url) throws SVNException {
    SVNRepository repos = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url));
    repos.setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    repos.setTunnelProvider(myConfiguration.getOptions(myProject));
    return repos;
  }

  public SVNRepository createRepository(SVNURL url) throws SVNException {
    SVNRepository repos = SVNRepositoryFactory.create(url);
    repos.setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    repos.setTunnelProvider(myConfiguration.getOptions(myProject));
    return repos;
  }

  @NotNull
  private ISVNRepositoryPool getPool() {
    return getPool(myConfiguration.getAuthenticationManager(this));
  }

  @NotNull
  private ISVNRepositoryPool getPool(ISVNAuthenticationManager manager) {
    if (myProject.isDisposed()) {
      throw new ProcessCanceledException();
    }
    return new PrimitivePool(manager, myConfiguration.getOptions(myProject));
  }

  public SVNUpdateClient createUpdateClient() {
    final SVNUpdateClient client = new SVNUpdateClient(getPool(), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    return client;
  }

  public SVNUpdateClient createUpdateClient(@NotNull ISVNAuthenticationManager manager) {
    final SVNUpdateClient client = new SVNUpdateClient(getPool(manager), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(manager);
    return client;
  }

  public SVNStatusClient createStatusClient() {
    SVNStatusClient client = new SVNStatusClient(getPool(), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    client.setIgnoreExternals(false);
    return client;
  }

  public SVNWCClient createWCClient() {
    final SVNWCClient client = new SVNWCClient(getPool(), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    return client;
  }

  public SVNWCClient createWCClient(@NotNull ISVNAuthenticationManager manager) {
    final SVNWCClient client = new SVNWCClient(getPool(manager), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(manager);
    return client;
  }

  public SVNCopyClient createCopyClient() {
    final SVNCopyClient client = new SVNCopyClient(getPool(), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    return client;
  }

  public SVNMoveClient createMoveClient() {
    final SVNMoveClient client = new SVNMoveClient(getPool(), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    return client;
  }

  public SVNLogClient createLogClient() {
    final SVNLogClient client = new SVNLogClient(getPool(), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    return client;
  }

  public SVNLogClient createLogClient(@NotNull ISVNAuthenticationManager manager) {
    final SVNLogClient client = new SVNLogClient(getPool(manager), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(manager);
    return client;
  }

  public SVNCommitClient createCommitClient() {
    final SVNCommitClient client = new SVNCommitClient(getPool(), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    return client;
  }

  public SVNDiffClient createDiffClient() {
    final SVNDiffClient client = new SVNDiffClient(getPool(), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    return client;
  }

  public SVNChangelistClient createChangelistClient() {
    final SVNChangelistClient client = new SVNChangelistClient(getPool(), myConfiguration.getOptions(myProject));
    client.getOperationsFactory().setAuthenticationManager(myConfiguration.getAuthenticationManager(this));
    return client;
  }

  public ISVNOptions getSvnOptions() {
    return myConfiguration.getOptions(myProject);
  }

  public ISVNAuthenticationManager getSvnAuthenticationManager() {
    return myConfiguration.getAuthenticationManager(this);
  }

  void dumpFileStatus(FileStatus fs) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("FileStatus:" + fs.getText() + " " + fs.getColor() + " " + " " + fs.getClass().getName());
    }
  }

  @Override
  public UpdateEnvironment getIntegrateEnvironment() {
    if (mySvnIntegrateEnvironment == null) {
      mySvnIntegrateEnvironment = new SvnIntegrateEnvironment(this);
    }
    return mySvnIntegrateEnvironment;
  }

  @Override
  public UpdateEnvironment createUpdateEnvironment() {
    if (mySvnUpdateEnvironment == null) {
      mySvnUpdateEnvironment = new SvnUpdateEnvironment(this);
    }
    return mySvnUpdateEnvironment;
  }

  @Override
  public String getDisplayName() {
    LOG.debug("getDisplayName");
    return VCS_DISPLAY_NAME;
  }

  @Override
  public Configurable getConfigurable() {
    LOG.debug("createConfigurable");
    return new SvnConfigurable(myProject);
  }


  public SvnConfiguration getSvnConfiguration() {
    return myConfiguration;
  }

  public static SvnVcs getInstance(Project project) {
    return (SvnVcs)ProjectLevelVcsManager.getInstance(project).findVcsByName(VCS_NAME);
  }

  @Override
  @NotNull
  public CheckinEnvironment createCheckinEnvironment() {
    if (myCheckinEnvironment == null) {
      myCheckinEnvironment = new SvnCheckinEnvironment(this);
    }
    return myCheckinEnvironment;
  }

  @Override
  @NotNull
  public RollbackEnvironment createRollbackEnvironment() {
    if (myRollbackEnvironment == null) {
      myRollbackEnvironment = new SvnRollbackEnvironment(this);
    }
    return myRollbackEnvironment;
  }

  @Override
  public VcsHistoryProvider getVcsHistoryProvider() {
    // no heavy state, but it would be useful to have place to keep state in -> do not reuse instance
    return new SvnHistoryProvider(this);
  }

  @Override
  public VcsHistoryProvider getVcsBlockHistoryProvider() {
    return getVcsHistoryProvider();
  }

  @Override
  public AnnotationProvider getAnnotationProvider() {
    if (myAnnotationProvider == null) {
      myAnnotationProvider = new SvnAnnotationProvider(this);
    }
    return myAnnotationProvider;
  }

  @Override
  public DiffProvider getDiffProvider() {
    if (mySvnDiffProvider == null) {
      mySvnDiffProvider = new SvnDiffProvider(this);
    }
    return mySvnDiffProvider;
  }

  private static Trinity<Long, Long, Long> getTimestampForPropertiesChange(final File ioFile, final boolean isDir) {
    final File dir = isDir ? ioFile : ioFile.getParentFile();
    final String relPath = SVNAdminUtil.getPropPath(ioFile.getName(), isDir ? SVNNodeKind.DIR : SVNNodeKind.FILE, false);
    final String relPathBase = SVNAdminUtil.getPropBasePath(ioFile.getName(), isDir ? SVNNodeKind.DIR : SVNNodeKind.FILE, false);
    final String relPathRevert = SVNAdminUtil.getPropRevertPath(ioFile.getName(), isDir ? SVNNodeKind.DIR : SVNNodeKind.FILE, false);
    return new Trinity<Long, Long, Long>(new File(dir, relPath).lastModified(), new File(dir, relPathBase).lastModified(),
                                         new File(dir, relPathRevert).lastModified());
  }

  private static boolean trinitiesEqual(final Trinity<Long, Long, Long> t1, final Trinity<Long, Long, Long> t2) {
    if (t2.first == 0 && t2.second == 0 && t2.third == 0) return false;
    return t1.equals(t2);
  }

  @Nullable
  public SVNPropertyValue getPropertyWithCaching(final VirtualFile file, final String propName) throws VcsException {
    Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>> cachedMap = myPropertyCache.get(keyForVf(file));
    final Pair<SVNPropertyValue, Trinity<Long, Long, Long>> cachedValue = cachedMap == null ? null : cachedMap.get(propName);

    final File ioFile = new File(file.getPath());
    final Trinity<Long, Long, Long> tsTrinity = getTimestampForPropertiesChange(ioFile, file.isDirectory());

    if (cachedValue != null) {
      // zero means that a file was not found
      if (trinitiesEqual(cachedValue.getSecond(), tsTrinity)) {
        return cachedValue.getFirst();
      }
    }

    PropertyClient client = getFactory(ioFile).createPropertyClient();
    final SVNPropertyData value = client.getProperty(SvnTarget.fromFile(ioFile, SVNRevision.WORKING), propName, false, SVNRevision.WORKING);
    final SVNPropertyValue propValue = value == null ? null : value.getValue();

    if (cachedMap == null) {
      cachedMap = new HashMap<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>();
      myPropertyCache.put(keyForVf(file), cachedMap);
    }

    cachedMap.put(propName, new Pair<SVNPropertyValue, Trinity<Long, Long, Long>>(propValue, tsTrinity));

    return propValue;
  }

  @Override
  public boolean fileExistsInVcs(FilePath path) {
    File file = path.getIOFile();
    try {
      SVNStatus status = getFactory(file).createStatusClient().doStatus(file, false);
      if (status != null) {
        if (svnStatusIs(status, SVNStatusType.STATUS_ADDED)) {
          return status.isCopied();
        }
        return !(svnStatusIsUnversioned(status) ||
                 svnStatusIs(status, SVNStatusType.STATUS_IGNORED) ||
                 svnStatusIs(status, SVNStatusType.STATUS_OBSTRUCTED));
      }
    }
    catch (SVNException e) {
      LOG.info(e);
    }
    return false;
  }

  public static boolean svnStatusIsUnversioned(final SVNStatus status) {
    return svnStatusIs(status, SVNStatusType.STATUS_UNVERSIONED);
  }

  public static boolean svnStatusIs(final SVNStatus status, @NotNull final SVNStatusType value) {
    return value.equals(status.getNodeStatus()) || value.equals(status.getContentsStatus());
  }

  @Override
  public boolean fileIsUnderVcs(FilePath path) {
    final ChangeListManager clManager = ChangeListManager.getInstance(myProject);
    final VirtualFile file = path.getVirtualFile();
    if (file == null) {
      return false;
    }
    return !SvnStatusUtil.isIgnoredInAnySense(clManager, file) && !clManager.isUnversioned(file);
  }

  private static File getEntriesFile(File file) {
    return file.isDirectory() ? new File(file, pathToEntries) : new File(file.getParentFile(), pathToEntries);
  }

  private static File getDirPropsFile(File file) {
    return new File(file, pathToDirProps);
  }

  @Nullable
  public SVNInfo getInfo(@NotNull SVNURL url,
                         SVNRevision pegRevision,
                         SVNRevision revision) throws SVNException {
    return getFactory().createInfoClient().doInfo(url, pegRevision, revision);
  }

  @Nullable
  public SVNInfo getInfo(@NotNull SVNURL url, SVNRevision revision) throws SVNException {
    return getInfo(url, SVNRevision.UNDEFINED, revision);
  }

  @Nullable
  public SVNInfo getInfo(@NotNull final VirtualFile file) {
    return getInfo(new File(file.getPath()));
  }

  @Nullable
  public SVNInfo getInfo(@NotNull String path) {
    return getInfo(new File(path));
  }

  @Nullable
  public SVNInfo getInfo(@NotNull File ioFile) {
    SVNInfo result = null;
    SvnWcClientI client = getFactory(ioFile).createInfoClient();

    try {
      // applying such behavior only when info requested w/o explicitly specifying revision
      // TODO: logs should be analyzed and decision taken if we need it or just need to explicitly specify HEAD revision in certain calls
      result = client.doInfo(ioFile, SVNRevision.UNDEFINED);
      SVNInfo localInfo = result;
      if (result == null || result.getRepositoryRootURL() == null) {
        LOG.info("Failed to get local info for " + ioFile + ". Trying to get HEAD info.");
        result = client.doInfo(ioFile, SVNRevision.HEAD);
        if (result != null) {
          LOG.info("Local info was " + localInfo + ", HEAD info was " + result);
        }
      }
    }
    catch (SVNException e) {
      handleInfoException(e);
    }

    return result;
  }

  @Nullable
  public SVNInfo getInfo(@NotNull File ioFile, @NotNull SVNRevision revision) {
    SVNInfo result = null;

    try {
      result = getFactory(ioFile).createInfoClient().doInfo(ioFile, revision);
    }
    catch (SVNException e) {
      handleInfoException(e);
    }

    return result;
  }

  private void handleInfoException(SVNException e) {
    final SVNErrorCode errorCode = e.getErrorMessage().getErrorCode();

    if (!myLogExceptions || 
        SVNErrorCode.WC_PATH_NOT_FOUND.equals(errorCode) ||
        SVNErrorCode.UNVERSIONED_RESOURCE.equals(errorCode) ||
        SVNErrorCode.WC_NOT_WORKING_COPY.equals(errorCode) ||
        // thrown when getting info from repository for non-existent item - like HEAD revision for deleted file
        SVNErrorCode.ILLEGAL_TARGET.equals(errorCode) ||
        // do not log working copy format vs client version inconsistencies as errors
        SVNErrorCode.WC_UNSUPPORTED_FORMAT.equals(errorCode) ||
        SVNErrorCode.WC_UPGRADE_REQUIRED.equals(errorCode)) {
      LOG.debug(e);
    }
    else {
      LOG.error(e);
    }
  }

  public WorkingCopyFormat getWorkingCopyFormat(@NotNull File ioFile) {
    RootUrlInfo rootInfo = getSvnFileUrlMapping().getWcRootForFilePath(ioFile);
    WorkingCopyFormat format = rootInfo != null ? rootInfo.getFormat() : WorkingCopyFormat.UNKNOWN;

    if (WorkingCopyFormat.UNKNOWN.equals(format)) {
      format = SvnFormatSelector.findRootAndGetFormat(ioFile);
    }

    return format;
  }

  public void refreshSSLProperty() {
    if (ourSSLProtocolsExplicitlySet) return;
    if (SvnConfiguration.SSLProtocols.all.equals(myConfiguration.SSL_PROTOCOLS)) {
      System.clearProperty(SVNKIT_HTTP_SSL_PROTOCOLS);
    } else if (SvnConfiguration.SSLProtocols.sslv3.equals(myConfiguration.SSL_PROTOCOLS)) {
      System.setProperty(SVNKIT_HTTP_SSL_PROTOCOLS, "SSLv3");
    } else if (SvnConfiguration.SSLProtocols.tlsv1.equals(myConfiguration.SSL_PROTOCOLS)) {
      System.setProperty(SVNKIT_HTTP_SSL_PROTOCOLS, "TLSv1");
    }
  }

  public boolean isWcRoot(FilePath filePath) {
    boolean isWcRoot = false;
    WorkingCopy wcRoot = myRootsToWorkingCopies.getWcRoot(filePath.getVirtualFile());
    if (wcRoot != null) {
      isWcRoot = wcRoot.getFile().getAbsolutePath().equals(filePath.getIOFile().getAbsolutePath());
    }
    return isWcRoot;
  }

  private static class JavaSVNDebugLogger extends SVNDebugLogAdapter {
    private final boolean myLoggingEnabled;
    private final boolean myLogNative;
    private final Logger myLog;
    private final static long ourErrorNotificationInterval = TimeUnit.MINUTES.toMillis(2);
    private long myPreviousTime = 0;

    public JavaSVNDebugLogger(boolean loggingEnabled, boolean logNative, Logger log) {
      myLoggingEnabled = loggingEnabled;
      myLogNative = logNative;
      myLog = log;
    }

    private boolean shouldLog(final SVNLogType logType) {
      return myLoggingEnabled || myLogNative && SVNLogType.NATIVE_CALL.equals(logType);
    }

    @Override
    public void log(final SVNLogType logType, final Throwable th, final Level logLevel) {
      handleSpecificSSLExceptions(th);
      if (shouldLog(logType)) {
        myLog.info(th);
      }
    }

    private void handleSpecificSSLExceptions(Throwable th) {
      final long time = System.currentTimeMillis();
      if ((time - myPreviousTime) <= ourErrorNotificationInterval) {
        return;
      }
      if (th instanceof SSLHandshakeException) {
        // not trusted certificate exception is not the problem, just part of normal behaviour
        if (th.getCause() instanceof SVNSSLUtil.CertificateNotTrustedException) {
          LOG.info(th);
          return;
        }

        myPreviousTime = time;
        String info = SSLExceptionsHelper.getAddInfo();
        info = info == null ? "" : " (" + info + ") ";
        if (th.getCause() instanceof CertificateException) {
          PopupUtil.showBalloonForActiveFrame("Subversion: " + info + th.getCause().getMessage(), MessageType.ERROR);
        } else {
          final String postMessage = "\nPlease check Subversion SSL settings (Settings | Version Control | Subversion | Network)\n" +
                                     "Maybe you should specify SSL protocol manually - SSLv3 or TLSv1";
          PopupUtil.showBalloonForActiveFrame("Subversion: " + info + th.getMessage() + postMessage, MessageType.ERROR);
        }
      } else if (th instanceof SSLProtocolException) {
        final String message = th.getMessage();
        if (! StringUtil.isEmptyOrSpaces(message)) {
          myPreviousTime = time;
          String info = SSLExceptionsHelper.getAddInfo();
          info = info == null ? "" : " (" + info + ") ";
          final SSLProtocolExceptionParser parser = new SSLProtocolExceptionParser(message);
          parser.parse();
          final String errMessage = "Subversion: " + info + parser.getParsedMessage();
          PopupUtil.showBalloonForActiveFrame(errMessage, MessageType.ERROR);
        }
      }
    }

    @Override
    public void log(final SVNLogType logType, final String message, final Level logLevel) {
      if (SVNLogType.NATIVE_CALL.equals(logType)) {
        logNative(message);
      }
      if (shouldLog(logType)) {
        myLog.info(message);
      }
    }

    private static void logNative(String message) {
      if (message == null) return;
      final NativeLogReader.CallInfo callInfo = SvnNativeLogParser.parse(message);
      if (callInfo == null) return;
      NativeLogReader.putInfo(callInfo);
    }

    @Override
    public void log(final SVNLogType logType, final String message, final byte[] data) {
      if (shouldLog(logType)) {
        if (data != null) {
          try {
            myLog.info(message + "\n" + new String(data, "UTF-8"));
          }
          catch (UnsupportedEncodingException e) {
            myLog.info(message + "\n" + new String(data));
          }
        }
        else {
          myLog.info(message);
        }
      }
    }
  }

  @Override
  public FileStatus[] getProvidedStatuses() {
    return new FileStatus[]{SvnFileStatus.EXTERNAL,
      SvnFileStatus.OBSTRUCTED,
      SvnFileStatus.REPLACED};
  }


  @Override
  @NotNull
  public CommittedChangesProvider<SvnChangeList, ChangeBrowserSettings> getCommittedChangesProvider() {
    if (myCommittedChangesProvider == null) {
      myCommittedChangesProvider = new SvnCommittedChangesProvider(myProject);
    }
    return myCommittedChangesProvider;
  }

  @Nullable
  @Override
  public VcsRevisionNumber parseRevisionNumber(final String revisionNumberString) {
    final SVNRevision revision = SVNRevision.parse(revisionNumberString);
    if (revision.equals(SVNRevision.UNDEFINED)) {
      return null;
    }
    return new SvnRevisionNumber(revision);
  }

  @Override
  public String getRevisionPattern() {
    return ourIntegerPattern;
  }

  @Override
  public boolean isVersionedDirectory(final VirtualFile dir) {
    return SvnUtil.seemsLikeVersionedDir(dir);
  }

  @NotNull
  public SvnFileUrlMapping getSvnFileUrlMapping() {
    if (myMapping == null) {
      myMapping = SvnFileUrlMappingImpl.getInstance(myProject);
    }
    return myMapping;
  }

  /**
   * Returns real working copies roots - if there is <Project Root> -> Subversion setting,
   * and there is one working copy, will return one root
   */
  public List<WCInfo> getAllWcInfos() {
    final SvnFileUrlMapping urlMapping = getSvnFileUrlMapping();

    final List<RootUrlInfo> infoList = urlMapping.getAllWcInfos();
    final List<WCInfo> infos = new ArrayList<WCInfo>();
    for (RootUrlInfo info : infoList) {
      final File file = info.getIoFile();
      infos.add(new WCInfo(file.getAbsolutePath(), info.getAbsoluteUrlAsUrl(),
                           info.getFormat(), info.getRepositoryUrl(), SvnUtil.isWorkingCopyRoot(file), info.getType(),
                           SvnUtil.getDepth(this, file)));
    }
    return infos;
  }

  @Override
  public RootsConvertor getCustomConvertor() {
    if (myProject.isDefault()) return null;
    return getSvnFileUrlMapping();
  }

  @Override
  public MergeProvider getMergeProvider() {
    if (myMergeProvider == null) {
      myMergeProvider = new SvnMergeProvider(myProject);
    }
    return myMergeProvider;
  }

  @Override
  public List<AnAction> getAdditionalActionsForLocalChange() {
    return Arrays.<AnAction>asList(new ShowPropertiesDiffWithLocalAction());
  }

  private static String keyForVf(final VirtualFile vf) {
    return vf.getUrl();
  }

  @Override
  public boolean allowsNestedRoots() {
    return true;
  }

  @Override
  public <S> List<S> filterUniqueRoots(final List<S> in, final Convertor<S, VirtualFile> convertor) {
    if (in.size() <= 1) return in;

    final List<MyPair<S>> infos = new ArrayList<MyPair<S>>(in.size());
    final SvnFileUrlMappingImpl mapping = (SvnFileUrlMappingImpl)getSvnFileUrlMapping();
    final List<S> notMatched = new LinkedList<S>();
    for (S s : in) {
      final VirtualFile vf = convertor.convert(s);
      if (vf == null) continue;

      final File ioFile = new File(vf.getPath());
      SVNURL url = mapping.getUrlForFile(ioFile);
      if (url == null) {
        url = SvnUtil.getUrl(this, ioFile);
        if (url == null) {
          notMatched.add(s);
          continue;
        }
      }
      infos.add(new MyPair<S>(vf, url.toString(), s));
    }
    final List<MyPair<S>> filtered = new ArrayList<MyPair<S>>(infos.size());
    ForNestedRootChecker.filterOutSuperfluousChildren(this, infos, filtered);

    final List<S> converted = ObjectsConvertor.convert(filtered, new Convertor<MyPair<S>, S>() {
      @Override
      public S convert(final MyPair<S> o) {
        return o.getSrc();
      }
    });
    if (!notMatched.isEmpty()) {
      // potential bug is here: order is not kept. but seems it only occurs for cases where result is sorted after filtering so ok
      converted.addAll(notMatched);
    }
    return converted;
  }

  private static class MyPair<T> implements RootUrlPair {
    private final VirtualFile myFile;
    private final String myUrl;
    private final T mySrc;

    private MyPair(VirtualFile file, String url, T src) {
      myFile = file;
      myUrl = url;
      mySrc = src;
    }

    public T getSrc() {
      return mySrc;
    }

    @Override
    public VirtualFile getVirtualFile() {
      return myFile;
    }

    @Override
    public String getUrl() {
      return myUrl;
    }
  }

  private static class MyFrameStateListener extends FrameStateListener.Adapter {
    private final ChangeListManager myClManager;
    private final VcsDirtyScopeManager myDirtyScopeManager;

    private MyFrameStateListener(ChangeListManager clManager, VcsDirtyScopeManager dirtyScopeManager) {
      myClManager = clManager;
      myDirtyScopeManager = dirtyScopeManager;
    }

    @Override
    public void onFrameActivated() {
      final List<VirtualFile> folders = ((ChangeListManagerImpl)myClManager).getLockedFolders();
      if (!folders.isEmpty()) {
        myDirtyScopeManager.filesDirty(null, folders);
      }
    }
  }

  public static VcsKey getKey() {
    return ourKey;
  }

  @Override
  public boolean isVcsBackgroundOperationsAllowed(VirtualFile root) {
    return ThreeState.YES.equals(myAuthNotifier.isAuthenticatedFor(root));
  }

  public SvnBranchPointsCalculator getSvnBranchPointsCalculator() {
    return mySvnBranchPointsCalculator;
  }

  @Override
  public boolean areDirectoriesVersionedItems() {
    return true;
  }

  @Override
  public CheckoutProvider getCheckoutProvider() {
    if (myCheckoutProvider == null) {
      myCheckoutProvider = new SvnCheckoutProvider();
    }
    return myCheckoutProvider;
  }

  public boolean isProject18() {
    return WorkingCopyFormat.ONE_DOT_EIGHT.equals(getProjectRootFormat());
  }

  public boolean isProject16() {
    return WorkingCopyFormat.ONE_DOT_SIX.equals(getProjectRootFormat());
  }

  private WorkingCopyFormat getProjectRootFormat() {
    return !getProject().isDefault() ? getWorkingCopyFormat(new File(getProject().getBaseDir().getPath())) : WorkingCopyFormat.UNKNOWN;
  }

  /**
   * Detects appropriate client factory based on project root directory working copy format.
   *
   * Try to avoid usages of this method (for now) as it could not correctly for all cases
   * detect svn 1.8 working copy format to guarantee command line client.
   *
   * For instance, when working copies of several formats are presented in project
   * (though it seems to be rather unlikely case).
   *
   * @return
   */
  @NotNull
  public ClientFactory getFactory() {
    return getFactory(getProjectRootFormat(), false);
  }

  public ClientFactory getSvnKitFactory() {
    return svnKitClientFactory;
  }

  @NotNull
  public ClientFactory getFactory(@NotNull File file) {
    return getFactory(getWorkingCopyFormat(file), true);
  }

  @NotNull
  private ClientFactory getFactory(@NotNull WorkingCopyFormat format, boolean useProjectRootForUnknown) {
    boolean is18 = WorkingCopyFormat.ONE_DOT_EIGHT.equals(format);
    boolean is16 = WorkingCopyFormat.ONE_DOT_SIX.equals(format);
    boolean isUnknown = WorkingCopyFormat.UNKNOWN.equals(format);

    return is18
           ? cmdClientFactory
           : (is16 ? svnKitClientFactory : (useProjectRootForUnknown && isUnknown ? getFactory() : getFactoryFromSettings()));
  }

  @NotNull
  public ClientFactory getFactory(@NotNull SvnTarget target) {
    return target.isFile() ? getFactory(target.getFile()) : getFactory();
  }

  @NotNull
  public ClientFactory getFactoryFromSettings() {
    return myConfiguration.isCommandLine() ? cmdClientFactory : svnKitClientFactory;
  }

  @NotNull
  public ClientFactory getCommandLineFactory() {
    return cmdClientFactory;
  }
}
