/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
package org.eclipse.compare.internal;

import java.lang.reflect.InvocationTargetException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

import org.eclipse.jface.dialogs.*;
import org.eclipse.jface.operation.*;
import org.eclipse.jface.resource.JFaceResources;

import org.eclipse.core.runtime.*;

/**
 * A modal dialog that displays progress during a long running operation.
 */
public class TimeoutContext {

	private static class ModalContextThread extends Thread {
		
		private boolean fWorking;
		private IRunnableWithProgress fRunnable;
		private Throwable fThrowable;
		private IProgressMonitor fProgressMonitor;
		private boolean fContinueEventDispatching= true;
		private Display fDisplay;

		private ModalContextThread(IRunnableWithProgress operation, IProgressMonitor monitor) {
			super("TimeoutContext"); //$NON-NLS-1$
			fRunnable= operation;
			fProgressMonitor= monitor;
		}
		
		synchronized boolean timeout(Display display) {
			fDisplay= display;
			return fWorking;
		}
		
		public void run() {
			try {
				fWorking= true;
				if (fRunnable != null)
					fRunnable.run(fProgressMonitor);
			} catch (InvocationTargetException e) {
				fThrowable= e;
			} catch (InterruptedException e) {
				fThrowable= e;
			} catch (RuntimeException e) {
				fThrowable= e;
			} catch (ThreadDeath e) {
				// Make sure to propagate ThreadDeath, or threads will never fully terminate
				throw e;
			} catch (Error e) {
				fThrowable= e;
			} finally {
				fWorking= false;
	
				if (fDisplay != null) {
					// Make sure that all events in the asynchronous event queue
					// are dispatched.
					fDisplay.syncExec(
						new Runnable() {
							public void run() {
								// do nothing
							}
						}
					);
					
					// Stop event dispatching
					fContinueEventDispatching= false;
					
					// Force the event loop to return from sleep () so that
					// it stops event dispatching.
					fDisplay.asyncExec(null);
				}
			}	
		}
		
		public void block() {
			while (fContinueEventDispatching)
				if (!fDisplay.readAndDispatch())
					fDisplay.sleep();
		}		
	}
	
	static class ProgressMonitorDialog extends org.eclipse.jface.dialogs.Dialog {

		protected ProgressIndicator fProgressIndicator;
		protected Label fTaskLabel;
		protected Label fSubTaskLabel;
		protected Button fCancel;
		protected boolean fEnableCancelButton;
		private ProgressMonitor fProgressMonitor;
		private Cursor fArrowCursor;
		private Cursor fWaitCursor;
		private Shell fParentShell;
		
		private ProgressMonitorDialog(Shell parent, boolean cancelable, ProgressMonitor pm) {
			super(parent);
			fProgressMonitor= pm;
			fParentShell= parent;
			fEnableCancelButton= cancelable;
			this.setBlockOnOpen(false);
			setShellStyle(SWT.BORDER | SWT.TITLE | SWT.APPLICATION_MODAL); // no close button
		}
		
		public boolean close() {
			if (fCancel != null && !fCancel.isDisposed())
				fCancel.setCursor(null);
			Shell shell= getShell();
			if (shell != null && !shell.isDisposed())
				shell.setCursor(null);
			if (fArrowCursor != null)
				fArrowCursor.dispose();
			if (fWaitCursor != null)
				fWaitCursor.dispose();
			fArrowCursor= null;
			fWaitCursor= null;
			return super.close();
		}
		
		protected void configureShell(Shell shell) {
			super.configureShell(shell);
			shell.setText(JFaceResources.getString("ProgressMonitorDialog.title")); //$NON-NLS-1$
			if (fWaitCursor == null)
				fWaitCursor= new Cursor(shell.getDisplay(),SWT.CURSOR_WAIT);
			shell.setCursor(fWaitCursor);
		}
		
		protected void createButtonsForButtonBar(Composite parent) {
			// cancel button		
			fCancel= createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, true);
			if(fArrowCursor == null)
				fArrowCursor= new Cursor(fCancel.getDisplay(),SWT.CURSOR_ARROW);		
			fCancel.setCursor(fArrowCursor);
			fCancel.addListener(SWT.Selection,
				new Listener() {
					public void handleEvent(Event e) {
						if (fCancel != null && !fCancel.isDisposed())
							fCancel.setEnabled(false);
						fProgressMonitor.setCanceled(true);
					}
				}
			);
			fCancel.setEnabled(fEnableCancelButton);
		}
		
		protected Control createDialogArea(Composite parent) {
		
			Composite c= (Composite)super.createDialogArea(parent);
			((GridLayout)c.getLayout()).numColumns= 2;
	
			// icon
			Label iconLabel= new Label(c, SWT.LEFT);
			GridData gd= new GridData();
			iconLabel.setLayoutData(gd);
			iconLabel.setFont(parent.getFont());
			Image i= JFaceResources.getImageRegistry().get(org.eclipse.jface.dialogs.Dialog.DLG_IMG_INFO);
			if (i != null)
				iconLabel.setImage(i);
			else
				iconLabel.setText(JFaceResources.getString("Image_not_found")); //$NON-NLS-1$
	
			// label on right hand side of icon
			fTaskLabel= new Label(c, SWT.LEFT | SWT.WRAP);
			fTaskLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
			fTaskLabel.setFont(parent.getFont());
	
			// progress indicator
			fProgressIndicator= new ProgressIndicator(c);
			gd= new GridData();
			gd.heightHint= 15;
			gd.horizontalAlignment= GridData.FILL;
			gd.grabExcessHorizontalSpace= true;
			gd.horizontalSpan= 2;
			fProgressIndicator.setLayoutData(gd);
	
			// label showing current task
			fSubTaskLabel= new Label(c, SWT.LEFT | SWT.WRAP);
			gd= new GridData(GridData.FILL_HORIZONTAL);
			gd.heightHint= 35;	
			gd.horizontalSpan= 2;
			fSubTaskLabel.setLayoutData(gd);
			fSubTaskLabel.setFont(parent.getFont());
						
			// update with values fProgressMonitor
			String s= fProgressMonitor.fTask;
			if (s == null)
				s= ""; //$NON-NLS-1$
			fTaskLabel.setText(s);
			
			if (fProgressMonitor.fMaxWork == IProgressMonitor.UNKNOWN)
				fProgressIndicator.beginAnimatedTask();
			else
				fProgressIndicator.beginTask(fProgressMonitor.fMaxWork);

			if (fProgressMonitor.fSubTask != null)
				fSubTaskLabel.setText(fProgressMonitor.fSubTask);
			fProgressIndicator.worked(fProgressMonitor.fWorked);
	
			fProgressMonitor.activate(this);

			return c;
		}
		
		void beginTask(final String name, final int totalWork) {
			fParentShell.getDisplay().syncExec(
				new Runnable() {
					public void run() {
						fTaskLabel.setText(name);
						
						if (fProgressIndicator != null && fProgressIndicator.isDisposed()) {
							if (totalWork == IProgressMonitor.UNKNOWN)
								fProgressIndicator.beginAnimatedTask();
							else
								fProgressIndicator.beginTask(totalWork);
						}
					}
				}
			);
		}
		
		void setTaskName(final String name) {
			fParentShell.getDisplay().syncExec(
				new Runnable() {
					public void run() {
						if (fTaskLabel != null && fTaskLabel.isDisposed())
							fTaskLabel.setText(name);
					}
				}
			);
		}

		void setSubTaskName(final String name) {
			fParentShell.getDisplay().syncExec(
				new Runnable() {
					public void run() {
						String n= (name == null) ? "" : name;	//$NON-NLS-1$
						if (fSubTaskLabel != null && !fSubTaskLabel.isDisposed())
							fSubTaskLabel.setText(n);
					}
				}
			);	
		}
		
		void done() {
			fParentShell.getDisplay().syncExec(
				new Runnable() {
					public void run() {
						if (fProgressIndicator != null && !fProgressIndicator.isDisposed()) {
							fProgressIndicator.sendRemainingWork();
							fProgressIndicator.done();
						}
					}
				}
			);
		}
		
		void worked(final double work) {
			fParentShell.getDisplay().syncExec(
				new Runnable() {
					public void run() {
						if (fProgressIndicator != null && !fProgressIndicator.isDisposed())
							fProgressIndicator.worked(work);
					}
				}
			);
		}

		protected Point getInitialSize() {
			return getShell().computeSize(450, SWT.DEFAULT);
		}
	}

	private static class ProgressMonitor implements IProgressMonitor {
		
		private int fMaxWork;
		private String fTask;
		private String fSubTask;
		private int fWorked;
		private ProgressMonitorDialog fProgressMonitorDialog;
		private boolean fIsCanceled;
		
		public void beginTask(String name, int totalWork) {
			
			fTask= name;
			fMaxWork= totalWork;
			fWorked= 0;
			
			if (fProgressMonitorDialog != null)	
				fProgressMonitorDialog.beginTask(name, totalWork);			
		}
		
		void activate(ProgressMonitorDialog dialog) {
			fProgressMonitorDialog= dialog;
		}
		
		public void done() {
			if (fProgressMonitorDialog != null)				
				fProgressMonitorDialog.done();
		}
		
		public void setTaskName(String name) {
			fTask= name;
			if (fProgressMonitorDialog != null)				
				fProgressMonitorDialog.setTaskName(name);
		}
				
		public boolean isCanceled() {
			return fIsCanceled;
		}
		
		public void setCanceled(boolean b) {
			fIsCanceled= b;
		}
		
		public void subTask(String name) {
			fSubTask= name;
			if (fProgressMonitorDialog != null)				
				fProgressMonitorDialog.setSubTaskName(name);
		}
		
		public void worked(int work) {
			if (fProgressMonitorDialog != null)
				internalWorked(work);
			else
				fWorked+= work;
		}
		
		public void internalWorked(double work) {
			if (fProgressMonitorDialog != null)				
				fProgressMonitorDialog.worked(work);
		}
	}
	
	public static void run(boolean cancelable, int timeout, Shell parent, IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException {
		
		Display display= parent.getDisplay();
		
		ProgressMonitor pm= new ProgressMonitor();
				
		ModalContextThread t= new ModalContextThread(runnable, pm);
		t.start();	// start the long running operation
		
		// wait until long operations terminates or timeout
		try {
			t.join(timeout);
		} catch (InterruptedException e) {
		}
		
		if (t.timeout(display)) {	// timeout
			ProgressMonitorDialog dialog= new ProgressMonitorDialog(parent, cancelable, pm);
			dialog.open();
			t.block();
			dialog.close();
		}
		
		Throwable throwable= t.fThrowable;
		if (throwable != null) {
			if (throwable instanceof InvocationTargetException) {
				throw (InvocationTargetException) throwable;
			} else if (throwable instanceof InterruptedException) {
				throw (InterruptedException) throwable;
			} else if (throwable instanceof OperationCanceledException) {
				throw new InterruptedException(throwable.getMessage());
			} else {
				throw new InvocationTargetException(throwable);
			}	
		}
	}
}

