/*******************************************************************************
 *  Copyright (c) 2003, 2012 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 - Initial API and implementation
 *******************************************************************************/
package org.eclipse.core.internal.jobs;

import java.util.*;
import org.eclipse.core.internal.runtime.RuntimeLog;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;

/**
 * Implicit jobs are jobs that are running by virtue of a JobManager.begin/end
 * pair. They act like normal jobs, except they are tied to an arbitrary thread
 * of the client's choosing, and they can be nested.
 * @ThreadSafe
 */
class ImplicitJobs {

	/**
	 * Cached unused instance that can be reused
	 * @GuardedBy("this")
	 */
	private ThreadJob jobCache = null;
	protected JobManager manager;

	/**
	 * Set of suspended scheduling rules.
	 * @GuardedBy("this")
	 */
	private final Set<ISchedulingRule> suspendedRules = new HashSet<>(20);

	/**
	 * Maps (Thread-&gt;ThreadJob), threads to the currently running job for that
	 * thread.
	 * @GuardedBy("this")
	 */
	private final Map<Thread, ThreadJob> threadJobs = new HashMap<>(20);

	ImplicitJobs(JobManager manager) {
		this.manager = manager;
	}

	/* (Non-javadoc)
	 * @see IJobManager#beginRule
	 */
	void begin(ISchedulingRule rule, IProgressMonitor monitor, boolean suspend) {
		if (JobManager.DEBUG_BEGIN_END)
			JobManager.debug("Begin rule: " + rule); //$NON-NLS-1$
		final Thread currentThread = Thread.currentThread();
		ThreadJob threadJob;
		synchronized (this) {
			threadJob = threadJobs.get(currentThread);
			if (threadJob != null) {
				//nested rule, just push on stack and return
				threadJob.push(rule);
				return;
			}
			//no need to schedule a thread job for a null rule
			if (rule == null)
				return;
			//create a thread job for this thread, use the rule from the real job if it has one
			Job realJob = manager.currentJob();
			if (realJob != null && realJob.getRule() != null)
				threadJob = newThreadJob(realJob.getRule());
			else {
				threadJob = newThreadJob(rule);
				threadJob.acquireRule = true;
			}
			//don't acquire rule if it is a suspended rule
			if (isSuspended(rule))
				threadJob.acquireRule = false;
			//indicate if it is a system job to ensure isBlocking works correctly
			threadJob.setRealJob(realJob);
			threadJob.setThread(currentThread);
		}
		try {
			threadJob.push(rule);
			//join the thread job outside sync block
			if (threadJob.acquireRule) {
				//no need to re-acquire any locks because the thread did not wait to get this lock
				if (manager.runNow(threadJob, false) == null)
					manager.getLockManager().addLockThread(Thread.currentThread(), rule);
				else
					threadJob = ThreadJob.joinRun(threadJob, monitor);
			}
		} finally {
			//remember this thread job  - only do this
			//after the rule is acquired because it is ok for this thread to acquire
			//and release other rules while waiting.
			synchronized (this) {
				threadJobs.put(currentThread, threadJob);
				if (suspend)
					suspendedRules.add(rule);
			}
		}
	}

	/* (Non-javadoc)
	 * @see IJobManager#endRule
	 */
	synchronized void end(ISchedulingRule rule, boolean resume) {
		if (JobManager.DEBUG_BEGIN_END)
			JobManager.debug("End rule: " + rule); //$NON-NLS-1$
		ThreadJob threadJob = threadJobs.get(Thread.currentThread());
		if (threadJob == null)
			Assert.isLegal(rule == null, "endRule without matching beginRule: " + rule); //$NON-NLS-1$
		else if (threadJob.pop(rule)) {
			endThreadJob(threadJob, resume);
		}
	}

	/**
	 * Called when a worker thread has finished running a job. At this
	 * point, the worker thread must not own any scheduling rules
	 * @param lastJob The last job to run in this thread
	 */
	void endJob(InternalJob lastJob) {
		final Thread currentThread = Thread.currentThread();
		IStatus error;
		synchronized (this) {
			ThreadJob threadJob = threadJobs.get(currentThread);
			if (threadJob == null) {
				if (lastJob.getRule() != null)
					notifyWaitingThreadJobs(lastJob);
				return;
			}
			String msg = "Worker thread ended job: " + lastJob + ", but still holds rule: " + threadJob; //$NON-NLS-1$ //$NON-NLS-2$
			error = new Status(IStatus.ERROR, JobManager.PI_JOBS, 1, msg, null);
			//end the thread job
			endThreadJob(threadJob, false);
		}
		try {
			RuntimeLog.log(error);
		} catch (RuntimeException e) {
			//failed to log, so print to console instead
			System.err.println(error.getMessage());
		}
	}

	/**
	 * @GuardedBy("this")
	 */
	private void endThreadJob(ThreadJob threadJob, boolean resume) {
		Thread currentThread = Thread.currentThread();
		//clean up when last rule scope exits
		threadJobs.remove(currentThread);
		ISchedulingRule rule = threadJob.getRule();
		if (resume && rule != null)
			suspendedRules.remove(rule);
		//if this job had a rule, then we are essentially releasing a lock
		//note it is safe to do this even if the acquire was aborted
		if (threadJob.acquireRule) {
			manager.getLockManager().removeLockThread(currentThread, rule);
			notifyWaitingThreadJobs(threadJob);
		}
		//if the job was started, we need to notify job manager to end it
		if (threadJob.isRunning())
			manager.endJob(threadJob, Status.OK_STATUS, false);
		recycle(threadJob);
	}

	/**
	 * Returns true if this rule has been suspended, and false otherwise.
	 * @GuardedBy("this")
	 */
	private boolean isSuspended(ISchedulingRule rule) {
		if (suspendedRules.isEmpty())
			return false;
		for (ISchedulingRule iSchedulingRule : suspendedRules)
			if (iSchedulingRule.contains(rule))
				return true;
		return false;
	}

	/**
	 * Returns a new or reused ThreadJob instance.
	 * @GuardedBy("this")
	 */
	private ThreadJob newThreadJob(ISchedulingRule rule) {
		if (jobCache != null) {
			ThreadJob job = jobCache;
			// calling setRule will try to acquire JobManager.lock, breaking
			// lock acquisition protocol. Since we managing this special job
			// ourselves we can call internalSetRule
			((InternalJob) job).internalSetRule(rule);
			job.acquireRule = job.isRunning = false;
			job.realJob = null;
			jobCache = null;
			return job;
		}
		return new ThreadJob(rule);
	}

	/**
	 * A job has just finished that was holding a scheduling rule, and the
	 * scheduling rule is now free.  Wake any blocked thread jobs so they can
	 * compete for the newly freed lock
	 */
	void notifyWaitingThreadJobs(InternalJob job) {
		synchronized (job.jobStateLock) {
			job.jobStateLock.notifyAll();
		}
	}

	/**
	 * Indicates that a thread job is no longer in use and can be reused.
	 * @GuardedBy("this")
	 */
	private void recycle(ThreadJob job) {
		if (jobCache == null && job.recycle())
			jobCache = job;
	}

	/**
	 * Implements IJobManager#resume(ISchedulingRule)
	 * @param rule
	 */
	void resume(ISchedulingRule rule) {
		//resume happens as a consequence of freeing the last rule in the stack
		end(rule, true);
		if (JobManager.DEBUG_BEGIN_END)
			JobManager.debug("Resume rule: " + rule); //$NON-NLS-1$
	}

	/**
	 * Implements IJobManager#suspend(ISchedulingRule, IProgressMonitor)
	 * @param rule
	 * @param monitor
	 */
	void suspend(ISchedulingRule rule, IProgressMonitor monitor) {
		if (JobManager.DEBUG_BEGIN_END)
			JobManager.debug("Suspend rule: " + rule); //$NON-NLS-1$
		//the suspend job will be remembered once the rule is acquired
		begin(rule, monitor, true);
	}

	/**
	 * Implements IJobManager#transferRule(ISchedulingRule, Thread)
	 */
	synchronized void transfer(ISchedulingRule rule, Thread destinationThread) {
		//nothing to do for null
		if (rule == null)
			return;
		final Thread currentThread = Thread.currentThread();
		//nothing to do if transferring to the same thread
		if (currentThread == destinationThread)
			return;
		//ensure destination thread doesn't already have a rule
		ThreadJob target = threadJobs.get(destinationThread);
		Assert.isLegal(target == null, "Transfer rule to job that already owns a rule"); //$NON-NLS-1$
		//ensure calling thread owns the job being transferred
		ThreadJob source = threadJobs.get(currentThread);
		Assert.isNotNull(source, "transferRule without beginRule"); //$NON-NLS-1$
		Assert.isLegal(source.getRule() == rule, "transferred rule " + rule + " does not match beginRule: " + source.getRule()); //$NON-NLS-1$ //$NON-NLS-2$		// transfer the thread job without ending it
		source.setThread(destinationThread);
		threadJobs.remove(currentThread);
		threadJobs.put(destinationThread, source);
		// transfer lock
		if (source.acquireRule) {
			manager.getLockManager().removeLockThread(currentThread, rule);
			manager.getLockManager().addLockThread(destinationThread, rule);
		}
		// Wake up any blocked jobs (waiting within yield or joinRun) waiting on
		// this rule
		notifyWaitingThreadJobs(source);
	}

	synchronized void removeWaiting(ThreadJob threadJob) {
		synchronized (((InternalJob) threadJob).jobStateLock) {
			threadJob.isWaiting = false;
			notifyWaitingThreadJobs(threadJob);
			((InternalJob) threadJob).setWaitQueueStamp(InternalJob.T_NONE);
		}
		manager.dequeue(manager.waitingThreadJobs, threadJob);
	}

	synchronized void addWaiting(ThreadJob threadJob) {
		synchronized (((InternalJob) threadJob).jobStateLock) {
			threadJob.isWaiting = true;
			notifyWaitingThreadJobs(threadJob);
			((InternalJob) threadJob).setWaitQueueStamp(manager.waitQueueCounter.increment());
		}
		manager.enqueue(manager.waitingThreadJobs, threadJob);
	}

	synchronized ThreadJob getThreadJob(Thread thread) {
		return threadJobs.get(thread);
	}

}
