package org.eclipse.team.internal.ccvs.core.client;

/*
 * (c) Copyright IBM Corp. 2000, 2002.
 * All Rights Reserved.
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.ICVSFile;
import org.eclipse.team.internal.ccvs.core.ICVSFolder;
import org.eclipse.team.internal.ccvs.core.ICVSResource;
import org.eclipse.team.internal.ccvs.core.ICVSResourceVisitor;
import org.eclipse.team.internal.ccvs.core.Policy;
import org.eclipse.team.internal.ccvs.core.client.Command.KSubstOption;
import org.eclipse.team.internal.ccvs.core.resources.CVSEntryLineTag;
import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;

/**
 * An ICVSResourceVisitor that is superclass to all ICVSResourceVisitor's used
 * by Command and it's subclasses.
 * Provides helper methods to send files and folders with modifications
 * to the server.
 */
abstract class AbstractStructureVisitor implements ICVSResourceVisitor {
	
	protected Session session;
	private ICVSFolder lastFolderSent;
	protected IProgressMonitor monitor;
	protected boolean sendQuestionable;
	protected boolean sendModifiedContents;

	public AbstractStructureVisitor(Session session, boolean sendQuestionable, boolean sendModifiedContents, IProgressMonitor monitor) {
		this.session = session;
		this.sendQuestionable = sendQuestionable;
		this.sendModifiedContents = sendModifiedContents;
		this.monitor = Policy.infiniteSubMonitorFor(monitor, 256);
	}

	/** 
	 * Helper method to indicate if a directory has already been sent to the server
	 */
	protected boolean isLastSent(ICVSFolder folder) {
		return folder.equals(lastFolderSent);
	}
	
	/** 
	 * Helper method to record if a directory has already been sent to the server
	 */
	protected void recordLastSent(ICVSFolder folder) {
		lastFolderSent = folder;
	}
	
	/** 
	 * Helper which indicates if a folder is an orphaned subtree. 
	 * That is, a directory which contains a CVS subdirectory but is
	 * not managed by its parent. The root directory of the session
	 * is not considered orphaned even if it is not managed by its
	 * parent.
	 */
	protected boolean isOrphanedSubtree(ICVSFolder mFolder) {
		return mFolder.isCVSFolder() && ! mFolder.isManaged() && ! mFolder.equals(session.getLocalRoot()) && mFolder.getParent().isCVSFolder();
	}
	
	/**
	 * Send the folder relative to the root to the server. Send all 
	 * appropiate modifier like Sticky, Questionable, Static-directory.
	 * <br>
	 * Folders will only be sent once.
	 */
	protected void sendFolder(ICVSFolder mFolder) throws CVSException {

		Policy.checkCanceled(monitor);
		
		if ( ! mFolder.exists()) return;
		
		// Do not send the same folder twice
		if (isLastSent(mFolder)) return;

		String localPath = mFolder.getRelativePath(session.getLocalRoot());
		
		monitor.subTask(Policy.bind("AbstractStructureVisitor.sendingFolder", localPath)); //$NON-NLS-1$
		
		// Deal with questionable directories
		boolean isQuestionable = ! mFolder.isCVSFolder() || isOrphanedSubtree(mFolder);
		if (isQuestionable) {
			if (sendQuestionable) {
				// We need to make sure the parent folder was sent 
				sendFolder(mFolder.getParent());
				session.sendQuestionable(mFolder);
			}
			return;
		}

		// Send the directory to the server
		String remotePath = mFolder.getRemoteLocation(session.getLocalRoot());
		if (remotePath == null) {
			throw new CVSException(Policy.bind("AbstractStructureVisitor.noRemote")); //$NON-NLS-1$
		}
		session.sendDirectory(localPath, remotePath);

		// Send any directory properties to the server
		FolderSyncInfo info = mFolder.getFolderSyncInfo();
		if (info != null) {

			if (info.getIsStatic()) {
				session.sendStaticDirectory();
			}

			CVSEntryLineTag tag = info.getTag();

			if (tag != null && tag.getType() != tag.HEAD) {
				session.sendSticky(tag.toEntryLineFormat(false));
			}
		}

		// Record that we sent this folder
		recordLastSent(mFolder);
		
		monitor.worked(1);
	}

	/**
	 * Send the information about the file to the server.
	 * 
	 * If the file is modified, its contents are sent as well.
	 */
	protected void sendFile(ICVSFile mFile) throws CVSException {

		Policy.checkCanceled(monitor);

		// Send the file's entry line to the server
		ResourceSyncInfo info = null;
		boolean isManaged = mFile.isManaged();
		if (isManaged) {
			info = mFile.getSyncInfo();
			session.sendEntry(info.getServerEntryLine(mFile.getTimeStamp()));
		} else {
			// If the file is not managed, send a questionable to the server if the file exists locally
			// A unmanaged, locally non-existant file results from the explicit use of the file name as a command argument
			if (sendQuestionable) {
				if (mFile.exists()) {
					session.sendQuestionable(mFile);
				}
				return;
			}
		}
		
		// If the file exists, send the appropriate indication to the server
		if (mFile.exists()) {
			if (mFile.isModified()) {
				boolean binary = info != null && info.getKeywordMode().isBinary();
				if (sendModifiedContents) {
					session.sendModified(mFile, binary, monitor);
				} else {
					session.sendIsModified(mFile, binary, monitor);
				}
			} else {
				session.sendUnchanged(mFile);
			}
		}
	}
	
	/**
	 * This method is used to visit a set of ICVSResources. Using it ensures
	 * that a common parent between the set of resources is only sent once
	 */
	public void visit(Session session, ICVSResource[] resources) throws CVSException {
		
		// Sort the resources to avoid sending the same directory multiple times
		List resourceList = new ArrayList(resources.length);
		resourceList.addAll(Arrays.asList(resources));
		final ICVSFolder localRoot = session.getLocalRoot();
		Collections.sort(resourceList, new Comparator() {
			public int compare(Object object1, Object object2) {
				ICVSResource resource1 = (ICVSResource)object1;
				ICVSResource resource2 = (ICVSResource)object2;
				try {
					String path1 = resource1.getParent().getRelativePath(localRoot);
					String path2 = resource2.getParent().getRelativePath(localRoot);
					int pathCompare = path1.compareTo(path2);
					if (pathCompare == 0) {
						if (resource1.isFolder() == resource2.isFolder()) {
							return resource1.getName().compareTo(resource2.getName());
						} else if (resource1.isFolder()) {
							return 1;
						} else {
							return -1;
						}
					} else {
						return pathCompare;
					}
				} catch (CVSException e) {
					return resource1.getName().compareTo(resource2.getName());
				}
			}
		});

		// Visit all the resources
		session.setSendFileTitleKey(getSendFileTitleKey());
		for (int i = 0; i < resourceList.size(); i++) {
			((ICVSResource)resourceList.get(i)).accept(this);
		}
		
		monitor.done();
	}
	
	protected String getSendFileTitleKey() {
		return "AbstractStructureVisitor.sendingFile"; //$NON-NLS-1$
	}
}