/*
 * Copyright 2000-2012 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.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.CalledInAwt;
import com.intellij.openapi.vcs.changes.committed.AbstractCalledLater;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.util.EventDispatcher;
import com.intellij.util.messages.Topic;
import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.proxy.CommonProxy;
import com.intellij.util.ui.UIUtil;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.auth.ProviderType;
import org.jetbrains.idea.svn.auth.SvnAuthenticationInteraction;
import org.jetbrains.idea.svn.auth.SvnAuthenticationListener;
import org.jetbrains.idea.svn.config.ProxyGroup;
import org.jetbrains.idea.svn.config.SvnServerFileKeys;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.*;
import org.tmatesoft.svn.core.internal.wc.*;
import org.tmatesoft.svn.core.io.SVNRepository;

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

/**
 * @author alex
 */
public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager implements SvnAuthenticationListener, ISVNAuthenticationManagerExt {
  private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnAuthenticationManager");
  // while Mac storage not working for IDEA, we use this key to check whether to prompt abt plaintext or just store
  public static final String SVN_SSH = "svn+ssh";
  public static final String HTTP = "http";
  public static final String HTTPS = "https";
  public static final String HTTP_PROXY_HOST = "http-proxy-host";
  public static final String HTTP_PROXY_PORT = "http-proxy-port";
  public static final String HTTP_PROXY_USERNAME = "http-proxy-username";
  public static final String HTTP_PROXY_PASSWORD = "http-proxy-password";
  private Project myProject;
  private File myConfigDirectory;
  private PersistentAuthenticationProviderProxy myPersistentAuthenticationProviderProxy;
  private SvnConfiguration myConfig;
  private static final ThreadLocal<Boolean> ourJustEntered = new ThreadLocal<Boolean>();
  private SvnAuthenticationInteraction myInteraction;
  private EventDispatcher<SvnAuthenticationListener> myListener;
  private IdeaSVNHostOptionsProvider myLocalHostOptionsProvider;
  private final ThreadLocalSavePermissions mySavePermissions;
  private final Map<Thread, String> myKeyAlgorithm;
  private boolean myArtificialSaving;
  private ISVNAuthenticationProvider myProvider;
  public static final Topic<ISVNAuthenticationProviderListener> AUTHENTICATION_PROVIDER_LISTENER =
    new Topic<ISVNAuthenticationProviderListener>("AUTHENTICATION_PROVIDER_LISTENER", ISVNAuthenticationProviderListener.class);
  private final static ThreadLocal<ISVNAuthenticationProvider> ourThreadLocalProvider = new ThreadLocal<ISVNAuthenticationProvider>();

  public SvnAuthenticationManager(final Project project, final File configDirectory) {
    super(configDirectory, true, null, null);
    myProject = project;
    myConfigDirectory = configDirectory;
    myKeyAlgorithm = new HashMap<Thread, String>();
    ensureListenerCreated();
    mySavePermissions = new ThreadLocalSavePermissions();
    myConfig = SvnConfiguration.getInstance(myProject);
    if (myPersistentAuthenticationProviderProxy != null) {
      myPersistentAuthenticationProviderProxy.setProject(myProject);
    }
    myInteraction = new MySvnAuthenticationInteraction(myProject);
    Disposer.register(project, new Disposable() {
      @Override
      public void dispose() {
        myProject = null;
        if (myPersistentAuthenticationProviderProxy != null) {
          myPersistentAuthenticationProviderProxy.myProject = null;
          ((MyKeyringMasterKeyProvider) myPersistentAuthenticationProviderProxy.myISVNGnomeKeyringPasswordProvider).myProject = null;
          myPersistentAuthenticationProviderProxy = null;
        }
        if (myInteraction instanceof MySvnAuthenticationInteraction) {
          ((MySvnAuthenticationInteraction) myInteraction).myProject = null;
        }
        if (myConfig != null) {
          myConfig.clear();
          myConfig = null;
        }
        myInteraction = null;

      }
    });
  }

  private class AuthenticationProviderProxy implements ISVNAuthenticationProvider {
    private final ISVNAuthenticationProvider myDelegate;

    private AuthenticationProviderProxy(ISVNAuthenticationProvider delegate) {
      myDelegate = delegate;
    }

    @Override
    public SVNAuthentication requestClientAuthentication(String kind,
                                                         SVNURL url,
                                                         String realm,
                                                         SVNErrorMessage errorMessage,
                                                         SVNAuthentication previousAuth, boolean authMayBeStored) {
      final SVNAuthentication authentication =
        myDelegate.requestClientAuthentication(kind, url, realm, errorMessage, previousAuth, authMayBeStored);
      if (myProject != null && ! myProject.isDisposed()) {
        myProject.getMessageBus().syncPublisher(AUTHENTICATION_PROVIDER_LISTENER)
          .requestClientAuthentication(kind, url, realm, errorMessage, previousAuth, authMayBeStored, authentication);
      }
      return authentication;
    }

    @Override
    public int acceptServerAuthentication(SVNURL url,
                                          String realm,
                                          Object certificate,
                                          boolean resultMayBeStored) {
      final int result = myDelegate.acceptServerAuthentication(url, realm, certificate, resultMayBeStored);
      if (myProject != null && ! myProject.isDisposed()) {
        myProject.getMessageBus().syncPublisher(AUTHENTICATION_PROVIDER_LISTENER)
          .acceptServerAuthentication(url, realm, certificate, resultMayBeStored, result);
      }
      return result;
    }
  }

  public interface ISVNAuthenticationProviderListener {
    void requestClientAuthentication(String kind, SVNURL url, String realm, SVNErrorMessage errorMessage,
      SVNAuthentication previousAuth, boolean authMayBeStored, SVNAuthentication authentication);
    void acceptServerAuthentication(SVNURL url, String realm, Object certificate, boolean resultMayBeStored, @MagicConstant int acceptResult);
  }

  @Override
  public void setAuthenticationProvider(ISVNAuthenticationProvider provider) {
    ISVNAuthenticationProvider useProvider = provider;
    if (! (provider instanceof AuthenticationProviderProxy)) {
      useProvider = new AuthenticationProviderProxy(provider);
    }
    myProvider = useProvider;
    super.setAuthenticationProvider(myProvider);
  }

  public ISVNAuthenticationProvider getProvider() {
    final ISVNAuthenticationProvider threadProvider = ourThreadLocalProvider.get();
    if (threadProvider != null) return threadProvider;
    return myProvider;
  }

  /**
   * Gets authentication provider without looking into thread local storage for providers.
   *
   * TODO:
   * Thread local storage is used "for some interaction with SVNKit" and is not always cleared correctly. So some threads contain
   * "passive provider" in thread local storage - and getProvider() returns this "passive provider". This occurs, for instance when
   * RemoteRevisionsCache is refreshed in background - after its execution, corresponding thread has "passive provider" in thread local
   * storage.
   *
   * As a result authentication fails in such cases (at least for command line implementation). To fix this, command line implementation is
   * updated not to check thread local storage at all.
   *
   * @return
   */
  public ISVNAuthenticationProvider getInnerProvider() {
    return myProvider;
  }

  @Override
  public ISVNAuthenticationStorage getRuntimeAuthStorage() {
    return super.getRuntimeAuthStorage();
  }

  // since set to null during dispose and we have background processes
  private SvnConfiguration getConfig() {
    if (myConfig == null) throw new ProcessCanceledException();
    return myConfig;
  }

  public void setArtificialSaving(boolean artificialSaving) {
    myArtificialSaving = artificialSaving;
  }

  private void ensureListenerCreated() {
    if (myListener == null) {
      myListener = EventDispatcher.create(SvnAuthenticationListener.class);
    }
  }

  @Override
  public IdeaSVNHostOptionsProvider getHostOptionsProvider() {
    if (myLocalHostOptionsProvider == null) {
      myLocalHostOptionsProvider = new IdeaSVNHostOptionsProvider();
    }
    return myLocalHostOptionsProvider;
  }

  public void addListener(final SvnAuthenticationListener listener) {
    myListener.addListener(listener);
  }

  @Override
  public void actualSaveWillBeTried(ProviderType type, SVNURL url, String realm, String kind) {
    myListener.getMulticaster().actualSaveWillBeTried(type, url, realm, kind);
  }

  @Override
  public void saveAttemptStarted(ProviderType type, SVNURL url, String realm, String kind) {
    myListener.getMulticaster().saveAttemptStarted(type, url, realm, kind);
  }

  @Override
  public void saveAttemptFinished(ProviderType type, SVNURL url, String realm, String kind) {
    myListener.getMulticaster().saveAttemptFinished(type, url, realm, kind);
  }

  @Override
  public void acknowledge(boolean accepted, String kind, String realm, SVNErrorMessage message, SVNAuthentication authentication) {
    myListener.getMulticaster().acknowledge(accepted, kind, realm, message, authentication);
  }

  @Override
  public void requested(ProviderType type, SVNURL url, String realm, String kind, boolean canceled) {
    if (ProviderType.interactive.equals(type) && (! canceled)) {
      ourJustEntered.set(true);
    }
    myListener.getMulticaster().requested(type, url, realm, kind, canceled);
  }

  @Override
  protected ISVNAuthenticationProvider createCacheAuthenticationProvider(File authDir, String userName) {
    // this is a hack due to the fact this method is called from super() constructor
    myConfigDirectory = new File(authDir.getParent());
    myPersistentAuthenticationProviderProxy = new PersistentAuthenticationProviderProxy(authDir, userName);
    return myPersistentAuthenticationProviderProxy;
  }

  private class PersistentAuthenticationProviderProxy implements ISVNAuthenticationProvider, ISVNPersistentAuthenticationProvider {
    private final ISVNAuthenticationProvider myDelegate;
    private final ISVNGnomeKeyringPasswordProvider myISVNGnomeKeyringPasswordProvider;
    private final File myAuthDir;
    private Project myProject;

    private PersistentAuthenticationProviderProxy(File authDir, String userName) {
      myISVNGnomeKeyringPasswordProvider = new MyKeyringMasterKeyProvider(myProject);
      ISVNAuthenticationStorageOptions delegatingOptions = new ISVNAuthenticationStorageOptions() {
        public boolean isNonInteractive() throws SVNException {
          return getAuthenticationStorageOptions().isNonInteractive();
        }

        public ISVNAuthStoreHandler getAuthStoreHandler() throws SVNException {
          return getAuthenticationStorageOptions().getAuthStoreHandler();
        }

        @Override
        public ISVNGnomeKeyringPasswordProvider getGnomeKeyringPasswordProvider() {
          return myISVNGnomeKeyringPasswordProvider;
        }

        @Override
        public boolean isSSLPassphrasePromptSupported() {
          return false;
        }
      };
      ensureListenerCreated();
      myDelegate = new DefaultSVNPersistentAuthenticationProvider(authDir, userName, delegatingOptions, getDefaultOptions(), getHostOptionsProvider()) {
        @Override
        protected IPasswordStorage[] createPasswordStorages(DefaultSVNOptions options) {
          final IPasswordStorage[] passwordStorages = super.createPasswordStorages(options);
          final IPasswordStorage[] proxied = new IPasswordStorage[passwordStorages.length];
          for (int i = 0; i < passwordStorages.length; i++) {
            final IPasswordStorage storage = passwordStorages[i];
            proxied[i] = new ProxyPasswordStorageForDebug(storage, myListener);
          }
          return proxied;
        }
      };
      myAuthDir = authDir;
    }

    public void setProject(Project project) {
      myProject = project;
    }

    public SVNAuthentication requestClientAuthentication(final String kind, final SVNURL url, final String realm, final SVNErrorMessage errorMessage,
                                                         final SVNAuthentication previousAuth, final boolean authMayBeStored) {
      try {
        return wrapNativeCall(new ThrowableComputable<SVNAuthentication, SVNException>() {
          @Override
          public SVNAuthentication compute() throws SVNException {
            final SVNAuthentication svnAuthentication =
              myDelegate.requestClientAuthentication(kind, url, realm, errorMessage, previousAuth, authMayBeStored);
            myListener.getMulticaster().requested(ProviderType.persistent, url, realm, kind, svnAuthentication == null);
            return svnAuthentication;
          }
        });
      }
      catch (SVNException e) {
        LOG.info(e);
        throw new RuntimeException(e);
      }
    }

    public int acceptServerAuthentication(final SVNURL url, final String realm, final Object certificate, final boolean resultMayBeStored) {
      return ACCEPTED_TEMPORARY;
    }

    private void actualSavePermissions(String realm, SVNAuthentication auth) {
      final String actualKind = auth.getKind();
          File dir = new File(myAuthDir, actualKind);
          String fileName = SVNFileUtil.computeChecksum(realm);
          File authFile = new File(dir, fileName);

          try {
            ((ISVNPersistentAuthenticationProvider) myDelegate).saveAuthentication(auth, actualKind, realm);
          }
          catch (SVNException e) {
            if (myProject != null) {
              ApplicationManager.getApplication().invokeLater(new VcsBalloonProblemNotifier(myProject,
                "<b>Problem when storing Subversion credentials:</b>&nbsp;" + e.getMessage(), MessageType.ERROR));
            }
          }
          finally {
            // do not make password file readonly
            setWriteable(authFile);
          }
    }

    public void saveAuthentication(final SVNAuthentication auth, final String kind, final String realm) throws SVNException {
      try {
        wrapNativeCall(new ThrowableComputable<Void, SVNException>() {
          @Override
          public Void compute() throws SVNException {
            final Boolean fromInteractive = ourJustEntered.get();
            ourJustEntered.set(null);
            if (! myArtificialSaving && ! Boolean.TRUE.equals(fromInteractive)) {
              // not what user entered
              return null;
            }
            myListener.getMulticaster().saveAttemptStarted(ProviderType.persistent, auth.getURL(), realm, auth.getKind());
            ((ISVNPersistentAuthenticationProvider) myDelegate).saveAuthentication(auth, kind, realm);
            myListener.getMulticaster().saveAttemptFinished(ProviderType.persistent, auth.getURL(), realm, auth.getKind());
            return null;
          }
        });
      }
      catch (SVNException e) {
        LOG.info(e);
        throw new RuntimeException(e);
      }
    }

    @Override
    public void saveFingerprints(final String realm, final byte[] fingerprints) {
      try {
        wrapNativeCall(new ThrowableComputable<Void, SVNException>() {
          @Override
          public Void compute() throws SVNException {
            ((ISVNPersistentAuthenticationProvider) myDelegate).saveFingerprints(realm, fingerprints);
            return null;
          }
        });
      }
      catch (SVNException e) {
        LOG.info(e);
        throw new RuntimeException(e);
      }
    }

    @Override
    public byte[] loadFingerprints(final String realm) {
      try {
        return wrapNativeCall(new ThrowableComputable<byte[], SVNException>() {
          @Override
          public byte[] compute() throws SVNException {
            return ((ISVNPersistentAuthenticationProvider) myDelegate).loadFingerprints(realm);
          }
        });
      }
      catch (SVNException e) {
        LOG.info(e);
        throw new RuntimeException(e);
      }
    }

    private final static int maxAttempts = 10;
    private void setWriteable(final File file) {
      if (! file.exists()) return;
      if (file.getParentFile() == null) {
        return;
      }
      for (int i = 0; i < maxAttempts; i++) {
        final File parent = file.getParentFile();
        try {
          final File tempFile = FileUtil.createTempFile(parent, "123", "1", true);
          FileUtil.delete(tempFile);
          if (! file.renameTo(tempFile)) continue;
          if (! file.createNewFile()) continue;
          FileUtil.copy(tempFile, file);
          FileUtil.delete(tempFile);
          return;
        }
        catch (IOException e) {
          //
        }
      }
    }
  }

  @Override
  public void verifyHostKey(String hostName, int port, String keyAlgorithm, byte[] hostKey) throws SVNException {
    myKeyAlgorithm.put(Thread.currentThread(), keyAlgorithm);
    try {
      super.verifyHostKey(hostName, port, keyAlgorithm, hostKey);
    } finally {
      myKeyAlgorithm.remove(Thread.currentThread());
    }
  }

  @Nullable
  public String getSSHKeyAlgorithm() {
    return myKeyAlgorithm.get(Thread.currentThread());
  }

  @Override
  public void acknowledgeConnectionSuccessful(SVNURL url) {
    CommonProxy.getInstance().removeNoProxy(url.getProtocol(), url.getHost(), url.getPort());
    SSLExceptionsHelper.removeInfo();
    ourThreadLocalProvider.remove();
  }

  @Override
  public void acknowledgeAuthentication(boolean accepted,
                                        String kind,
                                        String realm,
                                        SVNErrorMessage errorMessage,
                                        SVNAuthentication authentication) throws SVNException {
    acknowledgeAuthentication(accepted, kind, realm, errorMessage, authentication, null);
  }

  @Override
  public void acknowledgeAuthentication(boolean accepted,
                                        String kind,
                                        String realm,
                                        SVNErrorMessage errorMessage,
                                        SVNAuthentication authentication,
                                        SVNURL url) throws SVNException {
    SSLExceptionsHelper.removeInfo();
    ourThreadLocalProvider.remove();
    if (url != null) {
      CommonProxy.getInstance().removeNoProxy(url.getProtocol(), url.getHost(), url.getPort());
    }
    boolean successSaving = false;
    myListener.getMulticaster().acknowledge(accepted, kind, realm, errorMessage, authentication);
    try {
      final boolean authStorageEnabled = getHostOptionsProvider().getHostOptions(authentication.getURL()).isAuthStorageEnabled();
      final SVNAuthentication proxy = ProxySvnAuthentication.proxy(authentication, authStorageEnabled, myArtificialSaving);
      super.acknowledgeAuthentication(accepted, kind, realm, errorMessage, proxy);
      successSaving = true;
    } finally {
      mySavePermissions.remove();
      if (myArtificialSaving) {
        myArtificialSaving = false;
        throw new CredentialsSavedException(successSaving);
      }
    }
  }

  public void acknowledgeForSSL(boolean accepted, String kind, String realm, SVNErrorMessage message, SVNAuthentication proxy) {
    if (accepted && proxy instanceof SVNSSLAuthentication && (((SVNSSLAuthentication) proxy).getCertificateFile() != null)) {
      final SVNSSLAuthentication svnsslAuthentication = (SVNSSLAuthentication)proxy;
      final SVNURL url = svnsslAuthentication.getURL();

      final IdeaSVNHostOptionsProvider provider = getHostOptionsProvider();
      final SVNCompositeConfigFile serversFile = provider.getServersFile();
      String groupName = getGroupName(serversFile.getProperties("groups"), url.getHost());

      if (StringUtil.isEmptyOrSpaces(groupName)) {
        serversFile.setPropertyValue("global", SvnServerFileKeys.SSL_CLIENT_CERT_FILE, svnsslAuthentication.getCertificateFile().getPath(), true);
        //serversFile.setPropertyValue("global", SvnServerFileKeys.SSL_CLIENT_CERT_PASSWORD, null, true);
      } else {
        serversFile.setPropertyValue(groupName, SvnServerFileKeys.SSL_CLIENT_CERT_FILE, svnsslAuthentication.getCertificateFile().getPath(), true);
        //serversFile.setPropertyValue(groupName, SvnServerFileKeys.SSL_CLIENT_CERT_PASSWORD, null, true);
      }
      serversFile.save();
    }
  }

  public ISVNProxyManager getProxyManager(SVNURL url) throws SVNException {
    SSLExceptionsHelper.addInfo("Accessing URL: " + url.toString());
    ourThreadLocalProvider.set(myProvider);
    // in proxy creation, we need proxy information from common proxy. but then we should forbid common proxy to intercept
    final ISVNProxyManager proxy = createProxy(url);
    CommonProxy.getInstance().noProxy(url.getProtocol(), url.getHost(), url.getPort());
    return proxy;
  }

  private ISVNProxyManager createProxy(SVNURL url) {
    // this code taken from default manager (changed for system properties reading)
    String host = url.getHost();

    String proxyHost = getServersPropertyIdea(host, HTTP_PROXY_HOST);
    if ((proxyHost == null) || "".equals(proxyHost.trim())) {
      if (getConfig().isIsUseDefaultProxy()) {
        // ! use common proxy if it is set
        try {
          final List<Proxy> proxies = HttpConfigurable.getInstance().getOnlyBySettingsSelector().select(new URI(url.toString()));
          if (proxies != null && ! proxies.isEmpty()) {
            for (Proxy proxy : proxies) {
              if (HttpConfigurable.isRealProxy(proxy) && Proxy.Type.HTTP.equals(proxy.type())) {
                final SocketAddress address = proxy.address();
                if (address instanceof InetSocketAddress) {
                  return new MyPromptingProxyManager(((InetSocketAddress)address).getHostName(), "" + ((InetSocketAddress)address).getPort(),
                                                     url.getProtocol());
                }
              }
            }
          }
        }
        catch (URISyntaxException e) {
          LOG.info(e);
        }
      }
      return null;
    }
    String proxyExceptions = getServersPropertyIdea(host, "http-proxy-exceptions");
    String proxyExceptionsSeparator = ",";
    if (proxyExceptions == null) {
        proxyExceptions = System.getProperty("http.nonProxyHosts");
        proxyExceptionsSeparator = "|";
    }
    if (proxyExceptions != null) {
      for(StringTokenizer exceptions = new StringTokenizer(proxyExceptions, proxyExceptionsSeparator); exceptions.hasMoreTokens();) {
          String exception = exceptions.nextToken().trim();
          if (DefaultSVNOptions.matches(exception, host)) {
              return null;
          }
      }
    }
    String proxyPort = getServersPropertyIdea(host, HTTP_PROXY_PORT);
    String proxyUser = getServersPropertyIdea(host, HTTP_PROXY_USERNAME);
    String proxyPassword = getServersPropertyIdea(host, HTTP_PROXY_PASSWORD);
    return new MySimpleProxyManager(proxyHost, proxyPort, proxyUser, proxyPassword);
  }


  private static class MyPromptingProxyManager extends MySimpleProxyManager {
    private static final String ourPrompt = "Proxy authentication";
    private final String myProtocol;

    private MyPromptingProxyManager(final String host, final String port, String protocol) {
      super(host, port, null, null);
      myProtocol = protocol;
    }

    @Override
    public String getProxyUserName() {
      if (myProxyUser != null) {
        return myProxyUser;
      }
      tryGetCredentials();
      return myProxyUser;
    }

    private void tryGetCredentials() {
      try {
        final InetAddress ia = InetAddress.getByName(getProxyHost());
        final PasswordAuthentication authentication =
          Authenticator.requestPasswordAuthentication(getProxyHost(), ia, getProxyPort(), myProtocol, getProxyHost(), myProtocol,
                                                      null, Authenticator.RequestorType.PROXY);
        if (authentication != null) {
          myProxyUser = authentication.getUserName();
          myProxyPassword = String.valueOf(authentication.getPassword());
        }
      }
      catch (UnknownHostException e) {
        //
      }
    }

    @Override
    public String getProxyPassword() {
      if (myProxyPassword != null) {
        return myProxyPassword;
      }
      tryGetCredentials();
      return myProxyPassword;
    }
  }

  private static class MySimpleProxyManager implements ISVNProxyManager {
      protected String myProxyHost;
      private final String myProxyPort;
      protected String myProxyUser;
      protected String myProxyPassword;

      public MySimpleProxyManager(String host, String port, String user, String password) {
          myProxyHost = host;
          myProxyPort = port == null ? "3128" : port;
          myProxyUser = user;
          myProxyPassword = password;
      }

      public String getProxyHost() {
          return myProxyHost;
      }

      public int getProxyPort() {
          try {
              return Integer.parseInt(myProxyPort);
          } catch (NumberFormatException nfe) {
              //
          }
          return 3128;
      }

      public String getProxyUserName() {
          return myProxyUser;
      }

      public String getProxyPassword() {
          return myProxyPassword;
      }

      public void acknowledgeProxyContext(boolean accepted, SVNErrorMessage errorMessage) {
      }
  }

  // 30 seconds
  private final static int DEFAULT_READ_TIMEOUT = 30 * 1000;

  @Override
  public int getReadTimeout(final SVNRepository repository) {
    String protocol = repository.getLocation().getProtocol();
    if (HTTP.equals(protocol) || HTTPS.equals(protocol)) {
        String host = repository.getLocation().getHost();
        String timeout = getServersPropertyIdea(host, "http-timeout");
        if (timeout != null) {
            try {
                return Integer.parseInt(timeout)*1000;
            } catch (NumberFormatException nfe) {
              // use default
            }
        }
        return DEFAULT_READ_TIMEOUT;
    }
    if (SVN_SSH.equals(protocol)) {
      return (int) getConfig().mySSHReadTimeout;
    }
    return 0;
  }

  @Override
  public int getConnectTimeout(SVNRepository repository) {
    String protocol = repository.getLocation().getProtocol();
    if (SVN_SSH.equals(protocol)) {
      return (int) getConfig().mySSHConnectionTimeout;
    }
    final int connectTimeout = super.getConnectTimeout(repository);
    if ((HTTP.equals(protocol) || HTTPS.equals(protocol)) && (connectTimeout <= 0)) {
      return DEFAULT_READ_TIMEOUT;
    }
    return connectTimeout;
  }

  // taken from default manager as is
  private String getServersPropertyIdea(String host, final String name) {
    final SVNCompositeConfigFile serversFile = getHostOptionsProvider().getServersFile();
    return getPropertyIdea(host, serversFile, name);
  }

  private String getPropertyIdea(String host, SVNCompositeConfigFile serversFile, final String name) {
    String groupName = getGroupName(serversFile.getProperties("groups"), host);
    if (groupName != null) {
      Map hostProps = serversFile.getProperties(groupName);
      final String value = (String)hostProps.get(name);
      if (value != null) {
        return value;
      }
    }
    Map globalProps = serversFile.getProperties("global");
    return (String) globalProps.get(name);
  }

  public static boolean checkHostGroup(final String url, final String patterns, final String exceptions) {
    final SVNURL svnurl;
    try {
      svnurl = SVNURL.parseURIEncoded(url);
    }
    catch (SVNException e) {
      return false;
    }

    final String host = svnurl.getHost();
    return matches(patterns, host) && (! matches(exceptions, host));
  }

  private static boolean matches(final String pattern, final String host) {
    final StringTokenizer tokenizer = new StringTokenizer(pattern, ",");
    while(tokenizer.hasMoreTokens()) {
      String token = tokenizer.nextToken();
      if (DefaultSVNOptions.matches(token, host)) {
          return true;
      }
    }
    return false;
  }

  @Nullable
  public static String getGroupForHost(final String host, final IdeaSVNConfigFile serversFile) {
    final Map<String,ProxyGroup> groups = serversFile.getAllGroups();
    for (Map.Entry<String, ProxyGroup> entry : groups.entrySet()) {
      if (matchesGroupPattern(host, entry.getValue().getPatterns())) return entry.getKey();
    }
    return null;
  }

  // taken from default manager as is
  private static String getGroupName(Map groups, String host) {
    for (Object o : groups.keySet()) {
      final String name = (String) o;
      final String pattern = (String) groups.get(name);
      if (matchesGroupPattern(host, pattern)) return name;
    }
      return null;
  }

  private static boolean matchesGroupPattern(String host, String pattern) {
    for(StringTokenizer tokens = new StringTokenizer(pattern, ","); tokens.hasMoreTokens();) {
        String token = tokens.nextToken();
        if (DefaultSVNOptions.matches(token, host)) {
          return true;
        }
    }
    return false;
  }

  // default = yes
  private static boolean isTurned(final String value) {
    return value == null || "yes".equalsIgnoreCase(value) || "on".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value);
  }

  private ModalityState getCurrent() {
    if (ApplicationManager.getApplication().isDispatchThread()) {
      return ModalityState.current();
    }
    final ProgressIndicator pi = ProgressManager.getInstance().getProgressIndicator();
    if (pi == null) {
      return ModalityState.defaultModalityState();
    }
    return pi.getModalityState();
  }

  /**
   * Shows a yes/no question whether user wants to store his password in plain text and returns his answer.
   * @param title   title of the questioning dialog.
   * @param message questioning message to be displayed.
   * @return true if user agrees to store his password in plaintext, false if he doesn't.
   */
  @CalledInAwt
  private boolean askToStoreUnencrypted(String title, String message) {
    final int answer = Messages.showYesNoDialog(myProject, message, title, Messages.getQuestionIcon());
    return answer == 0;
  }

  public void setInteraction(SvnAuthenticationInteraction interaction) {
    myInteraction = interaction;
  }

  private static class MySvnAuthenticationInteraction implements SvnAuthenticationInteraction {
    private Project myProject;

    private MySvnAuthenticationInteraction(Project project) {
      myProject = project;
    }

    @Override
    public void warnOnAuthStorageDisabled(SVNURL url) {
      VcsBalloonProblemNotifier.showOverChangesView(myProject, "Cannot store credentials: forbidden by \"store-auth-creds=no\"", MessageType.ERROR);
    }

    @Override
    public void warnOnPasswordStorageDisabled(SVNURL url) {
      VcsBalloonProblemNotifier.showOverChangesView(myProject, "Cannot store password: forbidden by \"store-passwords=no\"", MessageType.ERROR);
    }

    @Override
    public void warnOnSSLPassphraseStorageDisabled(SVNURL url) {
      VcsBalloonProblemNotifier.showOverChangesView(myProject, "Cannot store passphrase: forbidden by \"store-ssl-client-cert-pp=no\"", MessageType.ERROR);
    }

    @Override
    public boolean promptForPlaintextPasswordSaving(SVNURL url, String realm) {
      final int answer = Messages.showYesNoDialog(myProject, String.format("Your password for authentication realm:\n" +
        "%s\ncan only be stored to disk unencrypted. Would you like to store it in plaintext?", realm),
        "Store the password in plaintext?", Messages.getQuestionIcon());
      return answer == 0;
    }

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

    @Override
    public boolean promptForSSLPlaintextPassphraseSaving(SVNURL url, String realm, File certificateFile, String certificateName) {
      final int answer = Messages.showYesNoDialog(myProject,
        String.format("Your passphrase for " + certificateName + ":\n%s\ncan only be stored to disk unencrypted. Would you like to store it in plaintext?",
                                                            certificateFile.getPath()),
        "Store the passphrase in plaintext?", Messages.getQuestionIcon());
      return answer == 0;
    }

    @Override
    public void dispose() {
      myProject = null;
    }
  }

  private static boolean isLion() {
    return SystemInfo.isMac && SystemInfo.isMacOSSnowLeopard && ! SystemInfo.OS_VERSION.startsWith("10.6");
  }

  public class IdeaSVNHostOptionsProvider extends DefaultSVNHostOptionsProvider {
    public IdeaSVNHostOptionsProvider() {
      super(myConfigDirectory);
    }

    @Override
    public SVNCompositeConfigFile getServersFile() {
      return super.getServersFile();
    }

    @Override
    public ISVNHostOptions getHostOptions(SVNURL url) {
      return new IdeaSVNHostOptions(getServersFile(), url);
    }
  }

  private static class ThreadLocalSavePermissions {
    private final Map<Thread, Boolean> myPlainTextAllowed;

    private ThreadLocalSavePermissions() {
      myPlainTextAllowed = Collections.synchronizedMap(new HashMap<Thread, Boolean>());
    }

    public void put(final boolean value) {
      myPlainTextAllowed.put(Thread.currentThread(), value);
    }

    public boolean have() {
      return myPlainTextAllowed.containsKey(Thread.currentThread());
    }

    public void remove() {
      myPlainTextAllowed.remove(Thread.currentThread());
    }

    public boolean allowed() {
      return Boolean.TRUE.equals(myPlainTextAllowed.get(Thread.currentThread()));
    }
  }

  private class IdeaSVNHostOptions extends DefaultSVNHostOptions {
    private SVNCompositeConfigFile myConfigFile;
    private final SVNURL myUrl;

    private IdeaSVNHostOptions(SVNCompositeConfigFile serversFile, SVNURL url) {
      super(serversFile, url);
      myUrl = url;
    }

    @Override
    public boolean isStorePlainTextPasswords(final String realm, SVNAuthentication auth) throws SVNException {
      if (USERNAME.equals(auth.getKind())) return true;

      final boolean superValue = super.isStorePlainTextPasswords(realm, auth);
      final boolean value = mySavePermissions.allowed() || superValue;
      if ((! value) && (! mySavePermissions.have())) {
        promptAndSaveWhenWeLackEncryption(realm, auth, new Getter<Boolean>() {
                                                @Override
                                                public Boolean get() {
                                                  return myInteraction.promptForPlaintextPasswordSaving(myUrl, realm);
                                                }
                                              });
      }
      return value;
    }

    @Override
    public boolean isStorePlainTextPassphrases(final String realm, final SVNAuthentication auth) throws SVNException {
      if (USERNAME.equals(auth.getKind())) return true;

      final boolean value = mySavePermissions.allowed() || super.isStorePlainTextPassphrases(realm, auth);
      if ((! value) && (! mySavePermissions.have())) {
        promptAndSaveWhenWeLackEncryption(realm, auth, new Getter<Boolean>() {
                                                @Override
                                                public Boolean get() {
                                                  File file = null;
                                                  String certificateName = null;
                                                  if (auth instanceof SVNSSLAuthentication) {
                                                    file = ((SVNSSLAuthentication) auth).getCertificateFile();
                                                    certificateName = "client certificate";
                                                  } else if (auth instanceof SVNSSHAuthentication) {
                                                    file = ((SVNSSHAuthentication) auth).getPrivateKeyFile();
                                                    certificateName = "private key file";
                                                  } else {
                                                    assert false;
                                                  }
                                                  return myInteraction.promptForSSLPlaintextPassphraseSaving(myUrl, realm,
                                                           file, certificateName);
                                                }
                                              });
      }
      return value;
    }

    @Override
    public boolean isAuthStorageEnabled() {
      final boolean value;
      if (hasAuthStorageEnabledOption()) {
        value = super.isAuthStorageEnabled();
      } else {
        value = isTurned(getConfigFile().getPropertyValue("auth", "store-auth-creds"));
      }
      if (! value) {
        myInteraction.warnOnAuthStorageDisabled(myUrl);
      }
      return value;
    }

    @Override
    public boolean isStorePasswords() {
      final String storePasswords = getStorePasswords();
      final boolean value;
      if (storePasswords != null) {
        value = isTurned(storePasswords);
      } else {
        final String configValue = getConfigFile().getPropertyValue("auth", "store-passwords");
        value = isTurned(configValue);
      }
      if (! value) {
        myInteraction.warnOnPasswordStorageDisabled(myUrl);
      }
      return value;
    }

    @Override
    public boolean isStoreSSLClientCertificatePassphrases() {
      final boolean value = super.isStoreSSLClientCertificatePassphrases();
      if (! value) {
        myInteraction.warnOnSSLPassphraseStorageDisabled(myUrl);
      }
      return value;
    }

    public String getStorePasswords() {
      return getServersPropertyIdea(getHost(), "store-passwords");
    }

    private SVNCompositeConfigFile getConfigFile() {
      if (myConfigFile == null) {
        final File config = new File(myConfigDirectory, "config");
        SVNConfigFile.createDefaultConfiguration(myConfigDirectory);
        SVNConfigFile userConfig = new SVNConfigFile(config);
        SVNConfigFile systemConfig = new SVNConfigFile(new File(SVNFileUtil.getSystemConfigurationDirectory(), "config"));
        myConfigFile = new SVNCompositeConfigFile(systemConfig, userConfig);
      }
      return myConfigFile;
    }

    private void promptAndSaveWhenWeLackEncryption(final String realm, final SVNAuthentication auth, final Getter<Boolean> prompt) {
      final Boolean[] saveOnce = new Boolean[1];
      final Runnable actualSave = new Runnable() {
        @Override
        public void run() {
          mySavePermissions.put(Boolean.TRUE.equals(saveOnce[0]));
          try {
            myPersistentAuthenticationProviderProxy.actualSavePermissions(realm, auth);
          }
          finally {
            mySavePermissions.remove();
          }
        }
      };

      if (myInteraction.promptInAwt()) {
        new AbstractCalledLater(myProject, getCurrent()) {
          @Override
          public void run() {
            saveOnce[0] = Boolean.TRUE.equals(prompt.get());
            ApplicationManager.getApplication().executeOnPooledThread(actualSave);
          }
        }.callMe();
      } else {
        saveOnce[0] = Boolean.TRUE.equals(prompt.get());
        actualSave.run();
      }
    }
  }

  private static class ProxyPasswordStorageForDebug implements DefaultSVNPersistentAuthenticationProvider.IPasswordStorage {
    private final DefaultSVNPersistentAuthenticationProvider.IPasswordStorage myDelegate;
    private final EventDispatcher<SvnAuthenticationListener> myListener;

    public ProxyPasswordStorageForDebug(final DefaultSVNPersistentAuthenticationProvider.IPasswordStorage delegate,
                                        final EventDispatcher<SvnAuthenticationListener> listener) {
      myDelegate = delegate;
      myListener = listener;
    }

    @Override
    public String getPassType() {
      return myDelegate.getPassType();
    }

    @Override
    public boolean savePassword(String realm, String password, SVNAuthentication auth, SVNProperties authParameters) throws SVNException {
      final boolean saved = myDelegate.savePassword(realm, password, auth, authParameters);
      if (saved) {
        myListener.getMulticaster().actualSaveWillBeTried(ProviderType.persistent, auth.getURL(), realm, auth.getKind()
        );
      }
      return saved;
    }

    @Override
    public String readPassword(String realm, String userName, SVNProperties authParameters) throws SVNException {
      return myDelegate.readPassword(realm, userName, authParameters);
    }

    @Override
    public boolean savePassphrase(String realm, String passphrase, SVNAuthentication auth, SVNProperties authParameters, boolean force)
      throws SVNException {
      final boolean saved = myDelegate.savePassphrase(realm, passphrase, auth, authParameters, force);
      if (saved) {
        myListener.getMulticaster().actualSaveWillBeTried(ProviderType.persistent, auth.getURL(), realm, auth.getKind()
        );
      }
      return saved;
    }

    @Override
    public String readPassphrase(String realm, SVNProperties authParameters) throws SVNException {
      return myDelegate.readPassphrase(realm, authParameters);
    }
  }

  private <T> T wrapNativeCall(final ThrowableComputable<T, SVNException> runnable) throws SVNException {
    try {
      NativeLogReader.startTracking();
      final T t = runnable.compute();
      final List<NativeLogReader.CallInfo> logged = NativeLogReader.getLogged();
      final StringBuilder sb = new StringBuilder();
      for (NativeLogReader.CallInfo info : logged) {
        final String message = SvnNativeCallsTranslator.getMessage(info);
        if (message != null) {
          if (sb.length() > 0) sb.append('\n');
          sb.append(message);
        }
      }
      if (sb.length() > 0) {
        VcsBalloonProblemNotifier.showOverChangesView(myProject, sb.toString(), MessageType.ERROR);
        LOG.info(sb.toString());
      }
      return t;
    } finally {
      NativeLogReader.clear();
      NativeLogReader.endTracking();
    }
  }

  private static class MyKeyringMasterKeyProvider implements ISVNGnomeKeyringPasswordProvider {
    private Project myProject;

    public MyKeyringMasterKeyProvider(Project project) {
      myProject = project;
    }

    @Override
    public String getKeyringPassword(final String keyringName) throws SVNException {
      final String message = keyringName != null ? SvnBundle.message("gnome.keyring.prompt.named", keyringName)
                                                 : SvnBundle.message("gnome.keyring.prompt.nameless");
      final Ref<String> result = Ref.create();
      UIUtil.invokeAndWaitIfNeeded(new Runnable() {
        @Override
        public void run() {
          result.set(Messages.showPasswordDialog(myProject, message, SvnBundle.message("subversion.name"), Messages.getQuestionIcon()));
        }
      });
      return result.get();
    }
  }

  public static class CredentialsSavedException extends RuntimeException {
    private final boolean mySuccess;

    public CredentialsSavedException(boolean success) {
      mySuccess = success;
    }

    public boolean isSuccess() {
      return mySuccess;
    }
  }
}
