/*******************************************************************************
 * Copyright (c) 2012, 2016 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.osgi.container;

import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent;
import org.eclipse.osgi.framework.util.ThreadInfoReport;
import org.eclipse.osgi.internal.container.EquinoxReentrantLock;
import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.report.resolution.ResolutionReport;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.AdminPermission;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleReference;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.service.resolver.ResolutionException;

/**
 * A module represents a set of revisions installed in a
 * module {@link ModuleContainer container}.
 * @since 3.10
 */
public abstract class Module implements BundleReference, BundleStartLevel, Comparable<Module> {
	/**
	 * The possible start options for a module
	 */
	public static enum StartOptions {
		/**
		 * The module start operation is transient and the persistent
		 * autostart or activation policy setting of the module is not modified.
		 */
		TRANSIENT,
		/**
		 * The module start operation must activate the module according to the module's declared
		 * activation policy.
		 */
		USE_ACTIVATION_POLICY,
		/**
		 * The module start operation is transient and the persistent activation policy
		 * setting will be used.
		 */
		TRANSIENT_RESUME,
		/**
		 * The module start operation is transient and will only happen if {@link Settings#AUTO_START auto start}
		 * setting is persistent.
		 */
		TRANSIENT_IF_AUTO_START,
		/**
		 * The module start operation that indicates the module is being started because of a
		 * lazy start trigger class load.
		 */
		LAZY_TRIGGER;

		/**
		 * Tests if this option is contained in the specified options
		 */
		public boolean isContained(StartOptions... options) {
			for (StartOptions option : options) {
				if (equals(option)) {
					return true;
				}
			}
			return false;
		}
	}

	/**
	 * The possible start options for a module
	 */
	public static enum StopOptions {
		/**
		 * The module stop operation is transient and the persistent
		 * autostart setting of the module is not modified.
		 */
		TRANSIENT;

		/**
		 * Tests if this option is contained in the specified options
		 */
		public boolean isContained(StopOptions... options) {
			for (StopOptions option : options) {
				if (equals(option)) {
					return true;
				}
			}
			return false;
		}
	}

	/**
	 * An enumeration of the possible {@link Module#getState() states} a module may be in.
	 */
	public static enum State {
		/**
		 * The module is installed but not yet resolved.
		 */
		INSTALLED,
		/**
		 * The module is resolved and able to be started.
		 */
		RESOLVED,
		/**
		 * The module is waiting for a {@link StartOptions#LAZY_TRIGGER trigger}
		 * class load to proceed with starting.
		 */
		LAZY_STARTING,
		/**
		 * The module is in the process of starting.
		 */
		STARTING,
		/**
		 * The module is now running.
		 */
		ACTIVE,
		/**
		 * The module is in the process of stopping
		 */
		STOPPING,
		/**
		 * The module is uninstalled and may not be used.
		 */
		UNINSTALLED
	}

	/**
	 * An enumeration of persistent settings for a module
	 */
	public static enum Settings {
		/**
		 * The module has been set to auto start.
		 */
		AUTO_START,
		/**
		 * The module has been set to use its activation policy.
		 */
		USE_ACTIVATION_POLICY,
		/**
		 * The module has been set for parallel activation from start-level
		 * @since 3.15
		 */
		PARALLEL_ACTIVATION
	}

	/**
	 * A set of {@link State states} that indicate a module is active.
	 */
	public static final EnumSet<State> ACTIVE_SET = EnumSet.of(State.STARTING, State.LAZY_STARTING, State.ACTIVE, State.STOPPING);
	/**
	 * A set of {@link State states} that indicate a module is resolved.
	 */
	public static final EnumSet<State> RESOLVED_SET = EnumSet.of(State.RESOLVED, State.STARTING, State.LAZY_STARTING, State.ACTIVE, State.STOPPING);

	private final Long id;
	private final String location;
	private final ModuleRevisions revisions;
	final EquinoxReentrantLock stateChangeLock = new EquinoxReentrantLock();
	private final EnumSet<ModuleEvent> stateTransitionEvents = EnumSet.noneOf(ModuleEvent.class);
	private final EnumSet<Settings> settings;
	final AtomicInteger inStart = new AtomicInteger(0);
	private volatile State state = State.INSTALLED;
	private volatile int startlevel;
	private volatile long lastModified;

	/**
	 * Constructs a new module with the specified id, location and
	 * container.
	 * @param id the new module id
	 * @param location the new module location
	 * @param container the container for the new module
	 * @param settings the persisted settings.  May be {@code null} if there are no settings.
	 * @param startlevel the persisted start level or initial start level.
	 */
	public Module(Long id, String location, ModuleContainer container, EnumSet<Settings> settings, int startlevel) {
		this.id = id;
		this.location = location;
		this.revisions = new ModuleRevisions(this, container);
		this.settings = settings == null ? EnumSet.noneOf(Settings.class) : EnumSet.copyOf(settings);
		this.startlevel = startlevel;
	}

	/**
	 * Returns the module id.
	 * @return the module id.
	 */
	public final Long getId() {
		return id;
	}

	/** Returns the module location
	 * @return the module location
	 */
	public final String getLocation() {
		return location;
	}

	/**
	 * Returns the {@link ModuleRevisions} associated with this module.
	 * @return the {@link ModuleRevisions} associated with this module
	 */
	public final ModuleRevisions getRevisions() {
		return revisions;
	}

	/**
	 * Returns the module container this module is contained in.
	 * @return the module container.
	 */
	public final ModuleContainer getContainer() {
		return revisions.getContainer();
	}

	/**
	 * Returns the current {@link ModuleRevision revision} associated with this module.
	 * If the module is uninstalled then the last current revision is returned.
	 * @return the current {@link ModuleRevision revision} associated with this module.
	 */
	public final ModuleRevision getCurrentRevision() {
		return revisions.getCurrentRevision();
	}

	/**
	 * Returns the current {@link State state} of this module.
	 * @return the current state of this module.
	 */
	public final State getState() {
		return state;
	}

	final void setState(State state) {
		this.state = state;
	}

	@Override
	public final int getStartLevel() {
		checkValid();
		return this.startlevel;
	}

	@Override
	public final void setStartLevel(int startLevel) {
		revisions.getContainer().setStartLevel(this, startLevel);
	}

	@Override
	public final boolean isPersistentlyStarted() {
		checkValid();
		return settings.contains(Settings.AUTO_START);
	}

	@Override
	public final boolean isActivationPolicyUsed() {
		checkValid();
		return settings.contains(Settings.USE_ACTIVATION_POLICY);
	}

	final void storeStartLevel(int newStartLevel) {
		this.startlevel = newStartLevel;
	}

	/**
	 * Returns the time when this module was last modified.  A module is considered
	 * to be modified when it is installed, updated or uninstalled.
	 * <p>
	 * The time value is a the number of milliseconds since January 1, 1970, 00:00:00 UTC.
	 * @return the time when this bundle was last modified.
	 */
	public final long getLastModified() {
		return this.lastModified;
	}

	final void setlastModified(long lastModified) {
		this.lastModified = lastModified;
	}

	private static final EnumSet<ModuleEvent> VALID_RESOLVED_TRANSITION = EnumSet.of(ModuleEvent.STARTED);
	private static final EnumSet<ModuleEvent> VALID_STOPPED_TRANSITION = EnumSet.of(ModuleEvent.UPDATED, ModuleEvent.UNRESOLVED, ModuleEvent.UNINSTALLED);

	/**
	 * Acquires the module lock for state changes by the current thread for the specified
	 * transition event.  Certain transition events locks may be nested within other
	 * transition event locks.  For example, a resolved transition event lock may be
	 * nested within a started transition event lock.  A stopped transition lock
	 * may be nested within an updated, unresolved or uninstalled transition lock.
	 * @param transitionEvent the transition event to acquire the lock for.
	 * @throws BundleException
	 */
	protected final void lockStateChange(ModuleEvent transitionEvent) throws BundleException {
		boolean previousInterruption = Thread.interrupted();
		boolean invalid = false;
		try {
			boolean acquired = stateChangeLock.tryLock(revisions.getContainer().getModuleLockTimeout(), TimeUnit.SECONDS);
			Set<ModuleEvent> currentTransition = Collections.emptySet();
			if (acquired) {
				boolean isValidTransition = true;
				switch (transitionEvent) {
					case STARTED :
					case UPDATED :
					case UNINSTALLED :
					case UNRESOLVED :
						// These states must be initiating transition states
						// no other transition state is allowed when these are kicked off
						isValidTransition = stateTransitionEvents.isEmpty();
						break;
					case RESOLVED :
						isValidTransition = VALID_RESOLVED_TRANSITION.containsAll(stateTransitionEvents);
						break;
					case STOPPED :
						isValidTransition = VALID_STOPPED_TRANSITION.containsAll(stateTransitionEvents);
						break;
					default :
						isValidTransition = false;
						break;
				}
				if (!isValidTransition) {
					currentTransition = EnumSet.copyOf(stateTransitionEvents);
					invalid = true;
					stateChangeLock.unlock();
				} else {
					stateTransitionEvents.add(transitionEvent);
					return;
				}
			} else {
				currentTransition = EnumSet.copyOf(stateTransitionEvents);
			}
			Throwable cause;
			if (invalid) {
				cause = new IllegalStateException(NLS.bind(Msg.Module_LockStateError, transitionEvent, currentTransition));
			} else {
				cause = new TimeoutException(NLS.bind(Msg.Module_LockTimeout, revisions.getContainer().getModuleLockTimeout())).initCause(new ThreadInfoReport(stateChangeLock.toString()));
			}
			String exceptonInfo = toString() + ' ' + transitionEvent + ' ' + currentTransition;
			throw new BundleException(Msg.Module_LockError + exceptonInfo, BundleException.STATECHANGE_ERROR, cause);
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			throw new BundleException(Msg.Module_LockError + toString() + " " + transitionEvent, BundleException.STATECHANGE_ERROR, e); //$NON-NLS-1$
		} finally {
			if (previousInterruption) {
				Thread.currentThread().interrupt();
			}
		}
	}

	/**
	 * Releases the lock for state changes for the specified transition event.
	 * @param transitionEvent
	 */
	protected final void unlockStateChange(ModuleEvent transitionEvent) {
		if (stateChangeLock.getHoldCount() == 0 || !stateTransitionEvents.contains(transitionEvent))
			throw new IllegalMonitorStateException("Current thread does not hold the state change lock for: " + transitionEvent); //$NON-NLS-1$
		stateTransitionEvents.remove(transitionEvent);
		stateChangeLock.unlock();
	}

	/**
	 * Returns true if the current thread holds the state change lock for the specified transition event.
	 * @param transitionEvent
	 * @return true if the current thread holds the state change lock for the specified transition event.
	 */
	public final boolean holdsTransitionEventLock(ModuleEvent transitionEvent) {
		return stateChangeLock.getHoldCount() > 0 && stateTransitionEvents.contains(transitionEvent);
	}

	/**
	 * Returns the thread that currently owns the state change lock for this module, or
	 * <code>null</code> if not owned.
	 * @return the owner, or <code>null</code> if not owned.
	 */
	public final Thread getStateChangeOwner() {
		return stateChangeLock.getOwner();
	}

	/**
	 * Starts this module
	 * @param options the options for starting
	 * @throws BundleException if an errors occurs while starting
	 */
	public void start(StartOptions... options) throws BundleException {
		ModuleContainer container = getContainer();
		long startTime = 0;
		if (container.DEBUG_BUNDLE_START_TIME) {
			startTime = System.nanoTime();
		}
		container.checkAdminPermission(getBundle(), AdminPermission.EXECUTE);
		if (options == null) {
			options = new StartOptions[0];
		}
		ModuleEvent event;
		if (StartOptions.LAZY_TRIGGER.isContained(options)) {
			setTrigger();
			if (stateChangeLock.getHoldCount() > 0 && stateTransitionEvents.contains(ModuleEvent.STARTED)) {
				// nothing to do here; the current thread is activating the bundle.
				return;
			}
		}
		BundleException startError = null;
		boolean lockedStarted = false;
		// Indicate we are in the middle of a start.
		// This must be incremented before we acquire the STARTED lock the first time.
		inStart.incrementAndGet();
		try {
			lockStateChange(ModuleEvent.STARTED);
			lockedStarted = true;
			checkValid();
			if (StartOptions.TRANSIENT_IF_AUTO_START.isContained(options) && !settings.contains(Settings.AUTO_START)) {
				// Do nothing; this is a request to start only if the module is set for auto start
				return;
			}
			checkFragment();
			persistStartOptions(options);
			if (getStartLevel() > container.getStartLevel()) {
				if (StartOptions.TRANSIENT.isContained(options)) {
					// it is an error to attempt to transient start a bundle without its start level met
					throw new BundleException(Msg.Module_Transient_StartError, BundleException.START_TRANSIENT_ERROR);
				}
				// Do nothing; start level is not met
				return;
			}
			if (State.ACTIVE.equals(getState()))
				return;
			if (getState().equals(State.INSTALLED)) {
				ResolutionReport report;
				// must unlock to avoid out of order locks when multiple unresolved
				// bundles are started at the same time from different threads
				unlockStateChange(ModuleEvent.STARTED);
				lockedStarted = false;
				try {
					report = container.resolve(Collections.singletonList(this), true);
				} finally {
					lockStateChange(ModuleEvent.STARTED);
					lockedStarted = true;
				}
				// need to check valid again in case someone uninstalled the bundle
				checkValid();
				ResolutionException e = report.getResolutionException();
				if (e != null) {
					if (e.getCause() instanceof BundleException) {
						throw (BundleException) e.getCause();
					}
				}
				if (State.ACTIVE.equals(getState()))
					return;
				if (getState().equals(State.INSTALLED)) {
					String reportMessage = report.getResolutionReportMessage(getCurrentRevision());
					throw new BundleException(Msg.Module_ResolveError + reportMessage, BundleException.RESOLVE_ERROR);
				}
			}

			try {
				event = doStart(options);
			} catch (BundleException e) {
				// must return state to resolved
				setState(State.RESOLVED);
				startError = e;
				// must always publish the STOPPED event on error
				event = ModuleEvent.STOPPED;
			}
		} finally {
			if (lockedStarted) {
				unlockStateChange(ModuleEvent.STARTED);
			}
			inStart.decrementAndGet();
		}

		if (event != null) {
			if (!EnumSet.of(ModuleEvent.STARTED, ModuleEvent.LAZY_ACTIVATION, ModuleEvent.STOPPED).contains(event))
				throw new IllegalStateException("Wrong event type: " + event); //$NON-NLS-1$
			publishEvent(event);
			// only print bundleTime information if we actually fired an event for this bundle
			if (container.DEBUG_BUNDLE_START_TIME) {
				Debug.println(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms for total start time event " + event + " - " + this); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}

		if (startError != null) {
			throw startError;
		}
	}

	final void publishEvent(ModuleEvent type) {
		revisions.getContainer().getAdaptor().publishModuleEvent(type, this, this);
	}

	/**
	 * Stops this module.
	 * @param options options for stopping
	 * @throws BundleException if an error occurs while stopping
	 */
	public void stop(StopOptions... options) throws BundleException {
		revisions.getContainer().checkAdminPermission(getBundle(), AdminPermission.EXECUTE);
		if (options == null)
			options = new StopOptions[0];
		ModuleEvent event;
		BundleException stopError = null;
		lockStateChange(ModuleEvent.STOPPED);
		try {
			checkValid();
			checkFragment();
			persistStopOptions(options);
			if (!Module.ACTIVE_SET.contains(getState()))
				return;
			try {
				event = doStop();
			} catch (BundleException e) {
				stopError = e;
				// must always publish the STOPPED event
				event = ModuleEvent.STOPPED;
			}
		} finally {
			unlockStateChange(ModuleEvent.STOPPED);
		}

		if (event != null) {
			if (!ModuleEvent.STOPPED.equals(event))
				throw new IllegalStateException("Wrong event type: " + event); //$NON-NLS-1$
			publishEvent(event);
		}
		if (stopError != null)
			throw stopError;
	}

	private void checkFragment() throws BundleException {
		ModuleRevision current = getCurrentRevision();
		if ((current.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
			throw new BundleException(Msg.Module_Fragment_InvalidOperation, BundleException.INVALID_OPERATION);
		}
	}

	@Override
	public final int compareTo(Module o) {
		int slcomp = this.startlevel - o.startlevel;
		if (slcomp != 0) {
			return slcomp;
		}
		long idcomp = getId() - o.getId();
		return (idcomp < 0L) ? -1 : ((idcomp > 0L) ? 1 : 0);
	}

	final void checkValid() {
		if (getState().equals(State.UNINSTALLED))
			throw new IllegalStateException(Msg.Module_UninstalledError);
	}

	private ModuleEvent doStart(StartOptions... options) throws BundleException {
		boolean isLazyTrigger = StartOptions.LAZY_TRIGGER.isContained(options);
		if (isLazyTrigger) {
			if (!State.LAZY_STARTING.equals(getState())) {
				// need to make sure we transition through the lazy starting state
				setState(State.LAZY_STARTING);
				// need to publish the lazy event
				unlockStateChange(ModuleEvent.STARTED);
				try {
					publishEvent(ModuleEvent.LAZY_ACTIVATION);
				} finally {
					lockStateChange(ModuleEvent.STARTED);
				}
				if (State.ACTIVE.equals(getState())) {
					// A sync listener must have caused the bundle to activate
					return null;
				}
				// continue on to normal starting
			}
			if (getContainer().DEBUG_MONITOR_LAZY) {
				Debug.printStackTrace(new Exception("Module is being lazy activated: " + this)); //$NON-NLS-1$
			}
		} else {
			if (isLazyActivate(options) && !isTriggerSet()) {
				if (State.LAZY_STARTING.equals(getState())) {
					// a sync listener must have tried to start this module again with the lazy option
					return null; // no event to publish; nothing to do
				}
				// set the lazy starting state and return lazy activation event for firing
				setState(State.LAZY_STARTING);
				return ModuleEvent.LAZY_ACTIVATION;
			}
		}

		// time to actual start the module
		if (!State.STARTING.equals(getState())) {
			// TODO this starting state check should not be needed
			// but we do it because of the way the system module init works
			setState(State.STARTING);
			publishEvent(ModuleEvent.STARTING);
		}
		try {
			startWorker();
			setState(State.ACTIVE);
			return ModuleEvent.STARTED;
		} catch (Throwable t) {
			// must fire stopping event
			setState(State.STOPPING);
			publishEvent(ModuleEvent.STOPPING);
			if (t instanceof BundleException)
				throw (BundleException) t;
			throw new BundleException(Msg.Module_StartError, BundleException.ACTIVATOR_ERROR, t);
		}
	}

	private void setTrigger() {
		ModuleLoader loader = getCurrentLoader();
		if (loader != null) {
			loader.getAndSetTrigger();
		}
	}

	private boolean isTriggerSet() {
		ModuleLoader loader = getCurrentLoader();
		return loader == null ? false : loader.isTriggerSet();
	}

	private ModuleLoader getCurrentLoader() {
		ModuleRevision current = getCurrentRevision();
		if (current == null) {
			return null;
		}
		ModuleWiring wiring = current.getWiring();
		if (wiring == null) {
			return null;
		}
		try {
			return wiring.getModuleLoader();
		} catch (UnsupportedOperationException e) {
			// just ignore and return null;
			return null;
		}
	}

	/**
	 * Performs any work associated with starting a module.  For example,
	 * loading and calling start on an activator.
	 * @throws BundleException if there was an exception starting the module
	 */
	protected void startWorker() throws BundleException {
		// Do nothing
	}

	private ModuleEvent doStop() throws BundleException {
		setState(State.STOPPING);
		publishEvent(ModuleEvent.STOPPING);
		try {
			stopWorker();
			return ModuleEvent.STOPPED;
		} catch (Throwable t) {
			if (t instanceof BundleException)
				throw (BundleException) t;
			throw new BundleException(Msg.Module_StopError, BundleException.ACTIVATOR_ERROR, t);
		} finally {
			// must always set the state to stopped
			setState(State.RESOLVED);
		}
	}

	/**
	 * Performs any work associated with stopping a module.  For example,
	 * calling stop on an activator.
	 * @throws BundleException if there was an exception stopping the module
	 */
	protected void stopWorker() throws BundleException {
		// Do nothing
	}

	@Override
	public String toString() {
		return getCurrentRevision() + " [id=" + id + "]"; //$NON-NLS-1$ //$NON-NLS-2$
	}

	private void persistStartOptions(StartOptions... options) {
		if (StartOptions.TRANSIENT.isContained(options) || StartOptions.TRANSIENT_RESUME.isContained(options) || StartOptions.LAZY_TRIGGER.isContained(options)) {
			return;
		}

		if (StartOptions.USE_ACTIVATION_POLICY.isContained(options)) {
			settings.add(Settings.USE_ACTIVATION_POLICY);
		} else {
			settings.remove(Settings.USE_ACTIVATION_POLICY);
		}
		settings.add(Settings.AUTO_START);
		revisions.getContainer().moduleDatabase.persistSettings(settings, this);
	}

	private void persistStopOptions(StopOptions... options) {
		if (StopOptions.TRANSIENT.isContained(options))
			return;
		settings.remove(Settings.USE_ACTIVATION_POLICY);
		settings.remove(Settings.AUTO_START);
		revisions.getContainer().moduleDatabase.persistSettings(settings, this);
	}

	/**
	 * Set if this module should be activated in parallel with other modules that have
	 * the same {@link #getStartLevel() start level}.
	 * @param parallelActivation true if the module should be started in parallel; false otherwise
	 * @since 3.15
	 */
	public void setParallelActivation(boolean parallelActivation) {
		if (parallelActivation) {
			settings.add(Settings.PARALLEL_ACTIVATION);
		} else {
			settings.remove(Settings.PARALLEL_ACTIVATION);
		}
		revisions.getContainer().moduleDatabase.persistSettings(settings, this);
	}

	/**
	 * Returns if this module should be activated in parallel with other modules that have
	 * the same {@link #getStartLevel() start level}.
	 * @return true if the module should be started in parallel; false otherwise
	 * @since 3.15
	 */
	public boolean isParallelActivated() {
		return settings.contains(Settings.PARALLEL_ACTIVATION);
	}

	/**
	 * The container is done with the revision and it has been completely removed.
	 * This method allows the resources behind the revision to be cleaned up.
	 * @param revision the revision to clean up
	 */
	abstract protected void cleanup(ModuleRevision revision);

	final boolean isLazyActivate(StartOptions... options) {
		if (StartOptions.TRANSIENT.isContained(options)) {
			if (!StartOptions.USE_ACTIVATION_POLICY.isContained(options)) {
				return false;
			}
		} else if (!settings.contains(Settings.USE_ACTIVATION_POLICY)) {
			return false;
		}
		return hasLazyActivatePolicy();
	}

	final boolean hasLazyActivatePolicy() {
		ModuleRevision current = getCurrentRevision();
		return current == null ? false : current.hasLazyActivatePolicy();
	}

	/**
	 * Used internally by the container to determine if any thread is in the middle
	 * of a start operation on this module.
	 * @return
	 */
	final boolean inStart() {
		return inStart.get() > 0;
	}
}
