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

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

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.ISynchronizer;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.team.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.ccvs.core.CVSTag;
import org.eclipse.team.ccvs.core.ICVSFile;
import org.eclipse.team.ccvs.core.ICVSFolder;
import org.eclipse.team.ccvs.core.ICVSResource;
import org.eclipse.team.core.TeamPlugin;
import org.eclipse.team.core.sync.ISyncProvider;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.Policy;
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.Assert;
import org.eclipse.team.internal.ccvs.core.util.SyncFileWriter;

/**
 * A synchronizer is responsible for managing synchronization information for local
 * CVS resources.
 * 
 * [Notes:
 *  1. how can we expire cache elements and purge to safe memory?
 *  2. how can we safeguard against overwritting meta files changes made outside of Eclipse? I'm
 *     not sure we should force setting file contents in EclipseFile handles?
 *  4. how do we reload
 * ]
 * 
 * @see ResourceSyncInfo
 * @see FolderSyncInfo
 */
public class EclipseSynchronizer {
	// the resources plugin synchronizer is used to cache and possibly persist. These 
	// are keys for storing the sync info.
	private static final QualifiedName FOLDER_SYNC_KEY = new QualifiedName(CVSProviderPlugin.ID, "folder-sync");
	private static final QualifiedName RESOURCE_SYNC_KEY = new QualifiedName(CVSProviderPlugin.ID, "resource-sync");
	private static final QualifiedName RESOURCE_SYNC_LOADED_KEY = new QualifiedName(CVSProviderPlugin.ID, "folder-has-loaded-childsync");
	private static final QualifiedName IGNORE_SYNC_KEY = new QualifiedName(CVSProviderPlugin.ID, "folder-ignore");
	
	private static final byte[] EMPTY_BYTES = new byte[0];
	private static final FolderSyncInfo EMPTY_FOLDER_SYNC_INFO = new FolderSyncInfo("", "", null, false);
	
	// the cvs eclipse synchronizer is a singleton
	private static EclipseSynchronizer instance;
	
	// track resources that have changed in a given operation
	private int nestingCount = 0;
	private Set changedResources = new HashSet();
	private Set changedFolders = new HashSet();
	
	private static final boolean DEBUG = false;
	
	private EclipseSynchronizer() {		
	}
	
	public static EclipseSynchronizer getInstance() {		
		return instance;
	}

	public void setFolderSync(IContainer folder, FolderSyncInfo info) throws CVSException {
		Assert.isNotNull(info);
		try {
			beginOperation(null);
			setCachedFolderSync(folder, info);
			changedFolders.add(folder);
		} finally {
			endOperation(null);
		}
	}
	
	public FolderSyncInfo getFolderSync(IContainer folder) throws CVSException {
		if (folder.getType() == IResource.ROOT) return null;					
		FolderSyncInfo info = getCachedFolderSync(folder);
		if (info == null && folder.exists()) {
			// read folder sync info and remember it
			// -- if none found then remember that fact for later
			info = SyncFileWriter.readFolderConfig(CVSWorkspaceRoot.getCVSFolderFor(folder));
			if (info == null) info = EMPTY_FOLDER_SYNC_INFO;
			setCachedFolderSync(folder, info);
		}
		if (info == EMPTY_FOLDER_SYNC_INFO) info = null;
		return info;
	}	

	public void setResourceSync(IResource resource, ResourceSyncInfo info) throws CVSException {
		Assert.isNotNull(info);
		try {
			beginOperation(null);
			ensureChildResourceSyncLoaded(resource.getParent());
			setCachedResourceSync(resource, info);
			changedResources.add(resource);		
		} finally {
			endOperation(null);
		}
	}
	
	public ResourceSyncInfo getResourceSync(IResource resource) throws CVSException {
		if (resource.getType() == IResource.ROOT) return null;
		ensureChildResourceSyncLoaded(resource.getParent());
		return getCachedResourceSync(resource);
	}

	public void deleteFolderSync(IContainer folder, IProgressMonitor monitor) throws CVSException {
		try {
			beginOperation(null);
			FolderSyncInfo info = getCachedFolderSync(folder);
			if (info != null && info != EMPTY_FOLDER_SYNC_INFO) {
				// remember that we deleted the folder sync info
				setCachedFolderSync(folder, EMPTY_FOLDER_SYNC_INFO);
				changedFolders.add(folder);
			}
		} finally {
			endOperation(null);
		}
	}
	
	public void deleteResourceSync(IResource resource, IProgressMonitor monitor) throws CVSException {
		try {
			beginOperation(null);
			ensureChildResourceSyncLoaded(resource.getParent());
			setCachedResourceSync(resource, null);
			changedResources.add(resource);
		} finally {
			endOperation(null);
		}
	}

	public String[] getIgnored(IResource resource) throws CVSException {
		IContainer parent = resource.getParent();
		if(parent==null || parent.getType()==IResource.ROOT) return null;
		String[] ignores = getCachedFolderIgnores(parent);
		if(ignores==null) {
			ICVSFile ignoreFile = CVSWorkspaceRoot.getCVSFileFor(parent.getFile(new Path(SyncFileWriter.IGNORE_FILE)));
			if(ignoreFile.exists()) {
				ignores = SyncFileWriter.readLines(ignoreFile);
				setCachedFolderIgnores(parent, ignores);
			}
		}
		return ignores;
	}
	
	public void setIgnored(IResource resource, String pattern) throws CVSException {
		SyncFileWriter.addCvsIgnoreEntry(CVSWorkspaceRoot.getCVSResourceFor(resource), pattern);
		TeamPlugin.getManager().broadcastResourceStateChanges(new IResource[] {resource});
	}
		
	public IResource[] members(IContainer folder) throws CVSException {
		try {
			// initialize cache if needed, this will create phantoms
			ensureChildResourceSyncLoaded(folder);
			IResource[] children = folder.members(true);
			List list = new ArrayList(children.length);
			for (int i = 0; i < children.length; ++i) {
				IResource child = children[i];
				if (! child.isPhantom() || getCachedResourceSync(child) != null) {
					list.add(child);
				}
			}
			return (IResource[]) list.toArray(new IResource[list.size()]);
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	static public void startup() {
		Assert.isTrue(instance==null);
		instance = new EclipseSynchronizer();	
		getSynchronizer().add(RESOURCE_SYNC_KEY);
		getSynchronizer().add(RESOURCE_SYNC_LOADED_KEY);
		getSynchronizer().add(FOLDER_SYNC_KEY);
		getSynchronizer().add(IGNORE_SYNC_KEY);
		try {
			flushAll(ResourcesPlugin.getWorkspace().getRoot(), false /*don't purge from disk*/);
		} catch(CVSException e) {
			//	// severe problem, it would mean that we are working with stale sync info
			CVSProviderPlugin.log(e.getStatus());
		}					
	}
	
	static public void shutdown() {
		// so that the workspace won't persist cached sync info
		getSynchronizer().remove(RESOURCE_SYNC_KEY);
		getSynchronizer().remove(RESOURCE_SYNC_LOADED_KEY);
		getSynchronizer().remove(FOLDER_SYNC_KEY);
		getSynchronizer().remove(IGNORE_SYNC_KEY);
	}
	
	public void beginOperation(IProgressMonitor monitor) throws CVSException {
		if (nestingCount++ == 0) {
			// any work here?
			
			// uncomment this line to bypass cache for testing
			//flushAll(ResourcesPlugin.getWorkspace().getRoot(), false /*don't purge from disk*/);			
		}		
	}
	
	public void endOperation(IProgressMonitor monitor) throws CVSException {
		if (--nestingCount == 0) {	
			if (! changedFolders.isEmpty() || ! changedResources.isEmpty()) {
				try {
					monitor = Policy.monitorFor(monitor);
					int numResources = changedFolders.size() + changedResources.size();
					monitor.beginTask(null, numResources);
					monitor.subTask("Updating CVS synchronization information...");
					/* write sync info to disk */
					List deletedFolderSync = new ArrayList();

					// folder sync info changes
					Iterator it = changedFolders.iterator();
					while (it.hasNext()) {
						IContainer folder = (IContainer) it.next();
						FolderSyncInfo info = getCachedFolderSync(folder);
						ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(folder);
						if (info == EMPTY_FOLDER_SYNC_INFO) {
							// deleted folder sync info since we loaded it, postpone change until later
							deletedFolderSync.add(folder);
						} else if (info == null) {
							// attempted to delete folder sync info for a previously unmanaged folder
							// no-op
						} else {
							// modified or created new folder sync info since we loaded it
							SyncFileWriter.writeFolderConfig(cvsFolder, info);
						}
						monitor.worked(1);
					}

					// resource sync info changes
					it = changedResources.iterator();
					while (it.hasNext()) {
						IResource resource = (IResource) it.next();
						ResourceSyncInfo info = getCachedResourceSync(resource);
						ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(resource);
						if(!isChildResourceSyncLoaded(resource.getParent())) {
							return;
						}
						Assert.isTrue(isChildResourceSyncLoaded(resource.getParent()));
						if (info == null) {
							// deleted resource sync info since we loaded it
							SyncFileWriter.deleteSync(cvsResource);
						} else {
							// modified or created new resource sync info since we loaded it
							SyncFileWriter.writeResourceSync(cvsResource, info);
						}
						monitor.worked(1);
					}
					
					// folder sync info deletes
					it = deletedFolderSync.iterator();
					while (it.hasNext()) {
						IContainer folder = (IContainer) it.next();
						// flush everything that was cached from the CVS subdirectory
						flushAll(folder, true /*purge from disk*/);
					}
					
					// broadcast events
					changedResources.addAll(changedFolders);				
					IResource[] resources = (IResource[]) changedResources.toArray(
						new IResource[changedResources.size()]);
					TeamPlugin.getManager().broadcastResourceStateChanges(resources);
					changedResources.clear();
					changedFolders.clear();
				} finally {
					monitor.done();
				}
			}
		}
		Assert.isTrue(nestingCount>= 0);
	}
	
	private static ISynchronizer getSynchronizer() {
		return ResourcesPlugin.getWorkspace().getSynchronizer();
	}
	
	/*
	 * Returns the cached resource sync info, or null if none found.
	 */
	private ResourceSyncInfo getCachedResourceSync(IResource resource) throws CVSException {
		try {
			byte[] bytes = getSynchronizer().getSyncInfo(RESOURCE_SYNC_KEY, resource);
			if(bytes == null) return null;
			return new ResourceSyncInfo(new String(bytes), null, null);
		} catch(CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	/*
	 * Sets the cached resource sync info, use null to delete it.
	 */
	private void setCachedResourceSync(IResource resource, ResourceSyncInfo info) throws CVSException {
		try {
			if(info==null) {
				getSynchronizer().setSyncInfo(RESOURCE_SYNC_KEY, resource, null); // faster than flush
			} else {
				getSynchronizer().setSyncInfo(RESOURCE_SYNC_KEY, resource, info.getEntryLine(true).getBytes());
			}
		} catch(CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	/*
	 * Returns the cached sync info for a folder, null if none found, or
	 * special placeholder EMPTY_FOLDER_SYNC_INFO for deleted sync info.
	 */
	private FolderSyncInfo getCachedFolderSync(IContainer folder) throws CVSException {
		try {
			byte[] bytes = getSynchronizer().getSyncInfo(FOLDER_SYNC_KEY, folder);
			if (bytes == null) return null;
			if (bytes.length == 0) return EMPTY_FOLDER_SYNC_INFO; // return placeholder for deleted sync info
			DataInputStream is = new DataInputStream(new ByteArrayInputStream(bytes));
			String repo = is.readUTF();
			String root = is.readUTF();
			String tag = is.readUTF();
			CVSTag cvsTag = null;
			boolean isStatic = is.readBoolean();
			if(!tag.equals("null")) {
				cvsTag = new CVSEntryLineTag(tag);
			}
			return new FolderSyncInfo(repo, root, cvsTag, isStatic);
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		} catch(IOException e) {
			throw CVSException.wrapException(e);
		}	
	}
	
	/*
	 * Sets the cached sync info for a folder, use null to flush, or special
	 * EMPTY_FOLDER_SYNC_INFO placeholder for deleted sync info.
	 */
	private void setCachedFolderSync(IContainer folder, FolderSyncInfo info) throws CVSException {
		try {
			if (info == null) {
				getSynchronizer().setSyncInfo(FOLDER_SYNC_KEY, folder, null); // faster than flush
			} else if (info == EMPTY_FOLDER_SYNC_INFO ) {
				// memorize placeholder for deleted sync info
				getSynchronizer().setSyncInfo(FOLDER_SYNC_KEY, folder, EMPTY_BYTES);
			} else {
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				DataOutputStream os = new DataOutputStream(bos);
				os.writeUTF(info.getRepository());
				os.writeUTF(info.getRoot());
				CVSEntryLineTag tag = info.getTag();
				if(tag==null) {
					os.writeUTF("null");
				} else {
					os.writeUTF(info.getTag().toEntryLineFormat(false));
				}
				os.writeBoolean(info.getIsStatic());				
				getSynchronizer().setSyncInfo(FOLDER_SYNC_KEY, folder, bos.toByteArray());
				os.close();
			}
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		} catch(IOException e) {
			throw CVSException.wrapException(e);
		}
	}	
	
	private String[] getCachedFolderIgnores(IContainer folder) throws CVSException {
		try {
			byte[] bytes = getSynchronizer().getSyncInfo(IGNORE_SYNC_KEY, folder);
			if (bytes == null) return null;
			DataInputStream is = new DataInputStream(new ByteArrayInputStream(bytes));
			int count = is.readInt();
			String[] ignoreList = new String[count];
			for(int i = 0; i < count; ++i) {
				ignoreList[i] = is.readUTF();
			}
			return ignoreList;
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		} catch(IOException e) {
			throw CVSException.wrapException(e);
		}				
	}
	
	private void setCachedFolderIgnores(IContainer folder, String[] ignores) throws CVSException {
		try {
			if (ignores == null) {
				getSynchronizer().setSyncInfo(IGNORE_SYNC_KEY, folder, null); // faster than flush
			} else {
				// a zero-length array indicates there were no ignores found
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				DataOutputStream os = new DataOutputStream(bos);
				os.writeInt(ignores.length);
				for(int i = 0; i < ignores.length; ++i) {
					os.writeUTF(ignores[i]);
				}
				getSynchronizer().setSyncInfo(IGNORE_SYNC_KEY, folder, bos.toByteArray());
				os.close();
			}
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		} catch(IOException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	/*
	 * Reads and caches the ResourceSyncInfos for this folder if not already cached.
	 */
	private void ensureChildResourceSyncLoaded(IContainer folder) throws CVSException {
		// don't try to load if the information is already cached
		if (isChildResourceSyncLoaded(folder)) return;
		ResourceSyncInfo[] infos = SyncFileWriter.readEntriesFile(CVSWorkspaceRoot.getCVSFolderFor(folder));
		if (infos != null) {
			for (int i = 0; i < infos.length; i++) {
				ResourceSyncInfo syncInfo = infos[i];
				IResource peer;
				IPath path = new Path(syncInfo.getName());
				if (syncInfo.isDirectory()) {
					peer = folder.getFolder(path);
				} else {
					peer = folder.getFile(path);
				}
				// may create a phantom if the sibling resource does not exist.
				setCachedResourceSync(peer, syncInfo);
			}
		}
		setChildResourceSyncLoaded(folder, true);
	}

	private boolean isChildResourceSyncLoaded(IContainer folder) throws CVSException {
		try {
			// root folder has no entries therefore info is always loaded
			if (folder.getType() == IResource.ROOT || ! folder.exists()) return true;
			return getSynchronizer().getSyncInfo(RESOURCE_SYNC_LOADED_KEY, folder) != null;
		} catch(CoreException e) {
			throw CVSException.wrapException(e);
		}		
	}
	
	private void setChildResourceSyncLoaded(IContainer folder, boolean isLoaded) throws CVSException {
		try {
			getSynchronizer().setSyncInfo(RESOURCE_SYNC_LOADED_KEY, folder, isLoaded ? EMPTY_BYTES : null);
		} catch(CoreException e) {
			throw CVSException.wrapException(e);
		}		

	}

	private void flushChildResourceSync(IContainer folder, int depth) throws CVSException {
		// flushSyncInfo fails with an exception if the folder does not exist
		if (! folder.exists()) return;
		try {
			byte[] folderSyncBytes = getSynchronizer().getSyncInfo(RESOURCE_SYNC_KEY, folder);
			getSynchronizer().flushSyncInfo(RESOURCE_SYNC_KEY, folder, depth);
			getSynchronizer().setSyncInfo(RESOURCE_SYNC_KEY, folder, folderSyncBytes);
		} catch(CoreException e) {
			throw CVSException.wrapException(folder, "Error flushing a folder's children sync", e);
		}
	}
	
	static private void flushAll(final IContainer root, final boolean purgeFromDisk) throws CVSException {
		if (! (root.exists() || root.isPhantom())) return;
		try {
			// purge sync information from children
			root.accept(new IResourceVisitor() {
				public boolean visit(IResource resource) throws CoreException {					
					if(! root.equals(resource)) {
						// don't clear resource sync on root since it might still be managed
						// by its parent
						getSynchronizer().setSyncInfo(RESOURCE_SYNC_KEY, resource, null);
					}
					if(resource.getType()!=IResource.FILE) {
						IContainer folder = (IContainer) resource;
						getSynchronizer().setSyncInfo(RESOURCE_SYNC_LOADED_KEY, folder, null);
						getSynchronizer().setSyncInfo(FOLDER_SYNC_KEY, folder, null);
						getSynchronizer().setSyncInfo(IGNORE_SYNC_KEY, folder, null);					
						if(purgeFromDisk) {
							SyncFileWriter.deleteCVSSubDirectory(folder);
						}
					}
					return true;					
				}

			}, IResource.DEPTH_INFINITE, true /*include phantoms*/);
		} catch(CoreException e) {
			throw CVSException.wrapException(root, "Problems occured flushing synchronizer cache", e);
		}
	}
}