/*******************************************************************************
 * Copyright (c) 2000, 2006 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.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.*;
import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
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;

/**
 * This class can be used to fetch and cache file contents for remote files.
 */
public class UpdateContentCachingService implements IUpdateMessageListener {

	private CVSRepositoryLocation repository;
	private ICVSFolder remoteRoot;
	private final CVSTag tag;
	private final int depth;
	private boolean fetchAbsentDirectories = true;
	private ArrayList<ICVSResource> removed = new ArrayList<>();

	public class SandboxUpdate extends Update {
		
		@Override
		protected boolean shouldRetrieveAbsentDirectories(Session session) {
			return fetchAbsentDirectories;
		}
		
		@Override
		protected IStatus commandFinished(Session session, GlobalOption[] globalOptions, LocalOption[] localOptions, ICVSResource[] resources, IProgressMonitor monitor, IStatus status) throws CVSException {
			// Don't do anything (i.e. don't prune)
			return status;
		}

		@Override
		protected IStatus doExecute(Session session, GlobalOption[] globalOptions, LocalOption[] localOptions, String[] arguments, ICommandOutputListener listener, IProgressMonitor monitor) throws CVSException {
			session.registerResponseHandler(new SandboxUpdatedHandler(UpdatedHandler.HANDLE_CREATED));
			session.registerResponseHandler(new SandboxUpdatedHandler(UpdatedHandler.HANDLE_MERGED));
			session.registerResponseHandler(new SandboxUpdatedHandler(UpdatedHandler.HANDLE_UPDATE_EXISTING));
			session.registerResponseHandler(new SandboxUpdatedHandler(UpdatedHandler.HANDLE_UPDATED));
			return super.doExecute(session, globalOptions, localOptions, arguments, listener, monitor);
		}
	}
	
	/**
	 * This class overrides the "Created" handler in order to configure the remote file
	 * to receive and cache the contents
	 */
	public class SandboxUpdatedHandler extends UpdatedHandler {
		public SandboxUpdatedHandler(int type) {
			super(type);
		}
		@Override
		protected void receiveTargetFile(
			Session session,
			ICVSFile mFile,
			String entryLine,
			Date modTime,
			boolean binary,
			boolean readOnly,
			boolean executable,
			IProgressMonitor monitor)
			throws CVSException {
			
			// Set the sync info first so that the contents are cached properly
			ResourceSyncInfo info = new ResourceSyncInfo(entryLine, modTime);
			// We're always excepting new revisions so the file is clean
			mFile.setSyncInfo(info, ICVSFile.CLEAN);
			
			// receive the file contents from the server
			session.receiveFile(mFile, binary, getHandlerType(), monitor);
			
			// Handle execute
			try {
				if (executable) mFile.setExecutable(true);
			} catch (CVSException e) {
				// Just log and keep going
				CVSProviderPlugin.log(e);
			}
		}
	}
	
	public static RemoteFolder buildRemoteTree(final CVSRepositoryLocation repository, ICVSFolder root, CVSTag tag, int depth, IProgressMonitor monitor) throws CVSException {
		monitor.beginTask(null, 100);
		try {
			RemoteFolder tree = buildBaseTree(repository, root, tag, Policy.subMonitorFor(monitor, 50));
			UpdateContentCachingService service = new UpdateContentCachingService(repository, tree, tag, depth);
			service.setFetchAbsentDirectories(getFetchAbsentDirectories(root));
			if (!service.cacheFileContents(Policy.subMonitorFor(monitor, 50)))
				return null;
			return tree;
		} finally {
			monitor.done();
		}
	}
	
	private void setFetchAbsentDirectories(boolean fetchAbsentDirectories) {
		this.fetchAbsentDirectories = fetchAbsentDirectories;
	}

	private static boolean getFetchAbsentDirectories(ICVSFolder root) {
		IResource resource = root.getIResource();
		if (resource != null) {
			IProject project = resource.getProject();
			RepositoryProvider provider = RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId());
			if (provider instanceof CVSTeamProvider) {
				CVSTeamProvider cp = (CVSTeamProvider) provider;
				try {
					return cp.getFetchAbsentDirectories();
				} catch (CVSException e) {
					CVSProviderPlugin.log(e);
				}
			}
		}
		return CVSProviderPlugin.getPlugin().getFetchAbsentDirectories();
	}

	private static RemoteFolder buildBaseTree(final CVSRepositoryLocation repository, ICVSFolder root, CVSTag tag, IProgressMonitor progress) throws CVSException {
		try {
			RemoteFolderTreeBuilder builder = new RemoteFolderTreeBuilder(repository, root, tag) {
				protected RemoteFolder createRemoteFolder(ICVSFolder local, RemoteFolder parent, FolderSyncInfo folderSyncInfo) {
					return new RemoteFolderSandbox(parent, local.getName(), repository, folderSyncInfo.getRepository(), folderSyncInfo.getTag(), folderSyncInfo.getIsStatic());
				}
				protected RemoteFile createRemoteFile(RemoteFolder remote, byte[] syncBytes) throws CVSException {
					return new RemoteFile(remote, syncBytes){
						public boolean isModified(IProgressMonitor monitor) throws CVSException {
							return false;
						}	
						public void delete() {
							RemoteFolderSandbox parent = (RemoteFolderSandbox)getParent();
							parent.remove(this);
						}
					};
				}
				protected boolean isPruneEmptyDirectories() {
					return true;
				}
			};
			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() })); 
			RemoteFolder tree = builder.buildBaseTree(null, root, subProgress);
			if (tree == null) {
				// The local tree is empty and was pruned.
				// Return the root folder so that the operation can proceed
				FolderSyncInfo folderSyncInfo = root.getFolderSyncInfo();
				if (folderSyncInfo == null) return null;
				return new RemoteFolderSandbox(null, root.getName(), repository, folderSyncInfo.getRepository(), folderSyncInfo.getTag(), folderSyncInfo.getIsStatic());
			}
			return tree;
		} finally {
			progress.done();
		}
	}
	
	public static RemoteFile buildRemoteTree(CVSRepositoryLocation repository, ICVSFile file, CVSTag tag, IProgressMonitor monitor) throws CVSException {
		monitor.beginTask(null, 100);
		try {
			RemoteFolderTreeBuilder builder = new RemoteFolderTreeBuilder(repository, file.getParent(), tag);
			RemoteFile remote =  builder.buildTree(file, Policy.subMonitorFor(monitor, 10));
			
			if (remote == null)
				return null;
			
			byte[] syncBytes = remote.getSyncBytes();
			if (builder.getFileDiffs().length > 0) {
				// Getting the storage of the file will cache the contents
				remote.getStorage(Policy.subMonitorFor(monitor, 90));
			}
			// We need to set the sync bytes back because the content fetch
			// makes the handle sticky
			remote.setSyncBytes(syncBytes, ICVSFile.CLEAN);
			return remote;
		} catch (TeamException e) {
			throw CVSException.wrapException(e);
		} finally {
			monitor.done();
		}
	}
	
	public UpdateContentCachingService(CVSRepositoryLocation repository, RemoteFolder tree, CVSTag tag, int depth) {
		this.repository = repository;
		this.remoteRoot = tree;
		this.tag = tag;
		this.depth = depth;
	}
	
	private boolean cacheFileContents(IProgressMonitor monitor) throws CVSException {
		// Fetch the file contents for all out-of-sync files by running an update
		// on the remote tree passing the known changed files as arguments
		monitor.beginTask(null, 100);
		Policy.checkCanceled(monitor);
		Session session = new Session(repository, remoteRoot, false);
		session.open(Policy.subMonitorFor(monitor, 10), false /* read-only */);
		try {
			Policy.checkCanceled(monitor);
			IStatus status = new SandboxUpdate().execute(session,
				Command.NO_GLOBAL_OPTIONS,
				getLocalOptions(),
				new String[] { Session.CURRENT_LOCAL_FOLDER },
				new UpdateListener(this),
				Policy.subMonitorFor(monitor, 90));
			if (!status.isOK()) {
				if (status.getCode() == CVSStatus.SERVER_ERROR) {
					CVSServerException e = new CVSServerException(status);
					if ( ! e.isNoTagException() && e.containsErrors())
						throw e;
					return false;
				} else if (status.getSeverity() == IStatus.ERROR && isReportableError(status)) {
					throw new CVSException(status);
				}
			}
			for (Iterator iterator = removed.iterator(); iterator.hasNext();) {
				ICVSResource resource = (ICVSResource) iterator.next();
				if (resource.exists())
					resource.delete();
			}
		} finally {
			session.close();
			monitor.done();
		}
		return true;
	}

	private boolean isReportableError(IStatus status) {
		return CVSStatus.isInternalError(status) 
			|| status.getCode() == TeamException.UNABLE
			|| status.getCode() == CVSStatus.INVALID_LOCAL_RESOURCE_PATH
			|| status.getCode() == CVSStatus.RESPONSE_HANDLING_FAILURE;
	}

	private LocalOption[] getLocalOptions() {
		ArrayList<LocalOption> options = new ArrayList<>();
		if (tag != null)
			options.add(Update.makeTagOption(tag));
		
		if (depth != IResource.DEPTH_INFINITE )
			options.add(Command.DO_NOT_RECURSE);
		
		if (fetchAbsentDirectories)
			options.add(Update.RETRIEVE_ABSENT_DIRECTORIES);
		
		if (!options.isEmpty())
			return options.toArray(new LocalOption[options.size()]);
		
		return Command.NO_LOCAL_OPTIONS;
	}

	public void directoryDoesNotExist(ICVSFolder commandRoot, String path) {
		try {
			removed.add(commandRoot.getChild(path));
		} catch (CVSException e) {
			CVSProviderPlugin.log(e);
		}
	}

	public void directoryInformation(ICVSFolder commandRoot, String path,
			boolean newDirectory) {
		// Nothing to do
	}

	public void fileDoesNotExist(ICVSFolder parent, String filename) {
		try {
			removed.add(parent.getChild(filename));
		} catch (CVSException e) {
			CVSProviderPlugin.log(e);
		}
	}

	public void fileInformation(int type, ICVSFolder parent, String filename) {
		// Nothing to do
	}
}
