/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Red Hat Incorporated - is/setExecutable() code
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.core.resources;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.*;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.history.IFileRevision;
import org.eclipse.team.core.variants.CachedResourceVariant;
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.Log;
import org.eclipse.team.internal.ccvs.core.client.listeners.ILogEntryListener;
import org.eclipse.team.internal.ccvs.core.client.listeners.LogListener;
import org.eclipse.team.internal.ccvs.core.connection.CVSServerException;
import org.eclipse.team.internal.ccvs.core.filehistory.CVSResourceVariantFileRevision;
import org.eclipse.team.internal.ccvs.core.filesystem.CVSURI;
import org.eclipse.team.internal.ccvs.core.syncinfo.*;

/**
 * This class provides the implementation of ICVSRemoteFile and IManagedFile for
 * use by the repository and sync view.
 */
public class RemoteFile extends RemoteResource implements ICVSRemoteFile  {
    /*
     * Listener for accumulating the entries fetched using the "cvs log" command
     */
	private final class LogEntryListener implements ILogEntryListener {
        private final List<ILogEntry> entries = new ArrayList<>();
        @Override
		public void handleLogEntryReceived(ILogEntry entry) {
            if (entry.getRemoteFile().getRepositoryRelativePath().equals(getRepositoryRelativePath())) {
                entries.add(entry);
            }
        }
        public ILogEntry[] getEntries() {
            return entries.toArray(new ILogEntry[entries.size()]);
        }
    }

    // sync info in byte form
	private byte[] syncBytes;
	// cache the log entry for the remote file
	private ILogEntry entry;
	// state that indicates that the handle is actively fetching content
	private boolean fetching = false;
	// executable bit
	private boolean executable = false;
			
	/**
	 * Static method which creates a file as a single child of its parent.
	 * This should only be used when one is only interested in the file alone.
	 * 
	 * The returned RemoteFile represents the base of the local resource.
	 * If the local resource does not have a base, then null is returned
	 * even if the resource does exists remotely (e.g. created by another party).
	 */
	public static RemoteFile getBase(RemoteFolder parent, ICVSFile managed) throws CVSException {
		Assert.isNotNull(parent, "A parent folder must be provided for file " + managed.getName()); //$NON-NLS-1$
		byte[] syncBytes = managed.getSyncBytes();
		if ((syncBytes == null) || ResourceSyncInfo.isAddition(syncBytes)) {
			// Either the file is unmanaged or has just been added (i.e. doesn't necessarily have a remote)
			return null;
		}
		if (ResourceSyncInfo.isDeletion(syncBytes)) {
			syncBytes = ResourceSyncInfo.convertFromDeletion(syncBytes);
		}
		RemoteFile file = new RemoteFile(parent, syncBytes);
		parent.setChildren(new ICVSRemoteResource[] {file});
		return file;
	}
	
	/**
	 * This method is used by the CVS subscribers to create file handles.
	 */
	public static RemoteFile fromBytes(IResource local, byte[] bytes, byte[] parentBytes) throws CVSException {
		Assert.isNotNull(bytes);
		Assert.isTrue(local.getType() == IResource.FILE);
		RemoteFolder parent = RemoteFolder.fromBytes(local.getParent(), parentBytes);
		RemoteFile file = new RemoteFile(parent, bytes);
		parent.setChildren(new ICVSRemoteResource[] {file});
		return file;
	}
	
	/**
	 * Create a remote file handle for the given file path that is relative to the
	 * given location.
	 */
	public static RemoteFile create(String filePath, ICVSRepositoryLocation location) {
		return create(filePath, location, null, null);
	}
	
	/**
	 * Create a remote file handle for the given file path that is relative to the
	 * given location.
	 */
	public static RemoteFile create(String filePath, ICVSRepositoryLocation location, CVSTag tag, String revision) {
		Assert.isNotNull(filePath);
		Assert.isNotNull(location);
		IPath path = new Path(null, filePath);
		if (tag != null && revision != null && tag.getName().equals(revision))
			tag = null;
		RemoteFolder parent = new RemoteFolder(null /* parent */, location, path.removeLastSegments(1).toString(), tag /* tag */);
		RemoteFile file = new RemoteFile(parent, Update.STATE_NONE, path.lastSegment(), revision /* revision */, null /* keyword mode */, tag /* tag */);
		parent.setChildren(new ICVSRemoteResource[] {file});
		return file;
	}
	
	/**
	 * Constructor for RemoteFile that should be used when nothing is know about the
	 * file ahead of time.
	 * @param parent the folder that is the parent of the file
	 * @param workspaceSyncState the workspace state (use Update.STATE_NONE if unknown)
	 * @param name the name of the file
	 * @param revision revision of the file or <code>null</code> if the revision is not known
	 * @param keywordMode keyword mode of the file or <code>null</code> if the mode is not known
	 * @param tag tag for the file
	 */
	public RemoteFile(RemoteFolder parent, int workspaceSyncState, String name, String revision, KSubstOption keywordMode, CVSTag tag) {
		this(parent, name, workspaceSyncState, getSyncBytes(name, revision, keywordMode, tag));
	}
	
	private static byte[] getSyncBytes(String name, String revision, KSubstOption keywordMode, CVSTag tag) {
		if (revision == null) {
			revision = ResourceSyncInfo.ADDED_REVISION;
		}
		if (keywordMode == null) {
			// Always use a blank mode for remote files so that 
			// the proper mode will be obtained when the contents
			// are fetched
			keywordMode = KSubstOption.fromMode(""); //$NON-NLS-1$
		}
		MutableResourceSyncInfo newInfo = new MutableResourceSyncInfo(name, revision);		
		newInfo.setKeywordMode(keywordMode);
		newInfo.setTag(tag);
		return newInfo.getBytes();
	}
	
	public RemoteFile(RemoteFolder parent, byte[] syncBytes) throws CVSException {
		this(parent, Update.STATE_NONE, syncBytes);
	}
	
	/* package */ RemoteFile(RemoteFolder parent, int workspaceSyncState, byte[] syncBytes) throws CVSException {
		this(parent, ResourceSyncInfo.getName(syncBytes), workspaceSyncState, syncBytes);
	}

	private RemoteFile(RemoteFolder parent, String name, int workspaceSyncState, byte[] syncBytes) {
		super(parent, name);
		this.syncBytes = syncBytes;
		setWorkspaceSyncState(workspaceSyncState);
	}

	/**
	 * @see ICVSResource#accept(ICVSResourceVisitor)
	 */
	@Override
	public void accept(ICVSResourceVisitor visitor) throws CVSException {
		visitor.visitFile(this);
	}

	/**
	 * @see ICVSResource#accept(ICVSResourceVisitor, boolean)
	 */
	@Override
	public void accept(ICVSResourceVisitor visitor, boolean recurse) throws CVSException {
		visitor.visitFile(this);
	}
	
	/**
	 * @see ICVSRemoteFile#getContents()
	 */
	@Override
	public InputStream getContents(IProgressMonitor monitor) throws CVSException {
		try {
			return getStorage(monitor).getContents();
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	@Override
	protected void fetchContents(IProgressMonitor monitor) throws TeamException {
		try {
			aboutToReceiveContents(getSyncBytes());
			internalFetchContents(monitor);
			// If the fetch succeeded but no contents were cached from the server
			// than we can assume that the remote file has no contents.
			if (!isContentsCached()) {
				setContents(new ByteArrayInputStream(new byte[0]), monitor);
			}
		} finally {
			doneReceivingContents();
		}
	}
	
	private void internalFetchContents(IProgressMonitor monitor) throws CVSException {
		monitor.beginTask(CVSMessages.RemoteFile_getContents, 100);
        monitor.subTask(CVSMessages.RemoteFile_getContents);
		if (getRevision().equals(ResourceSyncInfo.ADDED_REVISION)) {
			// The revision of the remote file is not known so we need to use the tag to get the status of the file
			CVSTag tag = getSyncInfo().getTag();
			if (tag == null) tag = CVSTag.DEFAULT;
			RemoteFolderMemberFetcher fetcher = new RemoteFolderMemberFetcher((RemoteFolder)getParent(), tag);
			fetcher.updateFileRevisions(new ICVSFile[] { this }, Policy.subMonitorFor(monitor, 10));
		}
		Session session = new Session(getRepository(), parent, false /* create backups */);
		session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
		try {
			IStatus status = Command.UPDATE.execute(
				session,
				Command.NO_GLOBAL_OPTIONS,
				new LocalOption[] { 
					Update.makeTagOption(new CVSTag(getRevision(), CVSTag.VERSION)),
					Update.IGNORE_LOCAL_CHANGES },
				new ICVSResource[] { this },
				null,
				Policy.subMonitorFor(monitor, 80));
			if (status.getCode() == CVSStatus.SERVER_ERROR) {
				throw new CVSServerException(status);
			}
		} finally {
			session.close();
			monitor.done();
		}
	}

	@Override
	public ILogEntry getLogEntry(IProgressMonitor monitor) throws CVSException {
		if (entry == null) {
			monitor = Policy.monitorFor(monitor);
			monitor.beginTask(CVSMessages.RemoteFile_getLogEntries, 100); 
			Session session = new Session(getRepository(), parent, false /* output to console */);
			session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
			try {
				try {
				    LogEntryListener listener = new LogEntryListener();
					IStatus status = Command.LOG.execute(
						session,
						Command.NO_GLOBAL_OPTIONS,
						new LocalOption[] { 
							Log.makeRevisionOption(getRevision())},
						new ICVSResource[] { RemoteFile.this },
						new LogListener(RemoteFile.this, listener),
						Policy.subMonitorFor(monitor, 90));
					ILogEntry[] entries = listener.getEntries();
					if (entries.length == 1) {
						entry = entries[0];
					}
					if (status.getCode() == CVSStatus.SERVER_ERROR) {
						throw new CVSServerException(status);
					}
				} finally {
					monitor.done();
				}
			} finally {
				session.close();
			}
		}
		return entry;
	}
	
	/**
	 * @see ICVSRemoteFile#getLogEntries()
	 */
	@Override
	public ILogEntry[] getLogEntries(IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(CVSMessages.RemoteFile_getLogEntries, 100); 
		Session session = new Session(getRepository(), parent, false /* output to console */);
		session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
		try {
			QuietOption quietness = CVSProviderPlugin.getPlugin().getQuietness();
			try {
				CVSProviderPlugin.getPlugin().setQuietness(Command.VERBOSE);
				LogEntryListener listener = new LogEntryListener();  
				IStatus status = Command.LOG.execute(
					session,
					Command.NO_GLOBAL_OPTIONS, Command.NO_LOCAL_OPTIONS,
					new ICVSResource[] { RemoteFile.this }, new LogListener(RemoteFile.this, listener),
					Policy.subMonitorFor(monitor, 90));
				if (status.getCode() == CVSStatus.SERVER_ERROR) {
					throw new CVSServerException(status);
				}
				return listener.getEntries();
			} finally {
				CVSProviderPlugin.getPlugin().setQuietness(quietness);
				monitor.done();
			}
		} finally { 
			session.close();
		}
	}
	
	/**
	 * @see ICVSRemoteFile#getRevision()
	 */
	@Override
	public String getRevision() {
		try {
			return ResourceSyncInfo.getRevision(syncBytes);
		} catch (CVSException e) {
			CVSProviderPlugin.log(e);
			return ResourceSyncInfo.ADDED_REVISION;
		}
	}
	
	private KSubstOption getKeywordMode() {
		try {
			return ResourceSyncInfo.getKeywordMode(syncBytes);
		} catch (CVSException e) {
			CVSProviderPlugin.log(e);
			return KSubstOption.getDefaultTextMode();
		}
	}
	
	/*
	 * Get a different revision of the remote file.
	 * 
	 * We must also create a new parent since the child is accessed through the parent from within CVS commands.
	 * Therefore, we need a new parent so that we can fetch the contents of the remote file revision
	 */
	public RemoteFile toRevision(String revision) {
		RemoteFolder newParent = new RemoteFolder(null, parent.getRepository(), parent.getRepositoryRelativePath(), parent.getTag());
		RemoteFile file = new RemoteFile(newParent, getWorkspaceSyncState(), getName(), revision, getKeywordMode(), CVSTag.DEFAULT);
		newParent.setChildren(new ICVSRemoteResource[] {file});
		return file;
	}

	/**
	 * @see ICVSFile#getSyncInfo()
	 */
	@Override
	public ResourceSyncInfo getSyncInfo() {
		try {
			return new ResourceSyncInfo(syncBytes);
		} catch (CVSException e) {
			CVSProviderPlugin.log(e);
			return null;
		}
	}
	
	/**
	 * @see ICVSResource#getRemoteLocation(ICVSFolder)
	 */
	@Override
	public String getRemoteLocation(ICVSFolder stopSearching) throws CVSException {
		return parent.getRemoteLocation(stopSearching) + Session.SERVER_SEPARATOR + getName();
	}
	
	/**
	 * Get the remote path for the receiver relative to the repository location path
	 */
	@Override
	public String getRepositoryRelativePath() {
		String parentPath = parent.getRepositoryRelativePath();
		return parentPath + Session.SERVER_SEPARATOR + getName();
	}
	
	/**
	 * Return the server root directory for the repository
	 */
	@Override
	public ICVSRepositoryLocation getRepository() {
		return parent.getRepository();
	}
	
	/**
	 * @see IManagedFile#setFileInfo(FileProperties)
	 */
	@Override
	public void setSyncInfo(ResourceSyncInfo fileInfo, int modificationState) {
		setSyncBytes(fileInfo.getBytes(),modificationState);
	}

	/**
	 * Set the revision for this remote file.
	 * 
	 * @param revision to associated with this remote file
	 */
	public void setRevision(String revision) throws CVSException {
		syncBytes = ResourceSyncInfo.setRevision(syncBytes, revision);
	}		
	
	@Override
	public InputStream getContents() throws CVSException {
		if (!fetching) {
			// Return the cached contents
			if (isContentsCached()) {
				try {
					InputStream cached = getCachedContents();
					if (cached != null) {
						return cached;
					}
				} catch (TeamException e) {
					throw CVSException.wrapException(e);
				}
			}
		}
		// There was nothing cached so return an empty stream.
		// This is done to allow the contents to be fetched
		// (i.e. update sends empty contents and real contents are sent back)
		return new ByteArrayInputStream(new byte[0]);
	}

	@Override
	protected InputStream getCachedContents() throws TeamException {
		if (isHandleCached()) {
			RemoteFile file = (RemoteFile)getCachedHandle();
			if (file != null) {
				byte[] newSyncBytes = file.getSyncBytes();
				if (newSyncBytes != null) {
					// Make sure the sync bytes match the content that is being accessed
					syncBytes = newSyncBytes;
				}
			}
		}
		return super.getCachedContents();
	}
	
	@Override
	public void setContents(InputStream stream, int responseType, boolean keepLocalHistory, IProgressMonitor monitor) throws CVSException {
		try {
			setContents(stream, monitor);
		} catch (TeamException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	@Override
	public void setReadOnly(boolean readOnly) {
		// RemoteFiles are always read only
 	}

	@Override
	public boolean isReadOnly() {
		return true;
	}
	
	@Override
	public Date getTimeStamp() {
		return getSyncInfo().getTimeStamp();
	}

	@Override
	public void setTimeStamp(Date date) {
		// RemoteFiles are not mutable so do not support timestamp changes
	}

	/**
	 * @see ICVSFile#moveTo(String)
	 */
	@Override
	public void copyTo(String mFile) {		
		// Do nothing
	}
	
	@Override
	public ICVSRemoteResource[] members(IProgressMonitor progress) {
		return new ICVSRemoteResource[0];
	}

	@Override
	public boolean isContainer() {
		return false;
	}

	@Override
	public boolean isFolder() {
		return false;
	}
	
	/*
	 * @see ICVSResource#tag(CVSTag, LocalOption[], IProgressMonitor)
	 * 
	 * The revision of the remote file is used as the base for the tagging operation
	 */
	 @Override
	public IStatus tag(final CVSTag tag, final LocalOption[] localOptions, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		Session session = new Session(getRepository(), getParent(), true /* output to console */);
		session.open(Policy.subMonitorFor(monitor, 10), true /* open for modification */);
		try {
			return Command.RTAG.execute(
				session,
				Command.NO_GLOBAL_OPTIONS,
				localOptions,
				new CVSTag(getRevision(), CVSTag.VERSION),
				tag,
				new ICVSRemoteResource[] { RemoteFile.this },
			Policy.subMonitorFor(monitor, 90));
		} finally {
			session.close();
		}
	 }
	
	@Override
	public boolean equals(Object target) {
		if (this == target)
			return true;
		if (!(target instanceof RemoteFile))
			return false;
		RemoteFile remote = (RemoteFile) target;
		return super.equals(target) && remote.getRevision().equals(getRevision());
	}

	/**
	 * @see org.eclipse.team.internal.ccvs.core.ICVSFile#checkout(int)
	 */
	@Override
	public void edit(int notifications, boolean notifyForWritable, IProgressMonitor monitor) {
		// do nothing
	}

	/**
	 * @see org.eclipse.team.internal.ccvs.core.ICVSFile#uncheckout()
	 */
	@Override
	public void unedit(IProgressMonitor monitor) {
		// do nothing
	}

	/**
	 * @see org.eclipse.team.internal.ccvs.core.ICVSFile#notificationCompleted()
	 */
	@Override
	public void notificationCompleted() {
		// do nothing
	}

	/**
	 * @see org.eclipse.team.internal.ccvs.core.ICVSFile#getPendingNotification()
	 */
	@Override
	public NotifyInfo getPendingNotification() {
		return null;
	}

	/**
	 * @see RemoteResource#forTag(ICVSRemoteFolder, CVSTag)
	 */
	@Override
	public ICVSRemoteResource forTag(ICVSRemoteFolder parent, CVSTag tag) {
		return new RemoteFile((RemoteFolder)parent, getWorkspaceSyncState(), getName(), getRevision(), getKeywordMode(), tag);
	}

	/**
	 * @see org.eclipse.team.internal.ccvs.core.ICVSRemoteResource#forTag(org.eclipse.team.internal.ccvs.core.CVSTag)
	 */
	@Override
	public ICVSRemoteResource forTag(CVSTag tag) {
		RemoteFolderTree remoteFolder = new RemoteFolderTree(null, getRepository(), 
			((ICVSRemoteFolder)getParent()).getRepositoryRelativePath(), 
			tag);
		RemoteFile remoteFile = (RemoteFile)forTag(remoteFolder, tag);
		remoteFolder.setChildren(new ICVSRemoteResource[] { remoteFile });
		return remoteFile;
	}
	/**
	 * @see org.eclipse.team.internal.ccvs.core.ICVSFile#committed(org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo)
	 */
	@Override
	public void checkedIn(String info, boolean commit) {
		// do nothing
	}
	/**
	 * @see org.eclipse.team.internal.ccvs.core.ICVSFile#isEdited()
	 */
	@Override
	public boolean isEdited() {
		return false;
	}
	/**
	 * @see org.eclipse.team.internal.ccvs.core.ICVSFile#getSyncBytes()
	 */
	@Override
	public byte[] getSyncBytes() {
		return syncBytes;
	}
	/**
	 * @see org.eclipse.team.internal.ccvs.core.ICVSFile#setSyncBytes(byte[])
	 */
	@Override
	public void setSyncBytes(byte[] syncBytes, int modificationState) {
		if (fetching) {
			RemoteFile file = (RemoteFile)getCachedHandle();
			if (file == null) {
				cacheHandle();
			} else if (file != this) {
				file.setSyncBytes(syncBytes, modificationState);
			}
		}
		this.syncBytes = syncBytes;
	}

	@Override
	public String toString() {
		return super.toString() + " " + getRevision(); //$NON-NLS-1$
	}

	@Override
	public String getContentIdentifier() {
		return getRevision();
	}

	/**
	 * Callback which indicates that the remote file is about to receive contents that should be cached
	 * @param entryLine
	 */
	public void aboutToReceiveContents(byte[] entryLine) {
		try {
			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=189025
			entryLine = ResourceSyncInfo.setSlot(syncBytes, 3, new byte[0]);
		} catch (CVSException e) {
			// log it and proceed
			CVSProviderPlugin.log(e);
		}
		setSyncBytes(entryLine, ICVSFile.CLEAN);
		fetching = true;
	}

	/**
	 * The contents for the file have already been provided.
	 */
	public void doneReceivingContents() {
		fetching = false;
	}
	
	@Override
	public boolean isContentsCached() {
		// Made public for use by FileContentCachingService
		return super.isContentsCached();
	}

	/**
	 * Cache the contents of the given IFile as the contents for this remote file handle.
	 * The caller must ensure that the local file is mapped to the same revision and is
	 * not modified since it was loaded from CVS.
	 * @param file
	 * @throws CoreException
	 * @throws TeamException
	 */
	public void setContents(IFile file, IProgressMonitor monitor) throws TeamException, CoreException {
	    setContents(file.getContents(), monitor);
	}

	@Override
	public void setExecutable(boolean executable) throws CVSException {
		// store executable bit;
		this.executable = executable;
		if (!isHandleCached()) {
			cacheHandle();
		}
		RemoteFile file = (RemoteFile)getCachedHandle();
		if (file != this) {
			file.setExecutable(executable);
		}
	}

	@Override
	public boolean isExecutable() throws CVSException {
		// return executable bit
		return executable;
	}
	
	@Override
	public CachedResourceVariant getCachedHandle() {
		return super.getCachedHandle();
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> T getAdapter(Class<T> adapter) {
		if (adapter == IFileRevision.class)
			return (T) new CVSResourceVariantFileRevision(this);
		return super.getAdapter(adapter);
	}
	
	public CVSURI toCVSURI() {
		ResourceSyncInfo info = getSyncInfo();
		return new CVSURI(getRepository(), new Path(getRepositoryRelativePath()), info.getTag(), info.getRevision());
	}
}
