/*******************************************************************************
 * Copyright (c) 2000, 2017 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
 *     Eugene Kuleshov (eu@md.pp.ru) - Bug 138152 Improve sync job status reporting
 *******************************************************************************/
package org.eclipse.team.internal.ui.synchronize;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.subscribers.Subscriber;
import org.eclipse.team.internal.ui.*;
import org.eclipse.team.ui.synchronize.*;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.progress.IProgressConstants;
import org.eclipse.ui.progress.UIJob;

/**
 * Job to refresh a {@link Subscriber} in the background. The job can be configured
 * to be re-scheduled and run at a specified interval.
 * <p>
 * The job supports a basic work flow for modal/non-modal usage. If the job is
 * run in the foreground (e.g. in a modal progress dialog) the refresh listeners
 * action is invoked immediately after the refresh is completed. Otherwise the refresh
 * listeners action is associated to the job as a <i>goto</i> action. This will
 * allow the user to select the action in the progress view and run it when they
 * choose.
 * </p>
 * @since 3.0
 */
public abstract class RefreshParticipantJob extends Job {

	/**
	 * Uniquely identifies this type of job. This is used for cancellation.
	 */
	private final static Object FAMILY_ID = new Object();

	/**
	 * If true this job will be restarted when it completes
	 */
	private boolean reschedule = false;

	/**
	 * If true a rescheduled refresh job should be restarted when canceled
	 */
	private boolean restartOnCancel = true;

	/**
	 * The schedule delay used when rescheduling a completed job
	 */
	private static long scheduleDelay;

	/**
	 * The participant that is being refreshed.
	 */
	private ISynchronizeParticipant participant;

	/**
	 * The task name for this refresh. This is usually more descriptive than the
	 * job name.
	 */
	private String taskName;

	/**
	 * Refresh started/completed listener for every refresh
	 */
	private static List<IRefreshSubscriberListener> listeners = new ArrayList<>(1);
	private static final int STARTED = 1;
	private static final int DONE = 2;

	/*
	 * Lock used to sequence refresh jobs
	 */
	private static final ILock lock = Job.getJobManager().newLock();

	/*
	 * Constant used for postponement
	 */
	private static final IStatus POSTPONED = new Status(IStatus.CANCEL, TeamUIPlugin.ID, 0, "Scheduled refresh postponed due to conflicting operation", null); //$NON-NLS-1$

	/*
	 * Action wrapper which allows the goto action
	 * to be set later. It also handles errors
	 * that have occurred during the refresh
	 */
	private final class GotoActionWrapper extends WorkbenchAction {
        private ActionFactory.IWorkbenchAction gotoAction;
        private IStatus status;
        @Override
		public void run() {
            if (status != null && !status.isOK()) {
                ErrorDialog.openError(Utils.getShell(null), null, TeamUIMessages.RefreshSubscriberJob_3, status);
            } else if(gotoAction != null) {
        		gotoAction.run();
        	}
        }
        @Override
		public boolean isEnabled() {
        	if(gotoAction != null) {
        		return gotoAction.isEnabled();
        	}
        	return true;
        }
        @Override
		public String getText() {
        	if(gotoAction != null) {
        		return gotoAction.getText();
        	}
        	return null;
        }
        @Override
		public String getToolTipText() {
            if (status != null && !status.isOK()) {
                return status.getMessage();
            }
        	if(gotoAction != null) {
        		return gotoAction.getToolTipText();
        	}
        	return Utils.shortenText(SynchronizeView.MAX_NAME_LENGTH, RefreshParticipantJob.this.getName());
        }
        @Override
		public void dispose() {
        	super.dispose();
        	if(gotoAction != null) {
        		gotoAction.dispose();
        	}
        }
        public void setGotoAction(ActionFactory.IWorkbenchAction gotoAction) {
            this.gotoAction = gotoAction;
			setEnabled(isEnabled());
			setToolTipText(getToolTipText());
			gotoAction.addPropertyChangeListener(event -> {
				if(event.getProperty().equals(IAction.ENABLED)) {
					Boolean bool = (Boolean) event.getNewValue();
					GotoActionWrapper.this.setEnabled(bool.booleanValue());
				}
			});
        }
        public void setStatus(IStatus status) {
            this.status = status;
        }
    }

    /**
	 * Notification for safely notifying listeners of refresh lifecycle.
	 */
	private abstract class Notification implements ISafeRunnable {
		private IRefreshSubscriberListener listener;
		@Override
		public void handleException(Throwable exception) {
			// don't log the exception....it is already being logged in Platform#run
		}
		public void run(IRefreshSubscriberListener listener) {
			this.listener = listener;
			SafeRunner.run(this);
		}
		@Override
		public void run() throws Exception {
			notify(listener);
		}
		/**
		 * Subclasses override this method to send an event safely to a listener
		 * @param listener
		 */
		protected abstract void notify(IRefreshSubscriberListener listener);
	}

	/**
	 * Monitor wrapper that will indicate that the job is canceled
	 * if the job is blocking another.
	 */
	private class NonblockingProgressMonitor extends ProgressMonitorWrapper {
		private final RefreshParticipantJob job;
		private long blockTime;
		private static final int THRESHOLD = 250;
		private boolean wasBlocking = false;
		protected NonblockingProgressMonitor(IProgressMonitor monitor, RefreshParticipantJob job) {
			super(monitor);
			this.job = job;
		}
		@Override
		public boolean isCanceled() {
			if (super.isCanceled()) {
				return true;
			}
			if (job.shouldReschedule() && job.isBlocking()) {
				if (blockTime == 0) {
					blockTime = System.currentTimeMillis();
				} else if (System.currentTimeMillis() - blockTime > THRESHOLD) {
					// We've been blocking for too long
					wasBlocking = true;
					return true;
				}
			} else {
				blockTime = 0;
			}
			wasBlocking = false;
			return false;
		}
		public boolean wasBlocking() {
			return wasBlocking;
		}
	}

	public static interface IChangeDescription {
		int getChangeCount();
	}

	/**
	 * Create a job to refresh the specified resources with the subscriber.
	 *
	 * @param participant the subscriber participant
	 * @param jobName
	 * @param taskName
	 * @param listener
	 */
	public RefreshParticipantJob(ISynchronizeParticipant participant, String jobName, String taskName, IRefreshSubscriberListener listener) {
		super(jobName);
		Assert.isNotNull(participant);
		this.participant = participant;
		this.taskName = taskName;
		setPriority(Job.DECORATE);
		setRefreshInterval(3600 /* 1 hour */);

		// Handle restarting of job if it is configured as a scheduled refresh job.
		addJobChangeListener(new JobChangeAdapter() {
			@Override
			public void done(IJobChangeEvent event) {
				if(shouldReschedule()) {
					IStatus result = event.getResult();
					if(result.getSeverity() == IStatus.CANCEL && ! restartOnCancel) {
						return;
					}
					long delay = scheduleDelay;
					if (result == POSTPONED) {
						// Restart in 5 seconds
						delay = 5000;
					}
					RefreshParticipantJob.this.schedule(delay);
					restartOnCancel = true;
				}
			}
		});
		if(listener != null)
			initialize(listener);
	}

	@Override
	public boolean belongsTo(Object family) {
		if (family instanceof SubscriberParticipant) {
			return family == participant;
		} else {
			return (family == getFamily() || family == ISynchronizeManager.FAMILY_SYNCHRONIZE_OPERATION);
		}
	}

	public static Object getFamily() {
		return FAMILY_ID;
	}

	/**
	 * This is run by the job scheduler. A list of subscribers will be refreshed, errors will not stop the job
	 * and it will continue to refresh the other subscribers.
	 */
	@Override
	public IStatus run(IProgressMonitor monitor) {
		// Perform a pre-check for auto-build or manual build jobs
		// when auto-refreshing
		if (shouldReschedule() &&
				(isJobInFamilyRunning(ResourcesPlugin.FAMILY_AUTO_BUILD)
				|| isJobInFamilyRunning(ResourcesPlugin.FAMILY_MANUAL_BUILD))) {
			return POSTPONED;
		}
		// Only allow one refresh job at a time
		// NOTE: It would be cleaner if this was done by a scheduling
		// rule but at the time of writing, it is not possible due to
		// the scheduling rule containment rules.
		// Acquiring lock to ensure only one refresh job is running at a particular time
		boolean acquired = false;
		try {
			while (!acquired) {
				try {
					acquired = lock.acquire(1000);
				} catch (InterruptedException e1) {
					acquired = false;
				}
				Policy.checkCanceled(monitor);
			}

			IChangeDescription changeDescription = createChangeDescription();
			RefreshEvent event = new RefreshEvent(reschedule ? IRefreshEvent.SCHEDULED_REFRESH : IRefreshEvent.USER_REFRESH, participant, changeDescription);
			IStatus status = null;
			NonblockingProgressMonitor wrappedMonitor = null;
			try {
				event.setStartTime(System.currentTimeMillis());
				if(monitor.isCanceled()) {
					return Status.CANCEL_STATUS;
				}
				// Pre-Notify
				notifyListeners(STARTED, event);
				// Perform the refresh
				monitor.setTaskName(getName());
				wrappedMonitor = new NonblockingProgressMonitor(monitor, this);
				doRefresh(changeDescription, wrappedMonitor);
				// Prepare the results
				setProperty(IProgressConstants.KEEPONE_PROPERTY, Boolean.valueOf(! isJobModal()));
			} catch(OperationCanceledException e2) {
				if (monitor.isCanceled()) {
					// The refresh was canceled by the user
					status = Status.CANCEL_STATUS;
				} else {
					// The refresh was canceled due to a blockage or a canceled authentication
					if (wrappedMonitor != null && wrappedMonitor.wasBlocking()) {
						status = POSTPONED;
					} else {
						status = Status.CANCEL_STATUS;
					}
				}
			} catch(CoreException e) {
			    // Determine the status to be returned and the GOTO action
			    status = e.getStatus();
			    if (!isUser()) {
		            // Use the GOTO action to show the error and return OK
		            Object prop = getProperty(IProgressConstants.ACTION_PROPERTY);
		            if (prop instanceof GotoActionWrapper) {
		                GotoActionWrapper wrapper = (GotoActionWrapper)prop;
		                wrapper.setStatus(e.getStatus());
		                status = new Status(IStatus.OK, TeamUIPlugin.ID, IStatus.OK, e.getStatus().getMessage(), e);
		            }
			    }
		        if (!isUser() && status.getSeverity() == IStatus.ERROR) {
		            // Never prompt for errors on non-user jobs
		            setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE);
		        }
			} finally {
				event.setStopTime(System.currentTimeMillis());
			}

			// Post-Notify
			if (status == null) {
				status = calculateStatus(event);
			}
			event.setStatus(status);
			notifyListeners(DONE, event);
			if (event.getChangeDescription().getChangeCount() > 0) {
				if (participant instanceof AbstractSynchronizeParticipant) {
					AbstractSynchronizeParticipant asp = (AbstractSynchronizeParticipant) participant;
					asp.firePropertyChange(participant, ISynchronizeParticipant.P_CONTENT, null, event.getChangeDescription());
				}
			}
			return event.getStatus();
		} finally {
			if (acquired) lock.release();
            monitor.done();
		}
	}

	protected abstract void doRefresh(IChangeDescription changeListener, IProgressMonitor monitor) throws CoreException;

	/**
	 * Return the total number of changes covered by the resources
	 * of this job.
	 * @return the total number of changes covered by the resources
	 * of this job
	 */
	protected abstract int getChangeCount();

	protected abstract int getIncomingChangeCount();
	protected abstract int getOutgoingChangeCount();

	private boolean isJobInFamilyRunning(Object family) {
		Job[] jobs = Job.getJobManager().find(family);
		if (jobs != null && jobs.length > 0) {
			for (int i = 0; i < jobs.length; i++) {
				Job job = jobs[i];
				if (job.getState() != Job.NONE) {
					return true;
				}
			}
		}
		return false;
	}

	private IStatus calculateStatus(IRefreshEvent event) {
		StringBuilder text = new StringBuilder();
		int code = IStatus.OK;
		int changeCount = event.getChangeDescription().getChangeCount();
		int numChanges = getChangeCount();
		if (numChanges > 0) {
			code = IRefreshEvent.STATUS_CHANGES;

			int incomingChanges = getIncomingChangeCount();
             String numIncomingChanges = incomingChanges==0 ? ""  //$NON-NLS-1$
                 : NLS.bind(TeamUIMessages.RefreshCompleteDialog_incomingChanges, Integer.toString(incomingChanges));

			int outgoingChanges = getOutgoingChangeCount();
			String numOutgoingChanges = outgoingChanges==0 ? ""  //$NON-NLS-1$
                : NLS.bind(TeamUIMessages.RefreshCompleteDialog_outgoingChanges, Integer.toString(outgoingChanges));

			String sep = incomingChanges>0 && outgoingChanges>0 ? "; " : "";  //$NON-NLS-1$ //$NON-NLS-2$

			if (changeCount > 0) {
			// New changes found
				code = IRefreshEvent.STATUS_NEW_CHANGES;
				String numNewChanges = Integer.toString(changeCount);
				if (changeCount == 1) {
				    text.append(NLS.bind(TeamUIMessages.RefreshCompleteDialog_newChangesSingular, (new Object[]{getName(), numNewChanges, numIncomingChanges, sep, numOutgoingChanges})));
				} else {
				    text.append(NLS.bind(TeamUIMessages.RefreshCompleteDialog_newChangesPlural, (new Object[]{getName(), numNewChanges, numIncomingChanges, sep, numOutgoingChanges})));
				}
			} else {
				// Refreshed resources contain changes
				if (numChanges == 1) {
					text.append(NLS.bind(TeamUIMessages.RefreshCompleteDialog_changesSingular, (new Object[]{getName(), Integer.valueOf(numChanges), numIncomingChanges, sep, numOutgoingChanges})));
				} else {
					text.append(NLS.bind(TeamUIMessages.RefreshCompleteDialog_changesPlural, (new Object[]{getName(), Integer.valueOf(numChanges), numIncomingChanges, sep, numOutgoingChanges})));
				}
			}
		} else {
			// No changes found
			code = IRefreshEvent.STATUS_NO_CHANGES;
			text.append(NLS.bind(TeamUIMessages.RefreshCompleteDialog_6, new String[] { getName() }));
		}
		return new Status(IStatus.OK, TeamUIPlugin.ID, code, text.toString(), null);
	}

	private void initialize(final IRefreshSubscriberListener listener) {
		final GotoActionWrapper actionWrapper = new GotoActionWrapper();

		IProgressMonitor group = Job.getJobManager().createProgressGroup();
		group.beginTask(taskName, 100);
		setProgressGroup(group, 80);
		handleProgressGroupSet(group, 20);
		setProperty(IProgressConstants.ICON_PROPERTY, participant.getImageDescriptor());
		setProperty(IProgressConstants.ACTION_PROPERTY, actionWrapper);
		setProperty(IProgressConstants.KEEPONE_PROPERTY, Boolean.valueOf(! isJobModal()));
		// Listener delegate
		IRefreshSubscriberListener autoListener = new IRefreshSubscriberListener() {
			@Override
			public void refreshStarted(IRefreshEvent event) {
				if(listener != null) {
					listener.refreshStarted(event);
				}
			}
			@Override
			public ActionFactory.IWorkbenchAction refreshDone(IRefreshEvent event) {
				if(listener != null) {
					boolean isModal = isJobModal();
					event.setIsLink(!isModal);
					final ActionFactory.IWorkbenchAction runnable = listener.refreshDone(event);
					if(runnable != null) {
						// If the job is being run modally then simply prompt the user immediately
						if(isModal) {
							if(runnable != null) {
								Job update = new UIJob("") { //$NON-NLS-1$
									@Override
									public IStatus runInUIThread(IProgressMonitor monitor) {
									    runnable.run();
										return Status.OK_STATUS;
									}
								};
								update.setSystem(true);
								update.schedule();
							}
						} else {
							// If the job is being run in the background, don't interrupt the user and simply update the goto action
							// to perform the results.
							actionWrapper.setGotoAction(runnable);
						}
					}
					RefreshParticipantJob.removeRefreshListener(this);
				}
				return null;
			}
		};

		if (listener != null) {
			RefreshParticipantJob.addRefreshListener(autoListener);
		}
	}

	/**
	 * The progress group of this job has been set. Any subclasses should
	 * assign this group to any additional jobs they use to collect
	 * changes from the refresh.
	 * @param group a progress group
	 * @param ticks the ticks for the change collection job
	 */
	protected abstract void handleProgressGroupSet(IProgressMonitor group, int ticks);

	protected abstract IChangeDescription createChangeDescription();

	public long getScheduleDelay() {
		return scheduleDelay;
	}

	protected void start() {
		if(getState() == Job.NONE) {
			if(shouldReschedule()) {
				schedule(getScheduleDelay());
			}
		}
	}

	/**
	 * Specify the interval in seconds at which this job is scheduled.
	 * @param seconds delay specified in seconds
	 */
	public void setRefreshInterval(long seconds) {
		boolean restart = false;
		if(getState() == Job.SLEEPING) {
			restart = true;
			cancel();
		}
		scheduleDelay = seconds * 1000;
		if(restart) {
			start();
		}
	}

	public void setRestartOnCancel(boolean restartOnCancel) {
		this.restartOnCancel = restartOnCancel;
	}

	public void setReschedule(boolean reschedule) {
		this.reschedule = reschedule;
	}

	public boolean shouldReschedule() {
		return reschedule;
	}

	public static void addRefreshListener(IRefreshSubscriberListener listener) {
		synchronized(listeners) {
			if(! listeners.contains(listener)) {
				listeners.add(listener);
			}
		}
	}

	public static void removeRefreshListener(IRefreshSubscriberListener listener) {
		synchronized(listeners) {
			listeners.remove(listener);
		}
	}

	protected void notifyListeners(final int state, final IRefreshEvent event) {
		// Get a snapshot of the listeners so the list doesn't change while we're firing
		IRefreshSubscriberListener[] listenerArray;
		synchronized (listeners) {
			listenerArray = listeners.toArray(new IRefreshSubscriberListener[listeners.size()]);
		}
		// Notify each listener in a safe manner (i.e. so their exceptions don't kill us)
		for (int i = 0; i < listenerArray.length; i++) {
			IRefreshSubscriberListener listener = listenerArray[i];
			Notification notification = new Notification() {
				@Override
				protected void notify(IRefreshSubscriberListener listener) {
					switch (state) {
						case STARTED:
							listener.refreshStarted(event);
							break;
						case DONE:
							listener.refreshDone(event);
							break;
						default:
							break;
					}
				}
			};
			notification.run(listener);
		}
	}

	private boolean isJobModal() {
		Boolean isModal = (Boolean)getProperty(IProgressConstants.PROPERTY_IN_DIALOG);
		if(isModal == null) return false;
		return isModal.booleanValue();
	}

	public ISynchronizeParticipant getParticipant() {
		return participant;
	}
}
