/*******************************************************************************
 * 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
	}

	/**
	 * 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 of " + this); //$NON-NLS-1$
			}
		}

		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.clear();
		revisions.getContainer().moduleDatabase.persistSettings(settings, this);
	}

	/**
	 * 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;
	}
}
