/*******************************************************************************
 * Copyright (c) 2000, 2018 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.ui.subscriber;

import java.lang.ref.SoftReference;
import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.subscribers.Subscriber;
import org.eclipse.team.core.synchronize.*;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFile;
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;
import org.eclipse.team.internal.ccvs.ui.CVSUIMessages;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.ccvs.ui.Policy;
import org.eclipse.team.internal.ccvs.ui.actions.CVSAction;
import org.eclipse.team.internal.ccvs.ui.mappings.ModelCompareParticipant;
import org.eclipse.team.internal.ccvs.ui.operations.RemoteLogOperation;
import org.eclipse.team.internal.ccvs.ui.operations.RemoteLogOperation.LogEntryCache;
import org.eclipse.team.internal.core.BackgroundEventHandler;
import org.eclipse.team.internal.core.subscribers.SubscriberResourceCollector;
import org.eclipse.team.ui.synchronize.*;

/**
 * This class wraps a LogEntryCache in order to clear entries once they are no longer
 * in the subscriber.
 */
public class LogEntryCacheUpdateHandler extends BackgroundEventHandler {
	
	private static final int REMOVAL = 1;
	private static final int CHANGE = 2;
	private static final int FETCH_REQUEST = 3;
	private static final int PAUSE = 4;
	
	/*
	 * Lock used to ensure that fetches are queued when the job is
	 * a non-system job.
	 */
	private final Object queueLock = new Object();
	
	/*
	 * Exception used to stop processing so the job can be restarted as a non-system job
	 */
	private static final OperationCanceledException PAUSE_EXCEPTION = new OperationCanceledException();
	
	/*
	 * Contants for configuring how long to wait for the job to be paused
	 * when a fetch is required and the job needs to be converted to a non-system
	 * job. If the wait time is elapsed, an exception is thrown.
	 */
	private static final int WAIT_INCREMENT = 10;
	private static final int MAX_WAIT = 1000;
	
	/*
	 * Set that keeps track of all resource for which we haved fetched log entries
	 */
	private final SyncInfoTree collectedInfos = new SyncInfoTree();
	
	/*
	 * The cache that hold the log entries while the job is running
	 */
	//private LogEntryCache logEntriesCache;
	
	/*
	 * SoftReference used to hold on to the log entry cache while
	 * the job is not running so the cache can be cleared if memory is low.
	 */
	private SoftReference cacheReference;
	
	/*
	 * Collector that forewards subscriber changes so that
	 * stale cache entries can be cleared.
	 */
	private final LogEntryResourceCollector collector;

	/*
	 * The subscriber generating the SyncInfo and log entries
	 */
	private final Subscriber subscriber;
	
	/*
	 * The accumulated list of updates that need to be dispatched
	 * (i.e. the cache should be purged of out-of-date resources).
	 * This list is only modified and accessed from the event processing
	 * thread.
	 */
	private final List<Event> updates = new ArrayList<>();
	
	/*
	 * The accumulated list of fetches that have been requested
	 */
	private final List<Event> fetches = new ArrayList<>();
	private final ISynchronizePageConfiguration configuration;
	
	
	/*
	 * Interface for notifying a single client that the infos have been fetched
	 */
	public interface ILogsFetchedListener {

		void logEntriesFetched(SyncInfoSet set, LogEntryCache logEntryCache, IProgressMonitor monitor);
		
	}
	
	/*
	 * The listener or null if noone is listening
	 */
	private ILogsFetchedListener listener;
	
	/*
	 * Subscriber resource collector that forwards subscriber changes
	 * through the handler so that stale cache entries can be cleared
	 */
	private class LogEntryResourceCollector extends SubscriberResourceCollector {

		public LogEntryResourceCollector(Subscriber subscriber) {
			super(subscriber);
		}

		@Override
		protected void remove(IResource resource) {
			queueEvent(new ResourceEvent(resource, REMOVAL, IResource.DEPTH_INFINITE), false /* do not put in on the front of the queue*/);  
		}

		@Override
		protected void change(IResource resource, int depth) {
			queueEvent(new ResourceEvent(resource, CHANGE, depth), false /* do not put in on the front of the queue*/); 
		}

		@Override
		protected boolean hasMembers(IResource resource) {
			return collectedInfos.hasMembers(resource);
		}
	}
	
	/*
	 * Custom event for queue a log entry fetch request
	 */
	private class FetchRequest extends Event {
		private final SyncInfo[] infos;
		public FetchRequest(SyncInfo[] infos) {
			super(FETCH_REQUEST);
			this.infos = infos;
		}
		public SyncInfo[] getInfos() {
			return infos;
		}
	}
	
	public LogEntryCacheUpdateHandler(ISynchronizePageConfiguration configuration) {
		super(CVSUIMessages.LogEntryCacheUpdateHandler_1, CVSUIMessages.LogEntryCacheUpdateHandler_0); // 
		this.configuration = configuration;
		this.subscriber = getSubscriber(configuration);
		cacheReference = new SoftReference(new LogEntryCache());
		collector = new LogEntryResourceCollector(subscriber);
	}

	private Subscriber getSubscriber(ISynchronizePageConfiguration configuration) {
		ISynchronizeParticipant participant = configuration.getParticipant();
		if (participant instanceof SubscriberParticipant) {
			SubscriberParticipant sp = (SubscriberParticipant) participant;
			return sp.getSubscriber();
		}
		if (participant instanceof ModelCompareParticipant) {
			ModelCompareParticipant mcp = (ModelCompareParticipant) participant;
			return mcp.getSubscriber();
		}
		return CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber();
	}

	public ISynchronizePageConfiguration getConfiguration() {
		return configuration;
	}
	
	public Subscriber getSubscriber() {
		return subscriber;
	}
	
	/**
	 * Set the listener that should receive notification when log entries
	 * have been fetched and are avalable.
	 * @param listener the listener or <code>null</code>
	 */
	public void setListener(ILogsFetchedListener listener) {
		this.listener = listener;
	}
	
	@Override
	protected Object getJobFamiliy() {
		return ISynchronizeManager.FAMILY_SYNCHRONIZE_OPERATION;
	}
	
	@Override
	protected void createEventHandlingJob() {
		super.createEventHandlingJob();
		Job job = getEventHandlerJob();
		job.setSystem(false);
		job.setUser(false);
	}
	
	@Override
	protected void processEvent(Event event, IProgressMonitor monitor) throws CoreException {
		Policy.checkCanceled(monitor);
		switch (event.getType()) {
			case REMOVAL:
			case CHANGE:
				updates.add(event);
				break;
			case FETCH_REQUEST:
				fetches.add(event);
				break;
			case PAUSE:
				throw PAUSE_EXCEPTION;
		}
		
	}
	
	@Override
	protected boolean doDispatchEvents(IProgressMonitor monitor) throws TeamException {
		Policy.checkCanceled(monitor);
		boolean dispatched = false;
		monitor.beginTask(null, 50);
		dispatched |= updateCache(Policy.subMonitorFor(monitor, 20));
		dispatched |= processQueuedFetches(Policy.subMonitorFor(monitor, 80));
		monitor.done();
		return dispatched;
	}
	
	/*
	 * Remove any stale or unneeded log entries from the cache.
	 * Return whether there were any entries to purge.
	 */
	private boolean updateCache(IProgressMonitor monitor) {
		if (updates.isEmpty()) return false;
		try {
			collectedInfos.beginInput();
			// Cycle through the update events
			for (Iterator iter = updates.iterator(); iter.hasNext();) {
				Event event = (Event) iter.next();
				Policy.checkCanceled(monitor);
				if (event.getType() == REMOVAL) {
					remove(event.getResource(), ((ResourceEvent)event).getDepth());
				} else if (event.getType() == CHANGE) {
					change(event.getResource(), ((ResourceEvent)event).getDepth());
				}
				// Use the iterator to remove so that updates will not be lost
				// if the job is cancelled and then restarted.
				iter.remove();
			}
		} finally {
			collectedInfos.endInput(monitor);
		}
		return true;
	}

	@Override
	public void shutdown() {
		super.shutdown();
		collector.dispose();
		// Probably not necessary as GC would take care of it but we'll do it anyway
		if (cacheReference != null) {
			LogEntryCache cache = (LogEntryCache)cacheReference.get();
			if (cache != null) {
				cache.clearEntries();
			}
		}
		collectedInfos.clear();
		
	}
	
	private void remove(IResource resource, int depth) {
		collectedInfos.remove(resource, depth);
	}

	private void remove(SyncInfo info) {
		if (info != null) {
			collectedInfos.remove(info.getLocal());
			LogEntryCache cache = (LogEntryCache)cacheReference.get();
			if (cache != null) {
				ICVSRemoteResource remoteResource = getRemoteResource(info);
				if (remoteResource != null)
					cache.clearEntries(remoteResource);
			}
		}
	}

	public ICVSRemoteResource getRemoteResource(SyncInfo info) {
		try {
			ICVSRemoteResource remote = (ICVSRemoteResource) info.getRemote();
			ICVSRemoteResource local = CVSWorkspaceRoot.getRemoteResourceFor(info.getLocal());
			if(local == null) {
				local = (ICVSRemoteResource)info.getBase();
			}
			
			boolean useRemote = true;
			if (local != null && remote != null) {
				String remoteRevision = getRevisionString(remote);
				String localRevision = getRevisionString(local);
				useRemote = useRemote(localRevision, remoteRevision);
			} else if (remote == null) {
				useRemote = false;
			}
			if (useRemote) {
				return remote;
			} else if (local != null) {
				return local;
			}
			return null;
		} catch (CVSException e) {
			CVSUIPlugin.log(e);
			return null;
		}
	}

	private boolean useRemote(String localRevision, String remoteRevision) {
		boolean useRemote;
		if (remoteRevision == null && localRevision == null) {
			useRemote = true;
		} else if (localRevision == null) {
			useRemote = true;
		} else if (remoteRevision == null) {
			useRemote = false;
		} else {
			useRemote = ResourceSyncInfo.isLaterRevision(remoteRevision, localRevision);
		}
		return useRemote;
	}

	private String getRevisionString(ICVSRemoteResource remoteFile) {
		if(remoteFile instanceof RemoteFile) {
			return ((RemoteFile)remoteFile).getRevision();
		}
		return null;
	}
	
	private void change(IResource resource, int depth) {
		// We only need to remove collected log entries that don't apply
		// any longer. They will be refetched when they are required.
		SyncInfo[] collected = collectedInfos.getSyncInfos(resource, depth);
		change(collected);
	}
	
	private void change(SyncInfo[] collected) {
		Subscriber subscriber = getSubscriber();
		for (int i = 0; i < collected.length; i++) {
			try {
				SyncInfo info = collected[i];
				SyncInfo newInfo = subscriber.getSyncInfo(info.getLocal());
				if (newInfo == null || !newInfo.equals(info)) {
					// The cached log entry no longer applies to the new sync info.
					// It will be refetched when required.
					remove(info);
				}
			} catch (TeamException e) {
				// Log and continue
				CVSUIPlugin.log(e);
			}
		}
	}

	/**
	 * Queue a request to fetch log entries for the given SyncInfo nodes.
	 * The event handler must be a non-system job when revision histories 
	 * are fetched.
	 * @param infos the nodes whose log entries are to be fetched
	 */
	public void fetch(SyncInfo[] infos) throws CVSException {
		synchronized(queueLock) {
			Job job = getEventHandlerJob();
			if (job.isSystem() && job.getState() != Job.NONE) {
				// queue an event to pause the processor
				super.queueEvent(new Event(PAUSE), true /* put on the front of the queue */);
				int count = 0;
				while (job.getState() != Job.NONE && count < MAX_WAIT) {
					count += WAIT_INCREMENT;
					try {
						Thread.sleep(WAIT_INCREMENT); // Wait a little while
					} catch (InterruptedException e) {
						// Ignore
					}
				}
				if (job.getState() != Job.NONE) {
					// The job never completed in the time aloted so throw an exception
					throw new CVSException(CVSUIMessages.LogEntryCacheUpdateHandler_2); 
				}
			}
			// Queue the event even if the job didn't stop in the time aloted
			queueEvent(new FetchRequest(infos), false /* don't place at the end */);
		}
	}
	
	@Override
	protected void queueEvent(Event event, boolean front) {
		// Override to snure that queues by this handler are serialized
		synchronized(queueLock) {
			Job job = getEventHandlerJob();
			if (job.getState() == Job.NONE) {
				job.setSystem(event.getType() != FETCH_REQUEST); 
			}
			super.queueEvent(event, front);
		}
	}
	
	/*
	 * Method invoked during event dispatch to fetch log entries
	 */
	private boolean processQueuedFetches(IProgressMonitor monitor) {
		if (fetches.isEmpty()) return false;
		try {
			// Now perform the fetching
			Map projectMapping = getFetchesByProject();
			if (projectMapping.isEmpty()) return true;
			LogEntryCache logEntriesCache = (LogEntryCache)cacheReference.get();
			if (logEntriesCache == null) {
				logEntriesCache = new LogEntryCache();
				cacheReference = new SoftReference(logEntriesCache);
			}
			monitor.beginTask(CVSUIMessages.CVSChangeSetCollector_4, 100 * projectMapping.size()); 
			monitor.setTaskName(CVSUIMessages.CVSChangeSetCollector_4); 
			for (Iterator iter = projectMapping.values().iterator(); iter.hasNext();) {
				SyncInfoSet set = (SyncInfoSet) iter.next();
				Policy.checkCanceled(monitor);
				fetchLogEntries(logEntriesCache, set, Policy.subMonitorFor(monitor, 90));
				fireFetchedNotification(logEntriesCache, set, Policy.subMonitorFor(monitor, 10));
			}
		} finally {
			// Clear the fetches even if we were cancelled.
			// Restarting will need to re-request all infos
			fetches.clear();
			monitor.done();
		}
		return true;
	}

	private void fireFetchedNotification(LogEntryCache logEntriesCache, SyncInfoSet set, IProgressMonitor monitor) {
		if (listener != null) {
			listener.logEntriesFetched(set, logEntriesCache, monitor);
		}
	}

	/*
	 * Return a map of IProject to SyncInfoSet as that is how entries are fetched.
	 * The set for each project includes all infos from the original set.
	 * This is one so that the completion notification contains all infos
	 * including those were a fetch was not required either because the
	 * entry was already cached or the resource has no history.
	 */
	private Map getFetchesByProject() {
		Map<IProject, SyncInfoSet> result = new HashMap<>();
		for (Iterator iter = fetches.iterator(); iter.hasNext();) {
			FetchRequest request = (FetchRequest) iter.next();
			SyncInfo[] infos = request.getInfos();
			for (int i = 0; i < infos.length; i++) {
				SyncInfo info = infos[i];
				IProject project = info.getLocal().getProject();
				SyncInfoSet infoSet = result.get(project);
				if (infoSet == null) {
					infoSet = new SyncInfoSet();
					result.put(project, infoSet);
				}
				infoSet.add(info);
			}
		}
		return result;
	}

	private boolean isFetchRequired(SyncInfo info) {
		// We only need to fetch if we don't have the log entry already
		// and the change is a remote change
		return info.getLocal().getType() == IResource.FILE && !isLogEntryCached(info) && isRemoteChange(info);
		
	}
	
	/*
	 * Return whether the given SyncInfo is cached. If there is
	 * an info for the resource that does not match the given info,
	 * it is removed and false is returned.
	 */
	private boolean isLogEntryCached(SyncInfo info) {
		SyncInfo collectedInfo = collectedInfos.getSyncInfo(info.getLocal());
		if (collectedInfo != null && !collectedInfo.equals(info)) {
			remove(collectedInfo);
			collectedInfo = null;
		}
		return collectedInfo != null;
	}

	/*
	 * Return if this sync info should be considered as part of a remote change
	 * meaning that it can be placed inside an incoming commit set (i.e. the
	 * set is determined using the comments from the log entry of the file). 
	 */
	public boolean isRemoteChange(SyncInfo info) {
		int kind = info.getKind();
		if(info.getLocal().getType() != IResource.FILE) return false;
		if(info.getComparator().isThreeWay()) {
			return (kind & SyncInfo.DIRECTION_MASK) != SyncInfo.OUTGOING;
		}
		// For two-way, the change is only remote if it has a remote or has a base locally
		if (info.getRemote() != null) return true;
		ICVSFile file = CVSWorkspaceRoot.getCVSFileFor((IFile)info.getLocal());
		try {
			return file.getSyncBytes() != null;
		} catch (CVSException e) {
			// Log the error and exclude the file from consideration
			CVSUIPlugin.log(e);
			return false;
		}
	}
	
	/*
	 * Fetch the log entries for the info in the given set
	 */
	private void fetchLogEntries(LogEntryCache logEntriesCache, SyncInfoSet set, IProgressMonitor monitor) {
		try {
			if (subscriber instanceof CVSCompareSubscriber) {
				CVSCompareSubscriber compareSubscriber = (CVSCompareSubscriber)subscriber;
				fetchLogEntries(logEntriesCache, compareSubscriber, set, monitor);
			} else {
				// Run the log command once with no tags
				fetchLogs(logEntriesCache, set, null, null, monitor);
			}
		} catch (CVSException e) {
			handleException(e);
		} catch (InterruptedException e) {
			throw new OperationCanceledException();
		}
		
	}
	
	private void fetchLogEntries(LogEntryCache logEntriesCache, CVSCompareSubscriber compareSubscriber, SyncInfoSet set, IProgressMonitor monitor) throws CVSException, InterruptedException {
		Map localTagMap = getLocalTagMap(set);
		monitor.beginTask(null, 100 * localTagMap.size());
		for (Iterator iter = localTagMap.keySet().iterator(); iter.hasNext();) {
			CVSTag localTag = (CVSTag) iter.next();        
			fetchLogEntries(logEntriesCache, compareSubscriber, set, localTag, Policy.subMonitorFor(monitor, 100));
		}
		Policy.checkCanceled(monitor);
		monitor.done();
	}

	/*
	 * Return the resources grouped by the tag found in the
	 * workspace. The map is CVSTag->SyncInfoSet
	 */
	private Map getLocalTagMap(SyncInfoSet set) {
		Map<CVSTag, SyncInfoSet> result = new HashMap<>();
		for (Iterator iter = set.iterator(); iter.hasNext();) {
			SyncInfo info = (SyncInfo) iter.next();
			CVSTag tag = getLocalTag(info);
			SyncInfoSet tagSet = result.get(tag);
			if (tagSet == null) {
				tagSet = new SyncInfoSet();
				result.put(tag, tagSet);
			}
			tagSet.add(info);
		}
		return result;
	}

	private CVSTag getLocalTag(SyncInfo syncInfo) {
		try {
			IResource local = syncInfo.getLocal();
			ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(local);
			CVSTag tag = null;
			if(cvsResource.isFolder()) {
				FolderSyncInfo info = ((ICVSFolder)cvsResource).getFolderSyncInfo();
				if(info != null) {
					tag = info.getTag();									
				}
				if (tag != null && tag.getType() == CVSTag.BRANCH) {
					tag = Util.getAccurateFolderTag(local, tag);
				}
			} else {
				tag = CVSAction.getAccurateFileTag(cvsResource);
			}
			if(tag == null) {
				tag = new CVSTag();
			}
			return tag;
		} catch (CVSException e) {
			CVSUIPlugin.log(e);
			return new CVSTag();
		}
	}

	private void fetchLogEntries(LogEntryCache logEntriesCache, CVSCompareSubscriber compareSubscriber, SyncInfoSet set, CVSTag localTag, IProgressMonitor monitor) throws CVSException, InterruptedException {
		if (compareSubscriber.isMultipleTagComparison()) {
			Map rootToInfoMap = getRootToInfoMap(compareSubscriber, set);
			monitor.beginTask(null, 100 * rootToInfoMap.size());
			for (Iterator iterator = rootToInfoMap.keySet().iterator(); iterator.hasNext();) {
				IResource root = (IResource) iterator.next();
				Policy.checkCanceled(monitor);
				fetchLogs(logEntriesCache, set, localTag, compareSubscriber.getTag(root), Policy.subMonitorFor(monitor, 100));
			}
			monitor.done();
		} else {
			Policy.checkCanceled(monitor);
			fetchLogs(logEntriesCache, set, localTag, compareSubscriber.getTag(), monitor);
		}
	}

	private Map getRootToInfoMap(CVSCompareSubscriber compareSubscriber, SyncInfoSet set) {
		Map<IResource, SyncInfoSet> rootToInfosMap = new HashMap<>();
		IResource[] roots = compareSubscriber.roots();
		for (Iterator iter = set.iterator(); iter.hasNext();) {
			SyncInfo info = (SyncInfo) iter.next();
			IPath localPath = info.getLocal().getFullPath();
			for (int j = 0; j < roots.length; j++) {
				IResource resource = roots[j];
				if (resource.getFullPath().isPrefixOf(localPath)) {
					SyncInfoSet infoList = rootToInfosMap.get(resource);
					if (infoList == null) {
						infoList = new SyncInfoSet();
						rootToInfosMap.put(resource, infoList);
					}
					infoList.add(info);
					break; // out of inner loop
				}
			}
			
		}
		return rootToInfosMap;
	}

	private void fetchLogs(LogEntryCache logEntriesCache, SyncInfoSet set, CVSTag localTag, CVSTag remoteTag, IProgressMonitor monitor) throws CVSException, InterruptedException {
		ICVSRemoteResource[] remoteResources = getRemotesToFetch(set.getSyncInfos());
		if (remoteResources.length > 0) {
			RemoteLogOperation logOperation = new RemoteLogOperation(getConfiguration().getSite().getPart(), remoteResources, localTag, remoteTag, logEntriesCache);
			logOperation.execute(monitor);
		}
		collectedInfos.addAll(set);
	}
	
	private ICVSRemoteResource[] getRemotesToFetch(SyncInfo[] infos) {
		List<ICVSRemoteResource> remotes = new ArrayList<>();
		for (int i = 0; i < infos.length; i++) {
			SyncInfo info = infos[i];
			if (isFetchRequired(info)) {
				ICVSRemoteResource remote = getRemoteResource(info);
				if(remote != null) {
					remotes.add(remote);
				}
			}
		}
		return remotes.toArray(new ICVSRemoteResource[remotes.size()]);
	}

	/**
	 * Stop any current fetch in process.
	 */
	public void stopFetching() {
		try {
			getEventHandlerJob().cancel();
			getEventHandlerJob().join();
		} catch (InterruptedException e) {
		}
	}
}
