/*******************************************************************************
 * Copyright (c) 2000, 2012 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Sebastian Davids <sdavids@gmx.de> - bug 74959
 *     Maik Schreiber - bug 102461
 *     William Mitsuda (wmitsuda@gmail.com) - Bug 153879 [Wizards] configurable size of cvs commit comment history
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.repo;


import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

import javax.xml.parsers.*;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.window.Window;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation;
import org.eclipse.team.internal.ccvs.core.util.KnownRepositories;
import org.eclipse.team.internal.ccvs.ui.*;
import org.eclipse.team.internal.ccvs.ui.Policy;
import org.eclipse.ui.IWorkingSet;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * This class is repsible for maintaining the UI's list of known repositories,
 * and a list of known tags within each of those repositories.
 * 
 * It also provides a number of useful methods for assisting in repository operations.
 */
public class RepositoryManager {
	// old state file
	private static final String STATE_FILE = ".repositoryManagerState"; //$NON-NLS-1$
	private static final int STATE_FILE_VERSION_1 = -1;
	// new state file
	private static final String REPOSITORIES_VIEW_FILE = "repositoriesView.xml"; //$NON-NLS-1$
	private static final String COMMENT_HIST_FILE = "commitCommentHistory.xml"; //$NON-NLS-1$
	private static final String COMMENT_TEMPLATES_FILE = "commentTemplates.xml"; //$NON-NLS-1$
	static final String ELEMENT_COMMIT_COMMENT = "CommitComment"; //$NON-NLS-1$
	static final String ELEMENT_COMMIT_HISTORY = "CommitComments"; //$NON-NLS-1$
	static final String ELEMENT_COMMENT_TEMPLATES = "CommitCommentTemplates"; //$NON-NLS-1$

	private Map<String, RepositoryRoot> repositoryRoots = new HashMap<>();
	
	List<IRepositoryListener> listeners = new ArrayList<>();

	// The previously remembered comment
	static String[] previousComments = new String[0];
	static String[] commentTemplates = new String[0];
	
	public static boolean notifyRepoView = true;
	
	// Cache of changed repository roots
	private int notificationLevel = 0;
	private Map<String, ICVSRepositoryLocation> changedRepositories = new HashMap<>();
	
	public static final int DEFAULT_MAX_COMMENTS = 10;
	
	private int maxComments = DEFAULT_MAX_COMMENTS;
	
	public void setMaxComments(int maxComments) {
		if (maxComments > 0) {
			this.maxComments = maxComments;
			if (maxComments < previousComments.length) {
				String[] newComments = new String[maxComments];
				System.arraycopy(previousComments, 0, newComments, 0, maxComments);
				previousComments = newComments;
			}
		}
	}
	
	/**
	 * Answer an array of all known remote roots.
	 */
	public ICVSRepositoryLocation[] getKnownRepositoryLocations() {
		return KnownRepositories.getInstance().getRepositories();
	}
	
	/**
	 * Method getRepositoryRoots.
	 * @param iCVSRepositoryLocations
	 * @return RepositoryRoot[]
	 */
	private RepositoryRoot[] getRepositoryRoots(ICVSRepositoryLocation[] locations) {
		List<RepositoryRoot> roots = new ArrayList<>();
		for (int i = 0; i < locations.length; i++) {
			ICVSRepositoryLocation location = locations[i];
			RepositoryRoot root = getRepositoryRootFor(location);
			if (root != null)
				roots.add(root);
		}
		return roots.toArray(new RepositoryRoot[roots.size()]);
	}
	
	public RepositoryRoot[] getKnownRepositoryRoots() {
		return getRepositoryRoots(getKnownRepositoryLocations());
	}
	
	/**
	 * Get the list of known branch tags for a given remote root.
	 */
	public CVSTag[] getKnownTags(ICVSFolder project, int tagType) {
		try {
			CVSTag[] tags = getKnownTags(project);
			Set<CVSTag> result = new HashSet<>();
			for (int i = 0; i < tags.length; i++) {
				CVSTag tag = tags[i];
				if (tag.getType() == tagType)
					result.add(tag);
			}

			return result.toArray(new CVSTag[result.size()]);
		} catch(CVSException e) {
			CVSUIPlugin.log(e);
			return new CVSTag[0];
		}
	}
	
	/**
	 * Get the list of known version tags for a given project.
	 */
	public CVSTag[] getKnownTags(ICVSRepositoryLocation location, int tagType) {
		Set<CVSTag> result = new HashSet<>();
		RepositoryRoot root = repositoryRoots.get(location.getLocation(false));
		if (root != null) {
			CVSTag[] tags = root.getAllKnownTags();
			for (int i = 0; i < tags.length; i++) {
				CVSTag tag = tags[i];
				if (tag.getType() == tagType)
					result.add(tag);
			}
		}
		return result.toArray(new CVSTag[0]);
	}
	
	/**
	 * Method getKnownTags.
	 * @param repository
	 * @param set
	 * @param i
	 * @param monitor
	 * @return CVSTag[]
	 */
	public CVSTag[] getKnownTags(ICVSRepositoryLocation repository, IWorkingSet set, int tagType, IProgressMonitor monitor) throws CVSException {
		if (set == null) {
			return getKnownTags(repository, tagType);
		}
		ICVSRemoteResource[] folders = getFoldersForTag(repository, CVSTag.DEFAULT, monitor);
		folders = filterResources(set, folders);
		Set<CVSTag> tags = new HashSet<>();
		for (int i = 0; i < folders.length; i++) {
			ICVSRemoteFolder folder = (ICVSRemoteFolder)folders[i];
			tags.addAll(Arrays.asList(getKnownTags(folder, tagType)));
		}
		return tags.toArray(new CVSTag[tags.size()]);
	}
	
	public CVSTag[] getKnownTags(ICVSFolder project) throws CVSException {
		RepositoryRoot root = getRepositoryRootFor(project);
		String remotePath = RepositoryRoot.getRemotePathFor(project);
		return root.getAllKnownTags(remotePath);
	}
	
	/*
	 * XXX I hope this methos is not needed in this form
	 */
	public Map getKnownProjectsAndVersions(ICVSRepositoryLocation location) {
		Map<String, Set<CVSTag>> knownTags = new HashMap<>();
		RepositoryRoot root = getRepositoryRootFor(location);
		String[] paths = root.getKnownRemotePaths();
		for (int i = 0; i < paths.length; i++) {
			String path = paths[i];
			Set<CVSTag> result = new HashSet<>();
			result.addAll(Arrays.asList(root.getAllKnownTags(path)));
			knownTags.put(path, result);
		}
		return knownTags;
	}
	
	public ICVSRemoteResource[] getFoldersForTag(ICVSRepositoryLocation location, CVSTag tag, IProgressMonitor monitor) throws CVSException {		
		monitor = Policy.monitorFor(monitor);
		try {
			monitor.beginTask(NLS.bind(CVSUIMessages.RepositoryManager_fetchingRemoteFolders, new String[] { tag.getName() }), 100); 
			if (tag.getType() == CVSTag.HEAD) {
				ICVSRemoteResource[] resources = location.members(tag, false, Policy.subMonitorFor(monitor, 60));
				RepositoryRoot root = getRepositoryRootFor(location);
				ICVSRemoteResource[] modules = root.getDefinedModules(tag, Policy.subMonitorFor(monitor, 40));
				ICVSRemoteResource[] result = new ICVSRemoteResource[resources.length + modules.length];
				System.arraycopy(resources, 0, result, 0, resources.length);
				System.arraycopy(modules, 0, result, resources.length, modules.length);
				return result;
			}
			if (tag.getType() == CVSTag.DATE) {
				ICVSRemoteResource[] resources = location.members(tag, false, Policy.subMonitorFor(monitor, 60));
				RepositoryRoot root = getRepositoryRootFor(location);
				ICVSRemoteResource[] modules = root.getDefinedModules(tag, Policy.subMonitorFor(monitor, 40));
				ICVSRemoteResource[] result = new ICVSRemoteResource[resources.length + modules.length];
				System.arraycopy(resources, 0, result, 0, resources.length);
				System.arraycopy(modules, 0, result, resources.length, modules.length);
				return result;
			}
			Set<ICVSRemoteFolder> result = new HashSet<>();
			// Get the tags for the location
			RepositoryRoot root = getRepositoryRootFor(location);
			String[] paths = root.getRemoteChildrenForTag(null, tag);
			for (int i = 0; i < paths.length; i++) {
				String path = paths[i];
				ICVSRemoteFolder remote = root.getRemoteFolder(path, tag,
						Policy.subMonitorFor(monitor, 100));
				result.add(remote);
			}
			return result.toArray(new ICVSRemoteResource[result.size()]);
		} finally {
			monitor.done();
		}
	}

	/**
	 * Returns a list of child resources for given folder that are known to
	 * contain given tag. If the return list is empty than given tag exists
	 * directly in given folder and its children should be retrieved directly
	 * from the repository.
	 *
	 * NOTE: Resources are cached only for tags of type CVSTag.Branch and
	 * CVSTag.Version. Other types of tags will always return empty list.
	 *
	 * @param location
	 *            CVS repository location
	 * @param parentFolder
	 *            folder to check tags for
	 * @param tag
	 * @param monitor
	 * @return a list of remote resources that are known to contain given tag or
	 *         empty list if resources should be retrieved from the repository
	 * @throws CVSException
	 */
	public ICVSRemoteResource[] getCachedChildrenForTag(
			ICVSRepositoryLocation location, ICVSRemoteFolder parentFolder,
			CVSTag tag, IProgressMonitor monitor) throws CVSException {
		if (tag == null || tag.getType() == CVSTag.HEAD
				|| tag.getType() == CVSTag.DATE) {
			// folders are kept in cache only for tags and versions
			return new ICVSRemoteResource[0];
		}
		monitor = Policy.monitorFor(monitor);
		Set<ICVSRemoteFolder> result = new HashSet<>();
		RepositoryRoot root = getRepositoryRootFor(location);
		// if remote folder is null return the subfolders of repository root
		String[] paths = root.getRemoteChildrenForTag(
				parentFolder == null ? null : RepositoryRoot
						.getRemotePathFor(parentFolder), tag);
		monitor.beginTask(NLS
				.bind(CVSUIMessages.RemoteFolderElement_fetchingRemoteChildren,
						new String[] { NLS.bind(
								CVSUIMessages.RemoteFolderElement_nameAndTag,
								new String[] { parentFolder.getName(),
										tag.getName() }) }), 10 * paths.length);
		try {
			for (int i = 0; i < paths.length; i++) {
				String path = paths[i];
				ICVSRemoteFolder remote = root.getRemoteFolder(path, tag,
						Policy.subMonitorFor(monitor, 10));
				result.add(remote);
			}
			return result
					.toArray(new ICVSRemoteResource[result.size()]);
		} finally {
			monitor.done();
		}
	}
		
	/*
	 * Fetches tags from auto-refresh files if they exist. Then fetches tags from the user defined auto-refresh file
	 * list. The fetched tags are cached in the CVS ui plugin's tag cache.
	 */
	public CVSTag[] refreshDefinedTags(ICVSFolder folder, boolean recurse, boolean notify, IProgressMonitor monitor) throws TeamException {
		RepositoryRoot root = getRepositoryRootFor(folder);
		CVSTag[] tags = root.refreshDefinedTags(folder, recurse, monitor);
		if (tags.length > 0 && notify)
			broadcastRepositoryChange(root);
		return tags;
	}
	
	/**
	 * A repository root has been added. Notify any listeners.
	 */
	public void rootAdded(ICVSRepositoryLocation root) {
		Iterator it = listeners.iterator();
		while (it.hasNext()) {
			IRepositoryListener listener = (IRepositoryListener)it.next();
			listener.repositoryAdded(root);
		}
	}
	
	/**
	 * A repository root has been removed.
	 * Remove the tags defined for this root and notify any listeners
	 */
	public void rootRemoved(ICVSRepositoryLocation root) {
		RepositoryRoot repoRoot = repositoryRoots.remove(root.getLocation(false));
		if (repoRoot != null)
			broadcastRepositoryChange(repoRoot);
	}
	
	/**
	 * Accept tags for any CVS resource. However, for the time being,
	 * the given version tags are added to the list of known tags for the 
	 * remote ancestor of the resource that is a direct child of the remote root
	 */
	public void addTags(ICVSResource resource, CVSTag[] tags) throws CVSException {
		RepositoryRoot root = getRepositoryRootFor(resource);
		// XXX could be a file or folder
		String remotePath = RepositoryRoot.getRemotePathFor(resource);
		root.addTags(remotePath, tags);
		broadcastRepositoryChange(root);
	}
	public void addDateTag(ICVSRepositoryLocation location, CVSTag tag) {
		if(tag == null) return;
		RepositoryRoot root = getRepositoryRootFor(location);
		root.addDateTag(tag);
		broadcastRepositoryChange(root);
	}
	public CVSTag[] getDateTags(ICVSRepositoryLocation location) {
		RepositoryRoot root = getRepositoryRootFor(location);
		return root.getDateTags();
	}
	public void removeDateTag(ICVSRepositoryLocation location, CVSTag tag){
		RepositoryRoot root = getRepositoryRootFor(location);
		root.removeDateTag(tag);
		broadcastRepositoryChange(root);
	}
	public void setAutoRefreshFiles(ICVSFolder project, String[] filePaths) throws CVSException {
		RepositoryRoot root = getRepositoryRootFor(project);
		String remotePath = RepositoryRoot.getRemotePathFor(project);
		root.setAutoRefreshFiles(remotePath, filePaths);
	}
	
	public String[] getAutoRefreshFiles(ICVSFolder project) throws CVSException {
		RepositoryRoot root = getRepositoryRootFor(project);
		String remotePath = RepositoryRoot.getRemotePathFor(project);
		return root.getAutoRefreshFiles(remotePath);
	}
	
	/**
	 * Remove the given tags from the list of known tags for the
	 * given remote root.
	 */
	public void removeTags(ICVSFolder project, CVSTag[] tags) throws CVSException {
		RepositoryRoot root = getRepositoryRootFor(project);
		String remotePath = RepositoryRoot.getRemotePathFor(project);
		root.removeTags(remotePath, tags);
		broadcastRepositoryChange(root);
	}
	
	public void startup() {
		loadState();
		loadCommentHistory();
		loadCommentTemplates();
		CVSProviderPlugin.getPlugin().addRepositoryListener(new ICVSListener() {
			@Override
			public void repositoryAdded(ICVSRepositoryLocation root) {
				rootAdded(root);
			}
			@Override
			public void repositoryRemoved(ICVSRepositoryLocation root) {
				rootRemoved(root);
			}
		});
		
		IPreferenceStore store = CVSUIPlugin.getPlugin().getPreferenceStore();
		store.addPropertyChangeListener(event -> {
			if (event.getProperty().equals(ICVSUIConstants.PREF_COMMIT_COMMENTS_MAX_HISTORY)) {
				Object newValue = event.getNewValue();
				if (newValue instanceof String) {
					try {
						setMaxComments(Integer.parseInt((String) newValue));
					} catch (NumberFormatException e) {
						// fail silently
					}
				}
			}
		});
		setMaxComments(store.getInt(ICVSUIConstants.PREF_COMMIT_COMMENTS_MAX_HISTORY));
	}
	
	public void shutdown() throws TeamException {
		saveState();
		saveCommentHistory();
		saveCommentTemplates();
	}
	
	private void loadState() {
		IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation().append(REPOSITORIES_VIEW_FILE);
		File file = pluginStateLocation.toFile();
		if (file.exists()) {
			try {
				BufferedInputStream is = new BufferedInputStream(new FileInputStream(file));
				try {
					readState(is);
				} finally {
					is.close();
				}
			} catch (IOException e) {
				CVSUIPlugin.log(IStatus.ERROR, CVSUIMessages.RepositoryManager_ioException, e); 
			} catch (TeamException e) {
				CVSUIPlugin.log(e);
			}
		} else {
			IPath oldPluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation().append(STATE_FILE);
			file = oldPluginStateLocation.toFile();
			if (file.exists()) {
				try {
					DataInputStream dis = new DataInputStream(new FileInputStream(file));
					try {
						readOldState(dis);
					} finally {
						dis.close();
					}
					saveState();
					file.delete();
				} catch (IOException e) {
					CVSUIPlugin.log(IStatus.ERROR, CVSUIMessages.RepositoryManager_ioException, e); 
				} catch (TeamException e) {
					CVSUIPlugin.log(e);
				}
			} 
		}
	}
	private void loadCommentHistory() {
		IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation().append(COMMENT_HIST_FILE);
		File file = pluginStateLocation.toFile();
		if (!file.exists()) return;
		try {
			BufferedInputStream is = new BufferedInputStream(new FileInputStream(file));
			try {
				readCommentHistory(is);
			} finally {
				is.close();
			}
		} catch (IOException e) {
			CVSUIPlugin.log(IStatus.ERROR, CVSUIMessages.RepositoryManager_ioException, e); 
		} catch (TeamException e) {
			CVSUIPlugin.log(e);
		}
	}
	private void loadCommentTemplates() {
		IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation().append(COMMENT_TEMPLATES_FILE);
		File file = pluginStateLocation.toFile();
		if (!file.exists()) return;
		try {
			BufferedInputStream is = new BufferedInputStream(new FileInputStream(file));
			try {
				readCommentTemplates(is);
			} finally {
				is.close();
			}
		} catch (IOException e) {
			CVSUIPlugin.log(IStatus.ERROR, CVSUIMessages.RepositoryManager_ioException, e);
		} catch (TeamException e) {
			CVSUIPlugin.log(e);
		}
	}
	
	protected void saveState() throws TeamException {
		IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation();
		File tempFile = pluginStateLocation.append(REPOSITORIES_VIEW_FILE + ".tmp").toFile(); //$NON-NLS-1$
		File stateFile = pluginStateLocation.append(REPOSITORIES_VIEW_FILE).toFile();
		try {
			XMLWriter writer = new XMLWriter(new BufferedOutputStream(new FileOutputStream(tempFile)));
			try {
				writeState(writer);
			} finally {
				writer.close();
			}
			if (stateFile.exists()) {
				stateFile.delete();
			}
			boolean renamed = tempFile.renameTo(stateFile);
			if (!renamed) {
				throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID, TeamException.UNABLE, NLS.bind(CVSUIMessages.RepositoryManager_rename, new String[] { tempFile.getAbsolutePath() }), null)); 
			}
		} catch (IOException e) {
			throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID, TeamException.UNABLE, NLS.bind(CVSUIMessages.RepositoryManager_save, new String[] { stateFile.getAbsolutePath() }), e)); 
		}
	}
	private void writeState(XMLWriter writer) {
		writer.startTag(RepositoriesViewContentHandler.REPOSITORIES_VIEW_TAG, null, true);
		// Write the repositories
		Collection repos = Arrays.asList(getKnownRepositoryLocations());
		Iterator it = repos.iterator();
		while (it.hasNext()) {
			CVSRepositoryLocation location = (CVSRepositoryLocation)it.next();
			RepositoryRoot root = getRepositoryRootFor(location);
			root.writeState(writer);
		}
		writer.endTag(RepositoriesViewContentHandler.REPOSITORIES_VIEW_TAG);
	}
	
	private void readState(InputStream stream) throws IOException, TeamException {
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
			parser.parse(new InputSource(stream), new RepositoriesViewContentHandler(this));
		} catch (SAXException ex) {
			IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSUIMessages.RepositoryManager_parsingProblem, new String[] { REPOSITORIES_VIEW_FILE }), ex);
			throw new CVSException(status); 
		} catch (ParserConfigurationException ex) {
			IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSUIMessages.RepositoryManager_parsingProblem, new String[] { REPOSITORIES_VIEW_FILE }), ex);
			throw new CVSException(status); 
		}
	}
	
	private void readCommentHistory(InputStream stream) throws IOException, TeamException {
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
			parser.parse(new InputSource(stream), new CommentHistoryContentHandler());
		} catch (SAXException ex) {
			IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSUIMessages.RepositoryManager_parsingProblem, new String[] { COMMENT_HIST_FILE }), ex);
			throw new CVSException(status); 
		} catch (ParserConfigurationException ex) {
			IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSUIMessages.RepositoryManager_parsingProblem, new String[] { COMMENT_HIST_FILE }), ex);
			throw new CVSException(status);  
		}
	}
	
	private void readOldState(DataInputStream dis) throws IOException, TeamException {
		int repoSize = dis.readInt();
		boolean version1 = false;
		if (repoSize == STATE_FILE_VERSION_1) {
			version1 = true;
			repoSize = dis.readInt();
		}
		for (int i = 0; i < repoSize; i++) {
			ICVSRepositoryLocation root = KnownRepositories.getInstance().getRepository(dis.readUTF());
			RepositoryRoot repoRoot = getRepositoryRootFor(root);
			
			// read branch tags associated with this root
			int tagsSize = dis.readInt();
			CVSTag[] branchTags = new CVSTag[tagsSize];
			for (int j = 0; j < tagsSize; j++) {
				String tagName = dis.readUTF();
				int tagType = dis.readInt();
				branchTags[j] = new CVSTag(tagName, tagType);
			}
			// Ignore the branch tags since they are handled differently now
			// addBranchTags(root, branchTags);
			
			// read the number of projects for this root that have version tags
			int projSize = dis.readInt();
			if (projSize > 0) {
				for (int j = 0; j < projSize; j++) {
					String name = dis.readUTF();
					Set<CVSTag> tagSet = new HashSet<>();
					int numTags = dis.readInt();
					for (int k = 0; k < numTags; k++) {
						tagSet.add(new CVSTag(dis.readUTF(), CVSTag.VERSION));
					}
					CVSTag[] tags = tagSet.toArray(new CVSTag[tagSet.size()]);
					repoRoot.addTags(name, tags);
				}
			}
			// read the auto refresh filenames for this project
			if (version1) {
				try {
					projSize = dis.readInt();
					if (projSize > 0) {
						for (int j = 0; j < projSize; j++) {
							String name = dis.readUTF();
							Set<String> filenames = new HashSet<>();
							int numFilenames = dis.readInt();
							for (int k = 0; k < numFilenames; k++) {
								filenames.add(name + "/" + dis.readUTF()); //$NON-NLS-1$
							}
							repoRoot.setAutoRefreshFiles(name, filenames.toArray(new String[filenames.size()]));
						}
					}
				} catch (EOFException e) {
					// auto refresh files are not persisted, continue and save them next time.
				}
			}
			broadcastRepositoryChange(repoRoot);
		}
	}
	
	protected void saveCommentHistory() throws TeamException {
		IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation();
		File tempFile = pluginStateLocation.append(COMMENT_HIST_FILE + ".tmp").toFile(); //$NON-NLS-1$
		File histFile = pluginStateLocation.append(COMMENT_HIST_FILE).toFile();
		try {
			XMLWriter writer = new XMLWriter(new BufferedOutputStream(new FileOutputStream(tempFile)));
			try {
				writeCommentHistory(writer);
			} finally {
				writer.close();
			}
			if (histFile.exists()) {
				histFile.delete();
			}
			boolean renamed = tempFile.renameTo(histFile);
			if (!renamed) {
				throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID, TeamException.UNABLE, NLS.bind(CVSUIMessages.RepositoryManager_rename, new String[] { tempFile.getAbsolutePath() }), null)); 
			}
		} catch (IOException e) {
			throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID, TeamException.UNABLE, NLS.bind(CVSUIMessages.RepositoryManager_save, new String[] { histFile.getAbsolutePath() }), e)); 
		}
	}
	private void writeCommentHistory(XMLWriter writer) {
		writer.startTag(ELEMENT_COMMIT_HISTORY, null, false);
		for (int i = 0; i < previousComments.length && i < maxComments; i++)
			writer.printSimpleTag(ELEMENT_COMMIT_COMMENT, previousComments[i]);
		writer.endTag(ELEMENT_COMMIT_HISTORY);
	}
		
	public void addRepositoryListener(IRepositoryListener listener) {
		listeners.add(listener);
	}
	
	public void removeRepositoryListener(IRepositoryListener listener) {
		listeners.remove(listener);
	}
	
	/**
	 * Return the entered comment or null if canceled.
	 * @param proposedComment
	 */
	public String promptForComment(final Shell shell, IResource[] resourcesToCommit, String proposedComment) {
		final int[] result = new int[1];
		final ReleaseCommentDialog dialog = new ReleaseCommentDialog(shell, resourcesToCommit, proposedComment, IResource.DEPTH_INFINITE); 
		shell.getDisplay().syncExec(() -> {
			result[0] = dialog.open();
			if (result[0] != Window.OK)
				return;
		});
		if (result[0] != Window.OK) return null;
		return dialog.getComment();
	}
	
	/**
	 * Prompt to add all or some of the provided resources to version control.
	 * The value null is returned if the dialog is cancelled.
	 * 
	 * @param shell
	 * @param unadded
	 * @return IResource[]
	 */
	public IResource[] promptForResourcesToBeAdded(Shell shell, IResource[] unadded) {
		if (unadded == null) return new IResource[0];
		if (unadded.length == 0) return unadded;
		final IResource[][] result = new IResource[1][0];
		result[0] = null;
		final AddToVersionControlDialog dialog = new AddToVersionControlDialog(shell, unadded);
		shell.getDisplay().syncExec(() -> {
			int code = dialog.open();
			if (code == IDialogConstants.YES_ID) {
				result[0] = dialog.getResourcesToAdd();
			} else if (code == IDialogConstants.NO_ID) {
				// allow the commit to continue.
				result[0] = new IResource[0];
			}
		});
		return result[0];
	}
	
	public ICVSRepositoryLocation getRepositoryLocationFor(ICVSResource resource) {
		try {
			return internalGetRepositoryLocationFor(resource);
		} catch (CVSException e) {
			CVSUIPlugin.log(e);
			return null;
		}
	}

	private ICVSRepositoryLocation internalGetRepositoryLocationFor(ICVSResource resource) throws CVSException {
		ICVSFolder folder;
		if (resource.isFolder()) {
			folder = (ICVSFolder)resource;
		} else {
			folder = resource.getParent();
		}
		if (folder.isCVSFolder()) {
			ICVSRepositoryLocation location = KnownRepositories.getInstance().getRepository(folder.getFolderSyncInfo().getRoot());
			return location;
		}
		// XXX This is asking for trouble
		return null;
	}
		
	private RepositoryRoot getRepositoryRootFor(ICVSResource resource) throws CVSException {
		ICVSRepositoryLocation location = internalGetRepositoryLocationFor(resource);
		if (location == null) return null;
		return getRepositoryRootFor(location);
	}
	
	public RepositoryRoot getRepositoryRootFor(ICVSRepositoryLocation location) {
		RepositoryRoot root = repositoryRoots.get(location.getLocation(false));
		if (root == null) {
			root = new RepositoryRoot(location);
			add(root);
		}
		return root;
	}
	
	/**
	 * Add the given repository root to the receiver. The provided instance of RepositoryRoot
	 * is used to provide extra information about the repository location
	 * 
	 * @param currentRepositoryRoot
	 */
	public void add(RepositoryRoot root) {
		repositoryRoots.put(root.getRoot().getLocation(false), root);
		broadcastRepositoryChange(root);
	}
	
	private void broadcastRepositoryChange(RepositoryRoot root) {
		if (notificationLevel == 0) {
			broadcastRepositoriesChanged(new ICVSRepositoryLocation[] {root.getRoot()});
		} else {
			changedRepositories.put(root.getRoot().getLocation(false), root.getRoot());
		}
	}
	
	private void broadcastRepositoriesChanged(ICVSRepositoryLocation[] roots) {
		if (roots.length == 0) return;
		Iterator it = listeners.iterator();
		while (it.hasNext()) {
			IRepositoryListener listener = (IRepositoryListener)it.next();
			listener.repositoriesChanged(roots);
		}
	}
	
	/**
	 * Run the given runnable, waiting until the end to perform a refresh
	 * 
	 * @param runnable
	 * @param monitor
	 */
	public void run(IRunnableWithProgress runnable, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
		try {
			notificationLevel++;
			runnable.run(monitor);
		} finally {
			notificationLevel = Math.max(0, notificationLevel - 1);
			if (notificationLevel == 0) {
				try {
					Collection<ICVSRepositoryLocation> roots = changedRepositories.values();
					broadcastRepositoriesChanged(roots.toArray(new ICVSRepositoryLocation[roots.size()]));
				} finally {
					changedRepositories.clear();
				}
			}
		}
	}
	
	/**
	 * Method isDisplayingProjectVersions.
	 * @param repository
	 * @return boolean
	 */
	public boolean isDisplayingProjectVersions(ICVSRepositoryLocation repository) {
		return true;
	}
	
	/**
	 * Method filterResources filters the given resources using the given
	 * working set.
	 *
	 * @param current
	 * @param resources
	 * @return ICVSRemoteResource[]
	 */
	public ICVSRemoteResource[] filterResources(IWorkingSet workingSet, ICVSRemoteResource[] resources) {
		if (workingSet == null) return resources;
		// get the projects associated with the working set
		IAdaptable[] adaptables = workingSet.getElements();
		Set<IProject> projects = new HashSet<>();
		for (int i = 0; i < adaptables.length; i++) {
			IAdaptable adaptable = adaptables[i];
			Object adapted = adaptable.getAdapter(IResource.class);
			if (adapted != null) {
				// Can this code be generalized?
				IProject project = ((IResource)adapted).getProject();
				projects.add(project);
			}
		}
		List<ICVSRemoteResource> result = new ArrayList<>();
		for (int i = 0; i < resources.length; i++) {
			ICVSRemoteResource resource = resources[i];
			for (Iterator iter = projects.iterator(); iter.hasNext();) {
				IProject project = (IProject) iter.next();
				if (project.getName().equals(resource.getName())) {
					result.add(resource);
					break;
				}
			}
		}
		return result.toArray(new ICVSRemoteResource[result.size()]);
	}
	
	/**
	 * Method setLabel.
	 * @param location
	 * @param label
	 */
	public void setLabel(CVSRepositoryLocation location, String label) {
		RepositoryRoot root = getRepositoryRootFor(location);
		String oldLabel = root.getName();
		if (oldLabel == null) {
			if (label == null) return;
			root.setName(label);
		} else if (label == null) {
			root.setName(label);
		} else if (label.equals(oldLabel)) {
			return;
		} else {
			root.setName(label);
		}
		broadcastRepositoryChange(root);	
	}
	
	/**
	 * Replace the old repository location with the new one assuming that they
	 * are the same location with different authentication informations
	 * @param location
	 * @param newLocation
	 */
	public void replaceRepositoryLocation(
			final ICVSRepositoryLocation oldLocation,
			final CVSRepositoryLocation newLocation) {
		
		try {
			run(monitor -> {
				RepositoryRoot root = getRepositoryRootFor(oldLocation);
				// Disposing of the old location will result in the deletion of the
				// cached root through a listener callback
				KnownRepositories.getInstance().disposeRepository(oldLocation);

				// Get the new location from the CVS plugin to ensure we use the
				// instance that will be returned by future calls to getRepository()
				boolean isNew = !KnownRepositories.getInstance().isKnownRepository(newLocation.getLocation());
				root.setRepositoryLocation(
						KnownRepositories.getInstance().addRepository(newLocation, isNew /* broadcast */));
				add(root);
			}, Policy.monitorFor(null));
		} catch (InvocationTargetException e) {
			CVSException.wrapException(e);
		} catch (InterruptedException e) {
		}
	}
	
	/**
	 * Purge any cahced information.
	 */
	public void purgeCache() {
		for (Iterator iter = repositoryRoots.values().iterator(); iter.hasNext();) {
			RepositoryRoot root = (RepositoryRoot) iter.next();
			root.clearCache();
		}
	}

	/**
	 * Answer the list of comments that were previously used when committing.
	 * @return String[]
	 */
	public String[] getPreviousComments() {
		return previousComments;
	}

	/**
	 * Method addComment.
	 * @param string
	 */
	public void addComment(String comment) {
		// Make comment first element if it's already there
		int index = getCommentIndex(comment);
		if (index != -1) {
			makeFirstElement(index);
			return;
		}
		if (containsCommentTemplate(comment))
			return;
		
		// Insert the comment as the first element
		String[] newComments = new String[Math.min(previousComments.length + 1, maxComments)];
		newComments[0] = comment;
		for (int i = 1; i < newComments.length; i++) {
			newComments[i] = previousComments[i-1];
		}
		previousComments = newComments;
	}

	private int getCommentIndex(String comment) {
		for (int i = 0; i < previousComments.length; i++) {
			if (previousComments[i].equals(comment)) {
				return i;
			}
		}
		return -1;
	}
	
	private void makeFirstElement(int index) {
		String[] newComments = new String[previousComments.length];
		newComments[0] = previousComments[index];
		System.arraycopy(previousComments, 0, newComments, 1, index);
		int maxIndex = previousComments.length - 1;
		if (index != maxIndex) {
			int nextIndex = (index + 1);
			System.arraycopy(previousComments, nextIndex, newComments,
					nextIndex, (maxIndex - index));
		}
		previousComments = newComments;
	}
	
	private void readCommentTemplates(InputStream stream) throws IOException, TeamException {
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
			parser.parse(new InputSource(stream),
					new CommentTemplatesContentHandler());
		} catch (SAXException ex) {
			IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(
					CVSUIMessages.RepositoryManager_parsingProblem,
					new String[] { COMMENT_TEMPLATES_FILE }), ex);
			throw new CVSException(status);
		} catch (ParserConfigurationException ex) {
			IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(
					CVSUIMessages.RepositoryManager_parsingProblem,
					new String[] { COMMENT_TEMPLATES_FILE }), ex);
			throw new CVSException(status);
		}
	}
	
	protected void saveCommentTemplates() throws TeamException {
		IPath pluginStateLocation = CVSUIPlugin.getPlugin().getStateLocation();
		File tempFile = pluginStateLocation.append(
				COMMENT_TEMPLATES_FILE + ".tmp").toFile(); //$NON-NLS-1$
		File histFile = pluginStateLocation.append(COMMENT_TEMPLATES_FILE)
				.toFile();
		try {
			XMLWriter writer = new XMLWriter(new BufferedOutputStream(
					new FileOutputStream(tempFile)));
			try {
				writeCommentTemplates(writer);
			} finally {
				writer.close();
			}
			if (histFile.exists()) {
				histFile.delete();
			}
			boolean renamed = tempFile.renameTo(histFile);
			if (!renamed) {
				throw new TeamException(new Status(IStatus.ERROR,
						CVSUIPlugin.ID, TeamException.UNABLE, NLS.bind(
								CVSUIMessages.RepositoryManager_rename,
								new String[] { tempFile.getAbsolutePath() }),
						null));
			}
		} catch (IOException e) {
			throw new TeamException(new Status(IStatus.ERROR, CVSUIPlugin.ID,
					TeamException.UNABLE, NLS.bind(
							CVSUIMessages.RepositoryManager_save,
							new String[] { histFile.getAbsolutePath() }), e));
		}
	}
	
	private void writeCommentTemplates(XMLWriter writer) {
		writer.startTag(ELEMENT_COMMENT_TEMPLATES, null, false);
		for (int i = 0; i < commentTemplates.length; i++)
			writer.printSimpleTag(ELEMENT_COMMIT_COMMENT, commentTemplates[i]);
		writer.endTag(ELEMENT_COMMENT_TEMPLATES);
	}
	
	private boolean containsCommentTemplate(String comment) {
		for (int i = 0; i < commentTemplates.length; i++) {
			if (commentTemplates[i].equals(comment)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Get list of comment templates.
	 */
	public String[] getCommentTemplates() {
		return commentTemplates;
	}
	
	public void replaceAndSaveCommentTemplates(String[] templates)
			throws TeamException {
		commentTemplates = templates;
		saveCommentTemplates();
	}
}
