/*******************************************************************************
 * Copyright (c) 2000, 2008 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
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.core.resources;

import java.util.*;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.*;
import org.eclipse.team.internal.ccvs.core.client.Command.*;
import org.eclipse.team.internal.ccvs.core.client.listeners.*;
import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation;
import org.eclipse.team.internal.ccvs.core.connection.CVSServerException;
import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.internal.ccvs.core.util.Util;

/*
 * This class is responsible for building a remote tree that shows the repository
 * state of a locally loaded folder tree.
 * 
 * It is used as follows
 * 
 * 		RemoteFolderTreeBuilder.buildRemoteTree(CVSRepositoryLocation, IManagedFolder, String, IProgressMonitor);
 * 
 * The provider IManagedFolder can be a local resource or a RemoteFolderTree that
 * that was previously built.
 */
public class RemoteFolderTreeBuilder {

	private static final int MAX_REVISION_FETCHES_PER_CONNECTION = 1024;
	
	private Map<String, Map> fileDeltas;
	private List<String> changedFiles;
	private Map<String, RemoteFolderTree> remoteFolderTable;
	
	private ICVSFolder root;
	private RemoteFolderTree remoteRoot;
	private CVSRepositoryLocation repository;
	
	private CVSTag tag;
	
	private LocalOption[] updateLocalOptions;
	
	private boolean rootDoesNotExist = false;
	
	private static String UNKNOWN = ""; //$NON-NLS-1$
	private static String DELETED = "DELETED"; //$NON-NLS-1$
	private static String ADDED = "ADDED"; //$NON-NLS-1$
	private static String FOLDER = "FOLDER"; //$NON-NLS-1$
	
	private static Map EMPTY_MAP = new HashMap();
	
	private boolean newFolderExist = false;
	
	static class DeltaNode {
		int syncState = Update.STATE_NONE;
		String name;
		String revision;
		
		DeltaNode(String name, String revision, int syncState) {
			this.name = name;
			this.revision = revision;
			this.syncState = syncState;			
		}
		
		String getName() {
			return name;
		}
		
		String getRevision() {
			return revision;
		}
		
		int getSyncState() {
			return syncState;
		}
	}
		
	
	/* package */ RemoteFolderTreeBuilder(CVSRepositoryLocation repository, ICVSFolder root, CVSTag tag) {
		this.repository = repository;
		this.root = root;
		this.tag = tag;
		this.fileDeltas = new HashMap<String, Map>();
		this.changedFiles = new ArrayList<String>();
		this.remoteFolderTable = new HashMap<String, RemoteFolderTree>();
		
		// Build the local options
		List<LocalOption> localOptions = new ArrayList<>();
		if (tag != null) {
			if (tag.getType() == CVSTag.HEAD) {
				localOptions.add(Update.CLEAR_STICKY);
			} else {
				localOptions.add(Update.makeTagOption(tag));
			}
		}
		updateLocalOptions = localOptions.toArray(new LocalOption[localOptions.size()]);
	}
	
	private LocalOption[] getOptionsWithoutTag() {
		// Build the local options
		List<LocalOption> localOptions = new ArrayList<>();
		localOptions.add(Update.RETRIEVE_ABSENT_DIRECTORIES);
		return localOptions.toArray(new LocalOption[localOptions.size()]);
	}
	
	public static RemoteFolder buildBaseTree(CVSRepositoryLocation repository, ICVSFolder root, CVSTag tag, IProgressMonitor progress) throws CVSException {
		try {
			RemoteFolderTreeBuilder builder = new RemoteFolderTreeBuilder(repository, root, tag);
			progress.beginTask(null, 100);
			IProgressMonitor subProgress = Policy.infiniteSubMonitorFor(progress, 100);
			subProgress.beginTask(null, 512);  
			subProgress.subTask(NLS.bind(CVSMessages.RemoteFolderTreeBuilder_buildingBase, new String[] { root.getName() })); 
	 		return builder.buildBaseTree(null, root, subProgress);
		} finally {
			progress.done();
		}
	}
	
	public static RemoteFolderTree buildRemoteTree(CVSRepositoryLocation repository, IContainer root, CVSTag tag, IProgressMonitor monitor) throws CVSException {
		return buildRemoteTree(repository, CVSWorkspaceRoot.getCVSFolderFor(root), tag, monitor);
	}
	
	public static RemoteFolderTree buildRemoteTree(CVSRepositoryLocation repository, ICVSFolder root, CVSTag tag, IProgressMonitor monitor) throws CVSException {
		RemoteFolderTreeBuilder builder = new RemoteFolderTreeBuilder(repository, root, tag);
 		return builder.buildTree(new ICVSResource[] { root }, monitor);
	}
	public static RemoteFile buildRemoteTree(CVSRepositoryLocation repository, ICVSFile file, CVSTag tag, IProgressMonitor monitor) throws CVSException {
		RemoteFolderTreeBuilder builder = new RemoteFolderTreeBuilder(repository, file.getParent(), tag);
 		return builder.buildTree(file, monitor);
	}
	
	/* package */ RemoteFolderTree buildTree(ICVSResource[] resources, IProgressMonitor monitor) throws CVSException {
		
		// Make sure that the cvs commands are not quiet during this operations
		QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness();
		try {
			CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE);
			
			monitor.beginTask(null, 100);

			// 1st Connection: Use local state to determine delta with server
			if (!fetchDelta(resources, Policy.subMonitorFor(monitor, 75))) {
				return null;
			}
			
			// 2nd Connection: Build remote tree from above delta using 2nd connection to fetch unknown directories
			// NOTE: Multiple commands may be issued over this connection.
			fetchNewDirectories(Policy.subMonitorFor(monitor, 10));

			//	3rd+ Connection: Used to fetch file status in groups of 1024
			fetchFileRevisions(Policy.subMonitorFor(monitor, 15));
			
			return remoteRoot;
			
		} finally {
			CVSProviderPlugin.getPlugin().setQuietness(quietness);
			monitor.done();
		}
	}

	private boolean fetchDelta(ICVSResource[] resources, IProgressMonitor monitor) throws CVSException {
		
		// Get the arguments from the files
		ArrayList<String> arguments = new ArrayList<>();
		for (int i = 0; i < resources.length; i++) {
			ICVSResource resource = resources[i];
			arguments.add(resource.getRelativePath(root));
		}
		
		// Use local state to determine delta with server
		monitor.beginTask(null, 100);
		Policy.checkCanceled(monitor);
		Session session = new Session(repository, root, false);
		session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
		try {
			Policy.checkCanceled(monitor);
			fetchDelta(session, arguments.toArray(new String[arguments.size()]), Policy.subMonitorFor(monitor, 90));
			if (rootDoesNotExist) {
				// We cannot handle the case where a project (i.e. the top-most CVS folder)
				// has been deleted directly on the sever (i.e. deleted using rm -rf)
				if (root.isCVSFolder() && ! root.isManaged()) {
					IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSMessages.RemoteFolderTreeBuild_folderDeletedFromServer, new String[] { root.getFolderSyncInfo().getRepository() }),root);
					throw new CVSException(status); 
				} else {
					return false;
				}
			}
		} finally {
			session.close();
			monitor.done();
		}
		return true;
	}

	private void fetchNewDirectories(IProgressMonitor monitor) throws CVSException {
		// Build remote tree from the fetched delta using a new connection to fetch unknown directories
		// NOTE: Multiple commands may be issued over this connection.
		monitor.beginTask(null, 100);
		Session session;
		FolderSyncInfo folderSyncInfo = root.getFolderSyncInfo();
		if (folderSyncInfo == null) {
		    // We've lost the mapping in the local workspace.
		    // This could be due to the project being deleted.
		    if (root.exists()) {
		        IResource resource = root.getIResource();
		        String path;
		        if (resource == null) {
		            path = root.getName();
		        } else {
		            path = resource.getFullPath().toString();
		        }
		        IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSMessages.RemoteFolderTreeBuilder_0, new String[] { path }), root);
                throw new CVSException(status); 
		    } else {
		        // Just return. The remote tree will be null
		        return;
		    }
		}
        remoteRoot =
			new RemoteFolderTree(null, root.getName(), repository,
				folderSyncInfo.getRepository(),
				tagForRemoteFolder(root, tag));
		if (newFolderExist) {
			// New folders will require a connection for fetching their members
			session = new Session(repository, remoteRoot, false);
			session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
		} else {
			session = null;
		}
		try {
			// Set up an infinite progress monitor for the recursive build
			IProgressMonitor subProgress = Policy.infiniteSubMonitorFor(monitor, 90);
			subProgress.beginTask(null, 512);
			// Build the remote tree
			buildRemoteTree(session, root, remoteRoot, "", subProgress); //$NON-NLS-1$
		} finally {
			if (session != null) {
				session.close();
			}
			monitor.done();
		}
	}
	
	private void fetchFileRevisions(IProgressMonitor monitor) throws CVSException {
		// 3rd+ Connection: Used to fetch file status in groups of 1024
		if (remoteRoot != null && !changedFiles.isEmpty()) {
			String[] allChangedFiles = changedFiles.toArray(new String[changedFiles.size()]);
			int iterations = (allChangedFiles.length / MAX_REVISION_FETCHES_PER_CONNECTION) 
				+ (allChangedFiles.length % MAX_REVISION_FETCHES_PER_CONNECTION == 0 ? 0 : 1);
			for (int i = 0; i < iterations ; i++) {
				int length = Math.min(MAX_REVISION_FETCHES_PER_CONNECTION, 
					allChangedFiles.length - (MAX_REVISION_FETCHES_PER_CONNECTION * i));
				String buffer[] = new String[length];
				System.arraycopy(allChangedFiles, i * MAX_REVISION_FETCHES_PER_CONNECTION, buffer, 0, length);
				Session session = new Session(repository, remoteRoot, false);
				session.open(Policy.subMonitorFor(monitor, 1), false /* read-only */);
				try {
					fetchFileRevisions(session, buffer, Policy.subMonitorFor(monitor, 2));
				} finally {
					session.close();
				}
			}
		}
	}
	
	/* package */ RemoteFile buildTree(ICVSFile file, IProgressMonitor monitor) throws CVSException {
		QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness();
		try {
			CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE);
			
			monitor.beginTask(null, 100);
	
			// Query the server to see if there is a delta available
			Policy.checkCanceled(monitor);
			Session session = new Session(repository, root, false);
			session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
			try {
				Policy.checkCanceled(monitor);
				fetchDelta(session, new String[] { file.getName() }, Policy.subMonitorFor(monitor, 50));
				if (rootDoesNotExist) {
					return null;
				}
			} finally {
				session.close();
			}
			// Create a parent for the remote resource
			remoteRoot =
				new RemoteFolderTree(null, root.getName(), repository,
					root.getFolderSyncInfo().getRepository(),
					tagForRemoteFolder(root, tag));
			// Create the remote resource (using the delta if there is one)
			RemoteFile remoteFile;
			Map deltas = fileDeltas.get(""); //$NON-NLS-1$
			if (deltas == null || deltas.isEmpty()) {
				// If the file is an addition, return null as the remote
				// Note: If there was a conflicting addition, the delta would not be empty
				byte[] syncBytes = file.getSyncBytes();
				if ( syncBytes == null || ResourceSyncInfo.isAddition(syncBytes)) {
					return null;
				}
				remoteFile = new RemoteFile(remoteRoot, syncBytes);
			} else {
				DeltaNode d = (DeltaNode)deltas.get(file.getName());
				if (d.getRevision() == DELETED) {
					return null;
				}
				CVSTag newTag = tagForRemoteFolder(remoteRoot, tag);
				if (newTag == null && file.getSyncInfo() != null) {
					newTag = file.getSyncInfo().getTag();
				}
				remoteFile = new RemoteFile(remoteRoot, 
					d.getSyncState(), 
					file.getName(), 
					null, /* the revision will be retrieved from the server */
					getKeywordMode(file), /* use the same keyword mode as the local file */
					newTag);
			}
			// Add the resource to its parent
			remoteRoot.setChildren(new ICVSRemoteResource[] {remoteFile});
			// If there was a delta, fetch the new revision
			if (!changedFiles.isEmpty()) {
				// Add the remote folder to the remote folder lookup table (used to update file revisions)
				recordRemoteFolder(remoteRoot);
				session = new Session(repository, remoteRoot, false);
				session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
				try {
					fetchFileRevisions(session, changedFiles.toArray(new String[changedFiles.size()]), Policy.subMonitorFor(monitor, 20));
				} finally {
					session.close();
				}
			}
			return remoteFile;
			
		} finally {
			CVSProviderPlugin.getPlugin().setQuietness(quietness);
			monitor.done();
		}
	}
	
	private Command.KSubstOption getKeywordMode(ICVSFile file) throws CVSException {
		if (file == null) return null;
		byte[] syncBytes = file.getSyncBytes();
		if (syncBytes == null) return null;
		return ResourceSyncInfo.getKeywordMode(syncBytes);
	}

	/*
	 * Build the base remote tree from the local tree.
	 * 
	 * The localPath is used to retrieve deltas from the recorded deltas
	 * 
	 * Does 1 work for each managed file and folder
	 */
	RemoteFolder buildBaseTree(RemoteFolder parent, ICVSFolder local, IProgressMonitor monitor) throws CVSException {
		
		Policy.checkCanceled(monitor);
					
		// Create a remote folder tree corresponding to the local resource
		FolderSyncInfo folderSyncInfo = local.getFolderSyncInfo();
		if (folderSyncInfo == null) return null;
        RemoteFolder remote = createRemoteFolder(local, parent, folderSyncInfo);

		// Create a List to contain the created children
		List<RemoteResource> children = new ArrayList<>();
		
		// Build the child folders corresponding to local folders base
		ICVSResource[] folders = local.members(ICVSFolder.FOLDER_MEMBERS);
		for (int i=0;i<folders.length;i++) {
			ICVSFolder folder = (ICVSFolder)folders[i];
			if (folder.isManaged() && folder.isCVSFolder()) {
				monitor.worked(1);
				RemoteFolder tree = buildBaseTree(remote, folder, monitor);
				if (tree != null)
				    children.add(tree);
			}
		}
		
		// Build the child files corresponding to local files base
		ICVSResource[] files = local.members(ICVSFolder.FILE_MEMBERS);
		for (int i=0;i<files.length;i++) {
			ICVSFile file = (ICVSFile)files[i];
			byte[] syncBytes = file.getSyncBytes();
			// if there is no sync info then there is no base
			if (syncBytes==null)
				continue;
			// There is no remote if the file was added
			if (ResourceSyncInfo.isAddition(syncBytes))
				continue;
			// If the file was deleted locally, we need to generate a new sync info without the delete flag
			if (ResourceSyncInfo.isDeletion(syncBytes)) {
				syncBytes = ResourceSyncInfo.convertFromDeletion(syncBytes);
			}
			children.add(createRemoteFile(remote, syncBytes));
			monitor.worked(1);
		}
		
		// Remove any folders that are phantoms locally if they have no children
		if (children.isEmpty() && isPruneEmptyDirectories() && !local.exists())
			return null;

		// Add the children to the remote folder tree
		remote.setChildren(children.toArray(new ICVSRemoteResource[children.size()]));
		
		return remote;
	}

	protected RemoteFile createRemoteFile(RemoteFolder remote, byte[] syncBytes) throws CVSException {
		return new RemoteFile(remote, syncBytes);
	}

	protected RemoteFolder createRemoteFolder(ICVSFolder local, RemoteFolder parent, FolderSyncInfo folderSyncInfo) {
		return new RemoteFolderTree(parent, local.getName(), repository, folderSyncInfo.getRepository(), folderSyncInfo.getTag());
	}
	
	/*
	 * Build the remote tree from the local tree and the recorded deltas.
	 * 
	 * The localPath is used to retrieve deltas from the recorded deltas
	 * 
	 * Does 1 work for each file and folder delta processed
	 */
	private void buildRemoteTree(Session session, ICVSFolder local, RemoteFolderTree remote, String localPath, IProgressMonitor monitor) throws CVSException {
		
		Policy.checkCanceled(monitor);
		
		// Add the remote folder to the remote folder lookup table (used to update file revisions)
		recordRemoteFolder(remote);
		
		// Create a map to contain the created children
		Map<String, RemoteResource> children = new HashMap<>();
		
		// If there's no corresponding local resource then we need to fetch its contents in order to populate the deltas
		if (local == null) {
			fetchNewDirectory(session, remote, localPath, monitor);
		}
		
		// Fetch the delta's for the folder
		Map deltas = fileDeltas.get(localPath);
		if (deltas == null)
			deltas = EMPTY_MAP;
		
		// If there is a local, use the local children to start building the remote children
		if (local != null) {
			// Build the child folders corresponding to local folders
			ICVSResource[] folders = local.members(ICVSFolder.FOLDER_MEMBERS);
			for (int i=0;i<folders.length;i++) {
				ICVSFolder folder = (ICVSFolder)folders[i];
				DeltaNode d = (DeltaNode)deltas.get(folder.getName());
				if (folder.isCVSFolder() && ! isOrphanedSubtree(folder) && (d==null || d.getRevision() != DELETED)) {
					children.put(folders[i].getName(), 
						new RemoteFolderTree(remote, folders[i].getName(), repository, 
							folder.getFolderSyncInfo().getRepository(), 
							tagForRemoteFolder(folder,tag)));
				}
			}
			// Build the child files corresponding to local files
			ICVSResource[] files = local.members(ICVSFolder.FILE_MEMBERS);
			for (int i=0;i<files.length;i++) {
				ICVSFile file = (ICVSFile)files[i];

				DeltaNode d = (DeltaNode)deltas.get(file.getName());
				byte[] syncBytes = file.getSyncBytes();
				// if there is no sync info then there isn't a remote file for this local file on the
				// server.
				if (syncBytes==null)
					continue;
				// There is no remote if the file was added and we didn't get a conflict (C) indicator from the server
				if (ResourceSyncInfo.isAddition(syncBytes) && d==null)
					continue;
				// There is no remote if the file was deleted and we didn't get a remove (R) indicator from the server
				if (ResourceSyncInfo.isDeletion(syncBytes) && d==null)
					continue;
					
				int type = d==null ? Update.STATE_NONE : d.getSyncState();
				children.put(file.getName(), new RemoteFile(remote, type, syncBytes));
			}
		}
		
		// Build the children for new or out-of-date resources from the deltas
		Iterator i = deltas.keySet().iterator();
		while (i.hasNext()) {
			String name = (String)i.next();
			DeltaNode d = (DeltaNode)deltas.get(name);
			String revision = d.getRevision();
			if (revision == FOLDER) {
				children.put(name, new RemoteFolderTree(remote, repository, 
					Util.appendPath(remote.getRepositoryRelativePath(), name), 
					tagForRemoteFolder(remote, tag)));
			} else if (revision == ADDED) {
				children.put(name, new RemoteFile(remote, 
					d.getSyncState(), 
					name, 
					null, /* the revision will be fetched later */
					null, /* there's no way to know the remote keyword mode */
					tagForRemoteFolder(remote, tag)));
			} else if (revision == UNKNOWN) {
				// The local resource is out of sync with the remote.
				// Create a RemoteFile associated with the tag so we are assured of getting the proper revision
				// (Note: this will replace the RemoteFile added from the local base)
				children.put(name, new RemoteFile(remote, 
					d.getSyncState(), 
					name, 
					null, /* the revision will be fetched later */
					getKeywordMode((ICVSFile)children.get(name)), /* get the keyword mode from the local file*/
					tagForRemoteFolder(remote, tag)));
			} else if (revision == DELETED) {
				// This should have been deleted while creating from the local resources.
				// If it wasn't, delete it now.
				if (children.containsKey(name))
					children.remove(name);
			} else {
				// We should never get here
			}
			monitor.worked(1);
		}

		// Add the children to the remote folder tree
		remote.setChildren(children.values().toArray(new ICVSRemoteResource[children.size()]));
		
		// We have to delay building the child folders to support the proper fetching of new directories
		// due to the fact that the same CVS home directory (i.e. the same root directory) must
		// be used for all requests sent over the same connection
		Iterator childIterator = children.entrySet().iterator();
		List<RemoteFolderTree> emptyChildren = new ArrayList<>();
		while (childIterator.hasNext()) {
			Map.Entry entry = (Map.Entry)childIterator.next();
			if (((RemoteResource)entry.getValue()).isFolder()) {
				RemoteFolderTree remoteFolder = (RemoteFolderTree)entry.getValue();
				String name = (String)entry.getKey();
				ICVSFolder localFolder;
				DeltaNode d = (DeltaNode)deltas.get(name);
				// for directories that are new on the server 
				if (d!=null && d.getRevision() == FOLDER)
					localFolder = null;
				else
					localFolder = local.getFolder(name);
				buildRemoteTree(session, localFolder, remoteFolder, Util.appendPath(localPath, name), monitor);
				// Record any children that are empty
				if (isPruneEmptyDirectories() && remoteFolder.getChildren().length == 0) {
					// Prune if the local folder is also empty.
					if (localFolder == null || (localFolder.members(ICVSFolder.ALL_EXISTING_MEMBERS).length == 0))
						emptyChildren.add(remoteFolder);
					else {
						// Also prune if the tag we are fetching is not HEAD and differs from the tag of the local folder
						FolderSyncInfo info = localFolder.getFolderSyncInfo();
						if (tag != null && info != null && ! tag.equals(CVSTag.DEFAULT) && ! tag.equals(info.getTag()))
							emptyChildren.add(remoteFolder);
					}
				}
			}
		}
		
		// Prune any empty child folders
		if (isPruneEmptyDirectories() && !emptyChildren.isEmpty()) {
			List<ICVSRemoteResource> newChildren = new ArrayList<ICVSRemoteResource>();
			newChildren.addAll(Arrays.asList(remote.getChildren()));
			newChildren.removeAll(emptyChildren);
			remote.setChildren(newChildren.toArray(new ICVSRemoteResource[newChildren.size()]));

		}
	}
	
	/*
	 * This method fetches the delta between the local state and the remote state of the resource tree
	 * and records the deltas in the fileDeltas instance variable
	 * 
	 * Returns the list of changed files
	 */
	private List<String> fetchDelta(Session session, String[] arguments, final IProgressMonitor monitor) throws CVSException {
		
		// Create an listener that will accumulate new and removed files and folders
		IUpdateMessageListener listener = new IUpdateMessageListener() {
			public void directoryInformation(ICVSFolder root, String path, boolean newDirectory) {
				if (newDirectory) {
					// Record new directory with parent so it can be retrieved when building the parent
					recordDelta(path, FOLDER, Update.STATE_NONE);
					monitor.subTask(NLS.bind(CVSMessages.RemoteFolderTreeBuilder_receivingDelta, new String[] { Util.toTruncatedPath(path, 3) })); 
				}
			}
			public void directoryDoesNotExist(ICVSFolder root, String path) {
				// Record removed directory with parent so it can be removed when building the parent
				if (path.length() == 0) {
					rootDoesNotExist = true;
				} else {
					recordDelta(path, DELETED, Update.STATE_NONE);
					monitor.subTask(NLS.bind(CVSMessages.RemoteFolderTreeBuilder_receivingDelta, new String[] { Util.toTruncatedPath(path, 3) })); 
				}
			}
			public void fileInformation(int type, ICVSFolder root, String filename) {
				// Cases that do not require action are:
				//	case 'A' :  = A locally added file that does not exists remotely
				//	case '?' :  = A local file that has not been added and does not exists remotely
				//  case 'M' :  = A locally modified file that has not been modified remotely
				switch(type) {
					case Update.STATE_MERGEABLE_CONFLICT :
					case Update.STATE_CONFLICT : 
								// We have an remote change to a modified local file
								// The change could be a local change conflicting with a remote deletion.
								// If so, the deltas may already have a DELETED for the file.
								// We shouldn't override this DELETED
								Map deltas = fileDeltas.get(Util.removeLastSegment(filename));
								DeltaNode d = deltas != null ? (DeltaNode)deltas.get(Util.getLastSegment(filename)) : null;
								if ((d!=null) && (d.getRevision() == DELETED))
									break;
					case Update.STATE_DELETED : // We have a locally removed file that still exists remotely
					case Update.STATE_REMOTE_CHANGES : // We have an remote change to an unmodified local file
								changedFiles.add(filename);
								recordDelta(filename, UNKNOWN, type);
								monitor.subTask(NLS.bind(CVSMessages.RemoteFolderTreeBuilder_receivingDelta, new String[] { Util.toTruncatedPath(filename, 3) })); 
								break;
				}	
			}
			public void fileDoesNotExist(ICVSFolder root, String filename) {
				recordDelta(filename, DELETED, Update.STATE_NONE);
				monitor.subTask(NLS.bind(CVSMessages.RemoteFolderTreeBuilder_receivingDelta, new String[] { Util.toTruncatedPath(filename, 3) })); 
			}
		};
		
		// Perform a "cvs -n update -d [-r tag] ." in order to get the
		// messages from the server that will indicate what has changed on the 
		// server.
		IStatus status = Command.SYNCUPDATE.execute(session,
			new GlobalOption[] { Command.DO_NOT_CHANGE },
			updateLocalOptions,
			arguments,
			new UpdateListener(listener),
			monitor);
		if (status.getCode() == CVSStatus.SERVER_ERROR) {
			CVSServerException e = new CVSServerException(status);
			if (e.isNoTagException()) {
				// This error indicates that the complete subtree 
				// being fetched does not have any files for the tag being queried
				rootDoesNotExist = true;
			} else if (e.containsErrors()) {
				// Log the error
				CVSProviderPlugin.log(e);
			}
		}
		return changedFiles;
	}
	/*
	 * Fetch the children of a previously unknown directory.
	 * 
	 * The fetch may do up to 2 units of work in the provided monitor.
	 */
	private void fetchNewDirectory(Session session, RemoteFolderTree newFolder, String localPath, final IProgressMonitor monitor) throws CVSException {
		
		// Create an listener that will accumulate new files and folders
		IUpdateMessageListener listener = new IUpdateMessageListener() {
			public void directoryInformation(ICVSFolder root, String path, boolean newDirectory) {
				if (newDirectory) {
					// Record new directory with parent so it can be retrieved when building the parent
					// NOTE: Check path prefix
					recordDelta(path, FOLDER, Update.STATE_NONE);
					monitor.subTask(NLS.bind(CVSMessages.RemoteFolderTreeBuilder_receivingDelta, new String[] { Util.toTruncatedPath(path, 3) })); 
				}
			}
			public void directoryDoesNotExist(ICVSFolder root, String path) {
			}
			public void fileInformation(int type, ICVSFolder root, String filename) {
				// NOTE: Check path prefix
				changedFiles.add(filename);
				recordDelta(filename, ADDED, type);
				monitor.subTask(NLS.bind(CVSMessages.RemoteFolderTreeBuilder_receivingDelta, new String[] { Util.toTruncatedPath(filename, 3) })); 
			}
			public void fileDoesNotExist(ICVSFolder root, String filename) {
			}
		};

		// NOTE: Should use the path relative to the remoteRoot
		IStatus status = Command.UPDATE.execute(session,
			new GlobalOption[] { Command.DO_NOT_CHANGE },
			updateLocalOptions,
			new String[] { localPath },
			new UpdateListener(listener),
			Policy.subMonitorFor(monitor, 1)); 
		if (status.getCode() == CVSStatus.SERVER_ERROR) {
			CVSServerException e = new CVSServerException(status);
			if ( ! e.isNoTagException() && e.containsErrors())
				throw e;
			// we now know that this is an exception caused by a cvs bug.
			// if the folder has no files in it (just subfolders) cvs does not respond with the subfolders...
			// workaround: retry the request with no tag to get the directory names (if any)
			Policy.checkCanceled(monitor);
			status = Command.UPDATE.execute(session,
				new GlobalOption[] { Command.DO_NOT_CHANGE },
				getOptionsWithoutTag(),
				new String[] { localPath },
				new UpdateListener(listener),
				Policy.subMonitorFor(monitor, 1));
			if (status.getCode() == CVSStatus.SERVER_ERROR) {
				throw new CVSServerException(status);
			}
		}
	}
	
	// Get the file revisions for the given filenames
	private void fetchFileRevisions(Session session, String[] fileNames, final IProgressMonitor monitor) throws CVSException {
		
		// Create a listener for receiving the revision info
		final List<CVSException> exceptions = new ArrayList<CVSException>();
		IStatusListener listener = new IStatusListener() {
			public void fileStatus(ICVSFolder root, String path, String remoteRevision) {
				try {
					updateRevision(path, remoteRevision);
					monitor.subTask(NLS.bind(CVSMessages.RemoteFolderTreeBuilder_receivingRevision, new String[] { Util.toTruncatedPath(path, 3) })); 
				} catch (CVSException e) {
					exceptions.add(e);
				}
			}
		};
			
		// Perform a "cvs status..." with a custom message handler
		IStatus status = Command.STATUS.execute(session,
			Command.NO_GLOBAL_OPTIONS,
			Command.NO_LOCAL_OPTIONS,
			fileNames,
			new StatusListener(listener),
			monitor);
		if (status.getCode() == CVSStatus.SERVER_ERROR) {
			throw new CVSServerException(status);
		}
		
		// Report any exceptions that occurred fetching the revisions
		if ( ! exceptions.isEmpty()) {
			if (exceptions.size() == 1) {
				throw exceptions.get(0);
			} else {
				MultiStatus multi = new MultiStatus(CVSProviderPlugin.ID, 0, CVSMessages.RemoteFolder_errorFetchingRevisions, null); 
				for (int i = 0; i < exceptions.size(); i++) {
					multi.merge(exceptions.get(i).getStatus());
				}
				throw new CVSException(multi);
			}
		}
	}

	protected boolean isPruneEmptyDirectories() {
		return false;
	}
	/*
	 * Record the deltas in a double map where the outer key is the parent directory
	 * and the inner key is the file name. The value is the revision of the file or
	 * DELETED (file or folder). New folders have a revision of FOLDER.
	 * 
	 * A revision of UNKNOWN indicates that the revision has not been fetched
	 * from the repository yet.
	 */
	private void recordDelta(String path, String revision, int syncState) {
		if (revision == FOLDER) {
			newFolderExist = true;
		}
		String parent = Util.removeLastSegment(path);
		Map<String, DeltaNode> deltas = fileDeltas.get(parent);
		if (deltas == null) {
			deltas = new HashMap<>();
			fileDeltas.put(parent, deltas);
		}
		String name = Util.getLastSegment(path);
		deltas.put(name, new DeltaNode(name, revision, syncState));
	}
	
	private void updateRevision(String path, String revision) throws CVSException {
		RemoteFolderTree folder = getRecoredRemoteFolder(Util.removeLastSegment(path));
		if (folder == null) {
			IStatus status = new CVSStatus(IStatus.ERROR, CVSStatus.ERROR, NLS.bind(CVSMessages.RemoteFolderTreeBuilder_missingParent, new String[] { path.toString(), revision }), root);
			throw new CVSException(status);
		}
		((RemoteFile)folder.getFile(Util.getLastSegment(path))).setRevision(revision);
	}
	
	/*
	 * Return the tag that should be associated with a remote folder.
	 * 
	 * This method is used to ensure that new directories contain the tag
	 * derived from the parent local folder when appropriate. For instance,
	 * 
	 * The tag should be the provided tag. However, if tag is null, the 
	 * tag for the folder should be derived from the provided reference folder
	 * which could be the local resource corresponding to the remote or the parent
	 * of the remote.
	 */
	private CVSTag tagForRemoteFolder(ICVSFolder folder, CVSTag tag) throws CVSException {
		return tag == null ? folder.getFolderSyncInfo().getTag() : tag;
	}
	
	private boolean isOrphanedSubtree(ICVSFolder mFolder) throws CVSException {
		return mFolder.isCVSFolder() && ! mFolder.isManaged() && ! mFolder.equals(root) && mFolder.getParent().isCVSFolder();
	}
	
	private void recordRemoteFolder(RemoteFolderTree remote) throws CVSException {
		String path = remote.getFolderSyncInfo().getRemoteLocation();
		remoteFolderTable.put(Util.asPath(path), remote);
	}
	
	private RemoteFolderTree getRecoredRemoteFolder(String path) {
		return remoteFolderTable.get(Util.asPath(path));
	}

	/**
	 * This method returns an array of the files that differ between the local and remote trees.
	 * The files are represented as a String that contains the path to the file in the remote or local trees.
	 * @return an array of differing files
	 */
	public String[] getFileDiffs() {
		return changedFiles.toArray(new String[changedFiles.size()]);
	}
}
