/*******************************************************************************
 * Copyright (c) 2003, 2006 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
 *******************************************************************************/
package org.eclipse.wst.common.frameworks.internal.datamodel;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Stack;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.wst.common.frameworks.datamodel.IDataModelOperation;
import org.eclipse.wst.common.frameworks.datamodel.IDataModelProperties;
import org.eclipse.wst.common.frameworks.internal.AdaptabilityUtility;
import org.eclipse.wst.common.frameworks.internal.WTPResourceHandler;
import org.eclipse.wst.common.frameworks.internal.enablement.IEnablementManager;
import org.eclipse.wst.common.frameworks.internal.operations.ComposedExtendedOperationHolder;
import org.eclipse.wst.common.frameworks.internal.operations.OperationStatus;
import org.eclipse.wst.common.frameworks.internal.plugin.WTPCommonPlugin;

public class DataModelPausibleOperationImpl extends WrappedOperation implements IDataModelPausibleOperation {

	// Stack of StackEntries to be executed
	protected Stack operationStackToExecute = null;

	// Stack of StackEntries already executed
	protected Stack undoStack = null;
	protected Stack redoStack = null;

	protected OperationStackEntry rootStackEntry = null;

	protected List operationListeners;

	protected int executionState = NOT_STARTED;

	public DataModelPausibleOperationImpl(IDataModelOperation rootOperation) {
		super(rootOperation);
	}

	public void addOperationListener(IDataModelPausibleOperationListener operationListener) {
		if (null == operationListeners) {
			operationListeners = new ArrayList();
		}
		operationListeners.add(operationListener);
	}

	public void removeOperationListener(IDataModelPausibleOperationListener operationListener) {
		if (null != operationListeners) {
			operationListeners.remove(operationListener);
		}
	}

	public int getExecutionState() {
		return executionState;
	}

	protected static final int EXECUTE_IMPL = 0;
	protected static final int UNDO_IMPL = 1;
	protected static final int REDO_IMPL = 2;
	protected static final int ROLLBACK_IMPL = 3;
	protected static final int RESUME_IMPL = 4;

	private static Hashtable threadToExtendedOpControl = new Hashtable();

	protected IStatus cacheThreadAndContinue(IProgressMonitor monitor, IAdaptable info, int runType) throws ExecutionException {
		final Thread currentThread = Thread.currentThread();
		final boolean isTopLevelOperation = !threadToExtendedOpControl.containsKey(currentThread);
		try {
			if (isTopLevelOperation) {
				threadToExtendedOpControl.put(currentThread, this);
			}
			switch (runType) {
				case EXECUTE_IMPL :
					return executeImpl(monitor, info);
				case UNDO_IMPL :
					return undoImpl(monitor, info);
				case REDO_IMPL :
					return redoImpl(monitor, info);
				case ROLLBACK_IMPL :
					return rollBackImpl(monitor, info);
				case RESUME_IMPL :
					return resumeImpl(monitor, info);
			}
		} finally {
			if (isTopLevelOperation) {
				threadToExtendedOpControl.remove(currentThread);
			}
		}
		throw new RuntimeException();
	}

	public IStatus resume(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		return cacheThreadAndContinue(monitor, info, RESUME_IMPL);
	}

	protected IStatus resumeImpl(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		switch (executionState) {
			case NOT_STARTED :
				return executeImpl(monitor, info);
			case PAUSED_EXECUTE :
			case COMPLETE_ROLLBACK :
				return doExecute(monitor, info);
			case PAUSED_UNDO :
				return doUndo(monitor, info);
			case PAUSED_REDO :
				return redoImpl(monitor, info);
		}
		throw new RuntimeException();
	}

	public boolean canRedo() {
		return (COMPLETE_UNDO == executionState) && super.canRedo();
	}

	public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		return cacheThreadAndContinue(monitor, info, REDO_IMPL);
	}

	protected IStatus redoImpl(IProgressMonitor monitor, IAdaptable info) {
		return doRedo(monitor, info);
	}

	protected IStatus doRedo(IProgressMonitor monitor, IAdaptable info) {
		try {
			executionState = RUNNING_REDO;
			OperationStatus returnStatus = null;
			int shouldContinue = IDataModelPausibleOperationListener.CONTINUE;
			while (IDataModelPausibleOperationListener.CONTINUE == shouldContinue && !redoStack.isEmpty()) {
				OperationStackEntry stackEntry = (OperationStackEntry) redoStack.peek();
				IDataModelOperation operation = stackEntry.getOperation();
				DataModelPausibleOperationEventImpl event = new DataModelPausibleOperationEventImpl(operation, IDataModelPausibleOperationEvent.MAIN_STARTING, IDataModelPausibleOperationEvent.REDO);
				shouldContinue = notifyOperationListeners(event);
				if (IDataModelPausibleOperationListener.PAUSE == shouldContinue) {
					continue;
				}
				undoStack.push(redoStack.pop());
				returnStatus = runOperation(operation, monitor, info, IDataModelPausibleOperationEvent.REDO, returnStatus);
				event = new DataModelPausibleOperationEventImpl(operation, IDataModelPausibleOperationEvent.MAIN_FINISHED, IDataModelPausibleOperationEvent.REDO);
				shouldContinue = notifyOperationListeners(event);

			}
			return returnStatus == null ? Status.OK_STATUS : returnStatus;
		} finally {
			executionState = redoStack.isEmpty() ? COMPLETE_REDO : PAUSED_REDO;
		}
	}

	public boolean canUndo() {
		return (executionState == COMPLETE_EXECUTE || executionState == COMPLETE_REDO) && super.canUndo();
	}

	public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		return cacheThreadAndContinue(monitor, info, UNDO_IMPL);
	}

	protected IStatus undoImpl(IProgressMonitor monitor, IAdaptable info) {
		redoStack = new Stack();
		return doUndo(monitor, info);
	}

	protected IStatus doUndo(IProgressMonitor monitor, IAdaptable info) {
		try {
			executionState = RUNNING_UNDO;
			OperationStatus returnStatus = null;
			int shouldContinue = IDataModelPausibleOperationListener.CONTINUE;
			while (IDataModelPausibleOperationListener.CONTINUE == shouldContinue && !undoStack.isEmpty()) {
				OperationStackEntry stackEntry = (OperationStackEntry) undoStack.peek();
				IDataModelOperation operation = stackEntry.getOperation();
				DataModelPausibleOperationEventImpl event = new DataModelPausibleOperationEventImpl(operation, IDataModelPausibleOperationEvent.MAIN_STARTING, IDataModelPausibleOperationEvent.UNDO);
				shouldContinue = notifyOperationListeners(event);
				if (IDataModelPausibleOperationListener.PAUSE == shouldContinue) {
					continue;
				}
				redoStack.push(undoStack.pop());
				returnStatus = runOperation(operation, monitor, info, IDataModelPausibleOperationEvent.UNDO, returnStatus);
				event = new DataModelPausibleOperationEventImpl(operation, IDataModelPausibleOperationEvent.MAIN_FINISHED, IDataModelPausibleOperationEvent.UNDO);
				shouldContinue = notifyOperationListeners(event);

			}
			return returnStatus == null ? Status.OK_STATUS : returnStatus;
		} finally {
			executionState = undoStack.isEmpty() ? COMPLETE_UNDO : PAUSED_UNDO;
		}
	}

	public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		return cacheThreadAndContinue(monitor, info, EXECUTE_IMPL);
	}

	protected IStatus executeImpl(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		try {
			executionState = RUNNING_EXECUTE;
			undoStack = new Stack();
			operationStackToExecute = new Stack();
			rootStackEntry = new OperationStackEntry(null, rootOperation);
			operationStackToExecute.push(rootStackEntry);
			DataModelPausibleOperationEventImpl event = new DataModelPausibleOperationEventImpl(rootOperation, IDataModelPausibleOperationEvent.NODE_STARTING, IDataModelPausibleOperationEvent.EXECUTE);
			if (IDataModelPausibleOperationListener.CONTINUE == notifyOperationListeners(event)) {
				return doExecute(monitor, info);
			}
			return Status.OK_STATUS;
		} finally {
			executionState = operationStackToExecute.isEmpty() ? COMPLETE_EXECUTE : PAUSED_EXECUTE;
		}
	}

	protected IStatus doExecute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		try {
			OperationStatus returnStatus = null;
			int shouldContinue = IDataModelPausibleOperationListener.CONTINUE;
			while (IDataModelPausibleOperationListener.CONTINUE == shouldContinue && !operationStackToExecute.isEmpty()) {
				OperationStackEntry stackEntry = (OperationStackEntry) operationStackToExecute.peek();
				OperationStackEntry preStackEntry = stackEntry.getNextPreOperation();
				if (null != preStackEntry) {
					operationStackToExecute.push(preStackEntry);
					DataModelPausibleOperationEventImpl event = new DataModelPausibleOperationEventImpl(preStackEntry.getOperation(), IDataModelPausibleOperationEvent.NODE_STARTING, IDataModelPausibleOperationEvent.EXECUTE);
					shouldContinue = notifyOperationListeners(event);
					continue;
				}
				IDataModelOperation stackEntryOperation = stackEntry.getOperationForExecution();
				if (null != stackEntryOperation) {
					DataModelPausibleOperationEventImpl event = new DataModelPausibleOperationEventImpl(stackEntryOperation, IDataModelPausibleOperationEvent.MAIN_STARTING, IDataModelPausibleOperationEvent.EXECUTE);
					shouldContinue = notifyOperationListeners(event);
					if (IDataModelPausibleOperationListener.PAUSE == shouldContinue) {
						continue;
					}
					returnStatus = runOperation(stackEntryOperation, monitor, info, IDataModelPausibleOperationEvent.EXECUTE, returnStatus);
					undoStack.push(stackEntry);
					event = new DataModelPausibleOperationEventImpl(stackEntryOperation, IDataModelPausibleOperationEvent.MAIN_FINISHED, IDataModelPausibleOperationEvent.EXECUTE);
					shouldContinue = notifyOperationListeners(event);
					if (IDataModelPausibleOperationListener.PAUSE == shouldContinue) {
						continue;
					}
				}
				OperationStackEntry postStackEntry = stackEntry.getNextPostOperation();
				if (null != postStackEntry) {
					operationStackToExecute.push(postStackEntry);
					DataModelPausibleOperationEventImpl event = new DataModelPausibleOperationEventImpl(postStackEntry.getOperation(), IDataModelPausibleOperationEvent.NODE_STARTING, IDataModelPausibleOperationEvent.EXECUTE);
					shouldContinue = notifyOperationListeners(event);
					continue;
				}
				operationStackToExecute.pop();
				DataModelPausibleOperationEventImpl event = new DataModelPausibleOperationEventImpl(stackEntry.getOperation(), IDataModelPausibleOperationEvent.NODE_FINISHED, IDataModelPausibleOperationEvent.EXECUTE);
				shouldContinue = notifyOperationListeners(event);
			}
			return returnStatus == null ? Status.OK_STATUS : returnStatus;
		} finally {
			executionState = operationStackToExecute.isEmpty() ? COMPLETE_EXECUTE : PAUSED_EXECUTE;
		}
	}

	public IStatus rollBack(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		return cacheThreadAndContinue(monitor, info, ROLLBACK_IMPL);
	}

	protected IStatus rollBackImpl(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
		if (PAUSED_EXECUTE == executionState || PAUSED_ROLLBACK == executionState) {
			try {
				executionState = RUNNING_ROLLBACK;
				OperationStatus returnStatus = null;
				int shouldContinue = IDataModelPausibleOperationListener.CONTINUE;
				while (IDataModelPausibleOperationListener.CONTINUE == shouldContinue && !undoStack.isEmpty()) {
					OperationStackEntry stackEntry = (OperationStackEntry) undoStack.peek();
					IDataModelOperation operation = stackEntry.getOperation();
					DataModelPausibleOperationEventImpl event = new DataModelPausibleOperationEventImpl(operation, IDataModelPausibleOperationEvent.MAIN_STARTING, IDataModelPausibleOperationEvent.ROLLBACK);
					shouldContinue = notifyOperationListeners(event);
					if (IDataModelPausibleOperationListener.PAUSE == shouldContinue) {
						continue;
					}
					undoStack.pop();
					OperationStackEntry executionTopStackEntry = stackEntry.rollBackOneOperation();
					if (operationStackToExecute.contains(executionTopStackEntry)) {
						while (operationStackToExecute.peek() != executionTopStackEntry) {
							operationStackToExecute.pop();
						}
					} else {
						Stack parentStack = new Stack();
						parentStack.push(executionTopStackEntry);
						OperationStackEntry entry = executionTopStackEntry.parent;
						while (!operationStackToExecute.contains(entry)) {
							parentStack.push(entry);
							entry = entry.parent;
						}
						while (operationStackToExecute.peek() != entry) {
							operationStackToExecute.pop();
						}
						while (!parentStack.isEmpty()) {
							operationStackToExecute.push(parentStack.pop());
						}
					}
					returnStatus = runOperation(operation, monitor, info, IDataModelPausibleOperationEvent.UNDO, returnStatus);
					event = new DataModelPausibleOperationEventImpl(operation, IDataModelPausibleOperationEvent.MAIN_FINISHED, IDataModelPausibleOperationEvent.ROLLBACK);
					shouldContinue = notifyOperationListeners(event);
				}
				return returnStatus == null ? Status.OK_STATUS : returnStatus;
			} finally {
				executionState = undoStack.isEmpty() ? COMPLETE_ROLLBACK : PAUSED_ROLLBACK;
			}
		}
		throw new RuntimeException();
	}

	private int notifyOperationListeners(DataModelPausibleOperationEventImpl event) {
		if (null != operationListeners) {
			IDataModelPausibleOperationListener listener = null;
			for (int i = 0; i < operationListeners.size(); i++) {
				listener = (IDataModelPausibleOperationListener) operationListeners.get(i);
				if (IDataModelPausibleOperationListener.PAUSE == listener.notify(event)) {
					return IDataModelPausibleOperationListener.PAUSE;
				}
			}
		}
		return IDataModelPausibleOperationListener.CONTINUE;
	}

	protected OperationStatus addStatus(OperationStatus returnStatus, IStatus status) {
		if (returnStatus == null) {
			returnStatus = new OperationStatus(status.getMessage(), status.getException());
			returnStatus.setSeverity(status.getSeverity());
			returnStatus.add(status);
		} else {
			returnStatus.add(status);
		}
		return returnStatus;
	}

	private OperationStatus addExtendedStatus(OperationStatus returnStatus, IStatus aStatus) {
		if (returnStatus == null) {
			returnStatus = new OperationStatus(new IStatus[]{WTPCommonPlugin.OK_STATUS});
		}
		returnStatus.addExtendedStatus(aStatus);
		return returnStatus;
	}

	private OperationStatus runOperation(final IDataModelOperation operation, final IProgressMonitor monitor, final IAdaptable info, final int executionType, OperationStatus returnStatus) {
		if (rootOperation == operation) {
			IStatus status = runOperation(operation, monitor, info, IDataModelPausibleOperationEvent.EXECUTE);
			if (!status.isOK()) {
				returnStatus = addStatus(returnStatus, status);
			}
		} else {
			try {
				IStatus status = runOperation(operation, monitor, info, IDataModelPausibleOperationEvent.EXECUTE);
				if (!status.isOK()) {
					returnStatus = addExtendedStatus(returnStatus, status);
				}
			} catch (Exception e) {
				IStatus status = new Status(IStatus.ERROR, WTPCommonPlugin.PLUGIN_ID, 0, WTPResourceHandler.getString("25", new Object[]{operation.getClass().getName()}), e); //$NON-NLS-1$
				returnStatus = addExtendedStatus(returnStatus, status);
			}
		}
		return returnStatus;
	}

	private IStatus runOperation(final IDataModelOperation operation, final IProgressMonitor monitor, final IAdaptable info, final int executionType) {
		IWorkspaceRunnableWithStatus workspaceRunnable = new IWorkspaceRunnableWithStatus(info) {
			public void run(IProgressMonitor pm) throws CoreException {
				try {
					switch (executionType) {
						case IDataModelPausibleOperationEvent.EXECUTE :
							this.setStatus(operation.execute(pm, info));
							break;
						case IDataModelPausibleOperationEvent.UNDO :
							this.setStatus(operation.undo(pm, info));
							break;
						case IDataModelPausibleOperationEvent.REDO :
							this.setStatus(operation.redo(pm, info));
							break;
					}
					if (null == this.getStatus()) {
						this.setStatus(Status.OK_STATUS);
					}
				} catch (Exception e) {
					this.setStatus(new Status(IStatus.ERROR, WTPCommonPlugin.PLUGIN_ID, 0, WTPResourceHandler.getString("25", new Object[]{operation.getClass().getName()}), e)); //$NON-NLS-1$
					WTPCommonPlugin.logError(e);
				}
			}
		};

		ISchedulingRule rule = operation.getSchedulingRule();
		if (null == rule) {
			rule = ResourcesPlugin.getWorkspace().getRoot();
		}

		try {
			ResourcesPlugin.getWorkspace().run(workspaceRunnable, rule, operation.getOperationExecutionFlags(), monitor);
		} catch (CoreException e) {
			workspaceRunnable.setStatus(new Status(IStatus.ERROR, WTPCommonPlugin.PLUGIN_ID, 0, WTPResourceHandler.getString("25", new Object[]{operation.getClass().getName()}), e)); //$NON-NLS-1$
		}
		return workspaceRunnable.getStatus();
	}

	protected class OperationStackEntry {

		private IDataModelOperation operation;
		private IDataModelOperation operationForExecution;

		private boolean extendedOpsInitialized = false;

		private ComposedExtendedOperationHolder extOpHolder = null;

		private int preOpIndex = 0;
		private int postOpIndex = 0;

		private OperationStackEntry[] preOpStackEntries = null;
		private OperationStackEntry[] postOpStackEntries = null;

		public OperationStackEntry parent = null;

		public OperationStackEntry(OperationStackEntry parent, IDataModelOperation operation) {
			this.parent = parent;
			this.operation = operation;
			this.operationForExecution = operation;
		}

		public OperationStackEntry rollBackOneOperation() {
			postOpIndex = 0;
			operationForExecution = operation;
			if (preOpIndex == 0 && parent != null) {
				return parent.rollBackExtended(this);
			}
			return this;
		}

		private OperationStackEntry rollBackExtended(OperationStackEntry extendedEntry) {
			while (postOpIndex > 0) {
				int index = --postOpIndex;
				if (postOpStackEntries[index] == extendedEntry) {
					postOpStackEntries[index] = null;
					return this;
				}
			}
			while (preOpIndex > 0) {
				int index = --preOpIndex;
				if (preOpStackEntries[index] == extendedEntry) {
					preOpStackEntries[index] = null;
					if (index != 0) {
						return this;
					}
				}
			}
			if (null != parent) {
				return parent.rollBackExtended(this);
			}
			return this;
		}

		public OperationStackEntry getNextPreOperation() {
			if (!extendedOpsInitialized) {
				initExtendedOps();
			}
			if (extOpHolder == null) {
				return null;
			}
			List ops = extOpHolder.getPreOps();
			if (ops == null || ops.size() <= preOpIndex) {
				return null;
			}

			while (preOpIndex < ops.size()) {
				int index = preOpIndex++;
				IDataModelOperation op = (IDataModelOperation) ops.get(index);
				if (shouldExecuteExtended(op.getID())) {
					op.setDataModel(getDataModel());
					op.setEnvironment(getEnvironment());
					preOpStackEntries[index] = new OperationStackEntry(this, op);
					return preOpStackEntries[index];
				}
			}
			return null;
		}

		public String toString() {
			return getOperationID();
		}

		public String getOperationID() {
			return operation.getID();
		}

		public IDataModelOperation getOperation() {
			return operation;
		}

		public boolean executed() {
			return null != operationForExecution;
		}

		/**
		 * The root operation is only returned once; this way it is known whether it has been
		 * executed yet or not.
		 * 
		 * @return
		 */
		public IDataModelOperation getOperationForExecution() {
			try {
				return operationForExecution;
			} finally {
				operationForExecution = null;
			}
		}

		public OperationStackEntry getNextPostOperation() {
			if (!extendedOpsInitialized) {
				initExtendedOps();
			}
			if (extOpHolder == null) {
				return null;
			}
			List ops = extOpHolder.getPostOps();
			if (ops == null || ops.size() <= postOpIndex) {
				return null;
			}

			while (postOpIndex < ops.size()) {
				int index = postOpIndex++;
				IDataModelOperation op = (IDataModelOperation) ops.get(index);
				if (shouldExecuteExtended(op.getID())) {
					op.setDataModel(getDataModel());
					op.setEnvironment(getEnvironment());
					postOpStackEntries[index] = new OperationStackEntry(this, op);
					return postOpStackEntries[index];
				}
			}
			return null;

		}

		private void initExtendedOps() {
			if (shouldExecuteExtended(operation.getID())) {
				extOpHolder = ComposedExtendedOperationHolder.createExtendedOperationHolder(operation.getID());
				if (null != extOpHolder) {
					if (extOpHolder.hasPreOps()) {
						preOpStackEntries = new OperationStackEntry[extOpHolder.getPreOps().size()];
					}
					if (extOpHolder.hasPostOps()) {
						postOpStackEntries = new OperationStackEntry[extOpHolder.getPostOps().size()];
					}
				}
			}
			extendedOpsInitialized = true;
		}
	}

	protected boolean shouldExecuteExtended(String operationID) {
		// Check the top most level operation first
		DataModelPausibleOperationImpl threadRootOperation = (DataModelPausibleOperationImpl) threadToExtendedOpControl.get(Thread.currentThread());
		if (threadRootOperation != this && threadRootOperation.getDataModel() != getDataModel() && !threadRootOperation.shouldExecuteExtended(operationID)) {
			return false;
		}
		// No extended operations are being executed
		boolean allowExtensions = getDataModel().getBooleanProperty(IDataModelProperties.ALLOW_EXTENSIONS);
		if (!allowExtensions) {
			return false;
		}
		// This specific operation should not be executed
		List restrictedExtensions = (List) getDataModel().getProperty(IDataModelProperties.RESTRICT_EXTENSIONS);
		if (restrictedExtensions.contains(operationID)) {
			return false;
		}
		// This specific function group should not be executed
		List extendedContext = getDataModel().getExtendedContext();
		for (int contextCount = 0; contextCount < extendedContext.size(); contextCount++) {
			IProject project = (IProject) AdaptabilityUtility.getAdapter(extendedContext.get(contextCount), IProject.class);
			if (null != project && !IEnablementManager.INSTANCE.getIdentifier(operationID, project).isEnabled()) {
				return false;
			}
		}
		return true;
	}

}
