/*******************************************************************************
 * Copyright (c) 2004, 2006 Subclipse project and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Subclipse project committers - initial API and implementation
 ******************************************************************************/
package org.tigris.subversion.subclipse.core;

import java.io.File;
import java.util.HashMap;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.tigris.subversion.clientadapter.Activator;
import org.tigris.subversion.svnclientadapter.ISVNClientAdapter;
import org.tigris.subversion.svnclientadapter.SVNClientException;

/**
 * Handles the creation of SVNClients
 * 
 * @author Cedric Chabanois (cchab at tigris.org) 
 */
public class SVNClientManager {
    private String svnClientInterface;
    private String svnAdminDir = ".svn";
    private File configDir = null;
    private boolean fetchChangePathOnDemand = true;
    private HashMap<String, ISVNClientAdapter> clients = new HashMap<String, ISVNClientAdapter>();
    
    public static final String UNABLE_TO_LOAD_DEFAULT_CLIENT = "Unable to load default SVN Client";
    
    public void startup(IProgressMonitor monitor) throws CoreException {
    }
    
    
	public void shutdown(IProgressMonitor monitor) throws CoreException {
	}

    /**
     * set the client interface to use
     * 
     * @param svnClientInterface
     */
    public void setSvnClientInterface(String svnClientInterface) {
    	this.svnClientInterface = svnClientInterface;
    }

    /**
     * get the current svn client interface used
     * @return
     */
    public String getSvnClientInterface() {
        return svnClientInterface;
    }    
    
    public String getSvnAdminDirectory() {
    	return svnAdminDir;
    }
    
	/**
	 * @param configDir The configDir to set.
	 */
	public void setConfigDir(File configDir) {
		this.configDir = configDir;
//		if (configDir == null) return;
		// Update configDir in stored clients
		Set<String> keys = clients.keySet();
		for (String key : keys) {
	    	ISVNClientAdapter svnClient = clients.get(key);
	    	if (svnClient != null) {
	    		try {
					svnClient.setConfigDirectory(configDir);
				} catch (SVNClientException e) {
					break;
				}
	    	}
		}
	}
    
    /**
     * @return the cached ISVNClientAdapter for the client interface
     * @throws SVNClientException
     */
    public ISVNClientAdapter getSVNClient() throws SVNException {
    	ISVNClientAdapter svnClient = this.getAdapter(svnClientInterface);
    	if (svnClient == null) {
    		svnClient = this.getAdapter(null);
    	}
    	if (svnClient == null)
    		throw new SVNException("No client adapters available.");
    	return svnClient;
    }

    
    /**
     * @return a new ISVNClientAdapter for the client interface
     *         Caller must call {@link ISVNClientAdapter#dispose()}
     *         when they are done with it.
     * @throws SVNClientException
     */
    public ISVNClientAdapter createSVNClient() throws SVNException {
    	ISVNClientAdapter svnClient = this.getAdapter(svnClientInterface);
  		svnClient = Activator.getDefault().getClientAdapter(svnClientInterface);
   		if (svnClient == null) {
   			svnClient = Activator.getDefault().getAnyClientAdapter();
	    	if (svnClient == null)
	    		throw new SVNException("No client adapters available.");
   		}
   		setupClientAdapter(svnClient);
    	return svnClient;
    }

	private void setupClientAdapter(ISVNClientAdapter svnClient)
			throws SVNException {
		if (configDir != null) {
    		try {
				svnClient.setConfigDirectory(configDir);
			} catch (SVNClientException e) {
	        	throw SVNException.wrapException(e);
			}
    	} 
    	if (SVNProviderPlugin.getPlugin().getSvnPromptUserPassword() != null)
    	    svnClient.addPasswordCallback(SVNProviderPlugin.getPlugin().getSvnPromptUserPassword());
    	svnAdminDir = svnClient.getAdminDirectoryName();
	}
    
    private ISVNClientAdapter getAdapter(String key) throws SVNException {
    	ISVNClientAdapter client = null;
    	if (key == null) {
    		key = "default";
     	}
    	client = (ISVNClientAdapter) clients.get(key);
    	if (client == null) {
    		if (!key.equals("default"))
    			client = Activator.getDefault().getClientAdapter(svnClientInterface);
    		
    		if (client == null)
    			client = Activator.getDefault().getAnyClientAdapter();
    		
    		if (client == null)
    			throw new SVNException(UNABLE_TO_LOAD_DEFAULT_CLIENT);
    		
    		setupClientAdapter(client);
    		if (client.isThreadsafe())
    			clients.put(key, client);
    	}
    	return client;
    }

	/**
	 * @return Returns the fetchChangePathOnDemand.
	 */
	public boolean isFetchChangePathOnDemand() {
		return fetchChangePathOnDemand;
	}
	/**
	 * @param fetchChangePathOnDemand The fetchChangePathOnDemand to set.
	 */
	
	public void setFetchChangePathOnDemand(
			boolean fetchChangePathOnDemand) {
		this.fetchChangePathOnDemand = fetchChangePathOnDemand;
	}
	
}

@@ -3043,716 +3043,8 @@
  %7D%0A%0A
-    %0A    /**%0A     * @return a new ISVNClientAdapter for the client interface%0A     *         Caller must call %7B@link ISVNClientAdapter#dispose()%7D%0A     *         when they are done with it.%0A     * @throws SVNClientException%0A     */%0A    public ISVNClientAdapter createSVNClient() throws SVNException %7B%0A    %09ISVNClientAdapter svnClient = this.getAdapter(svnClientInterface);%0A  %09%09svnClient = Activator.getDefault().getClientAdapter(svnClientInterface);%0A   %09%09if (svnClient == null) %7B%0A   %09%09%09svnClient = Activator.getDefault().getAnyClientAdapter();%0A%09    %09if (svnClient == null)%0A%09    %09%09throw new SVNException(%22No client adapters available.%22);%0A   %09%09%7D%0A   %09%09setupClientAdapter(svnClient);%0A    %09return svnClient;%0A    %7D%0A%0A
 %09pri
@@ -4597,10 +4597,249 @@
 d;%0A%09%7D%0A%09%0A
+%09public void returnSVNClient(ISVNClientAdapter client) %7B%0A%09%09if (client.isThreadsafe())%0A%09%09%09return;%0A%09%09// For non-threadsafe clients we are done with the object so %0A%09%09// let it clean up any resources it has allocated.%0A%09%09client.dispose();%0A%09%7D%0A%09%0A
 %7D%0A

Remove unused method and add new method to cleanup svnclient when no longer used.