/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
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);
			applyDialogFont(c);
			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);
			}	
		}
	}
}

