/*
 * Created on 27 Jul 2006
 * Created by Paul Gardner
 * Copyright (C) 2006 Aelitis, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 * AELITIS, SAS au capital de 46,603.30 euros
 * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
 *
 */

package org.gudy.azureus2.ui.swt.progress;

import java.io.InputStream;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.AEThread;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.DelayedEvent;
import org.gudy.azureus2.ui.swt.ImageRepository;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;

import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreOperation;
import com.aelitis.azureus.core.AzureusCoreOperationListener;

public class 
ProgressWindow 
{
	public static void
	register(
		AzureusCore		core )
	{
		core.addOperationListener(
			new AzureusCoreOperationListener()
			{
				public boolean
				operationCreated(
					AzureusCoreOperation	operation )
				{
					if ( 	operation.getOperationType() == AzureusCoreOperation.OP_FILE_MOVE &&
							Utils.isThisThreadSWT()){
												
						if ( operation.getTask() != null ){
							
							new ProgressWindow( operation );
														
							return( true );
						}
					}
					
					return( false );
				}
			});
	}
	
	private volatile Shell 		shell;
	private volatile boolean 	task_complete;
	
	public 
	ProgressWindow(
		final AzureusCoreOperation	operation )
	{
		final RuntimeException[] error = {null};
		
		new DelayedEvent( 
				"ProgWin",
				1000,
				new AERunnable()
				{
					public void
					runSupport()
					{
						synchronized( this ){
							
							if ( !task_complete ){
								
								Utils.execSWTThread(
									new Runnable()
									{
										public void
										run()
										{
											synchronized( this ){
												
												if ( !task_complete ){
											
													showDialog();
												}
											}
										}
									},
									false );
							}
						}
					}
				});
		
		new AEThread( "ProgressWindow", true )
		{
			public void 
			runSupport()
			{
				try{	
					// Thread.sleep(10000);
					
					operation.getTask().run( operation );
					
				}catch( RuntimeException e ){
					
					error[0] = e;
					
				}catch( Throwable e ){
		
					error[0] = new RuntimeException( e );
					
				}finally{
					
					synchronized( this ){
						
						task_complete = true;
						
						Utils.execSWTThread( new Runnable(){public void run(){}}, true );
					}			
				}
			}
		}.start();
			
		try{
			final Display display = SWTThread.getInstance().getDisplay();
	
			while( !( task_complete || display.isDisposed())){
				
				if (!display.readAndDispatch()) display.sleep();
			}
		}finally{
			
				// bit of boiler plate in case something fails in the dispatch loop
			
			synchronized( this ){
				
				task_complete = true;
			}
			
			try{
				if ( shell != null && !shell.isDisposed()){
				
					shell.dispose();
				}
			}catch( Throwable e ){
				
				Debug.printStackTrace(e);
			}
		}
		
		if ( error[0] != null ){
			
			throw( error[0] );
		}
	}
	
	protected void
	showDialog()
	{	
		shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createMainShell(
				( SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL ));

		shell.setText( MessageText.getString( "progress.window.title" ));

		if(! Constants.isOSX) {
			shell.setImage(ImageRepository.getImage("azureus"));
		}

		shell.addListener( 
				SWT.Close, 
				new Listener()
				{
					public void 
					handleEvent(
						org.eclipse.swt.widgets.Event event)
					{
						event.doit = false;
					}
				});
		
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		shell.setLayout(layout);

		InputStream	is = ImageRepository.getImageAsStream( "working" );
		
		if ( is == null ){
			
			new Label( shell, SWT.NULL );
			
		}else{
			
			final ImageLoader loader = new ImageLoader();
			
			final Color	background = shell.getBackground();

		    loader.load( is );
		    		    
		    final Canvas	canvas =
		    	new Canvas( shell, SWT.NULL )
		    	{
		    		public Point computeSize(int wHint, int hHint,boolean changed )
		    		{
		    			return( new Point(loader.logicalScreenWidth,loader.logicalScreenWidth));
		    		}
		    	};
		    			    		    
		    final GC canvas_gc = new GC( canvas );

	        new AEThread("GifAnim", true )
	        {
	        	private Image	image;
	        	private boolean useGIFBackground;
	        	
	        	public void 
	        	runSupport()
	        	{
	        		Display display = shell.getDisplay();  
	        	
	        		ImageData[]	image_data = loader.data;
	        		
	        			/* Create an off-screen image to draw on, and fill it with the shell background. */
	        		
	        		Image offScreenImage = new Image(display, loader.logicalScreenWidth, loader.logicalScreenHeight);
	        		
	        		GC offScreenImageGC = new GC(offScreenImage);
	        		
	        		offScreenImageGC.setBackground(background);
	        		
	        		offScreenImageGC.fillRectangle(0, 0, loader.logicalScreenWidth, loader.logicalScreenHeight);

	        		try{
	        				/* Create the first image and draw it on the off-screen image. */
	        			
	        			int imageDataIndex = 0;
	        			
	        			ImageData imageData = image_data[imageDataIndex];
	        			
	        			if (image != null && !image.isDisposed()) image.dispose();
	        			
	        			image = new Image(display, imageData);
	        			
	        			offScreenImageGC.drawImage(
	        					image,
	        					0,
	        					0,
	        					imageData.width,
	        					imageData.height,
	        					imageData.x,
	        					imageData.y,
	        					imageData.width,
	        					imageData.height);

		        			/* Now loop through the images, creating and drawing each one
		        			 * on the off-screen image before drawing it on the shell. */
		        			
	        			int repeatCount = loader.repeatCount;
	        			
	        			while ( !task_complete && loader.repeatCount == 0 || repeatCount > 0) {
	        				
	        				switch (imageData.disposalMethod){
	        				
		        				case SWT.DM_FILL_BACKGROUND:
		        					
		        						/* Fill with the background color before drawing. */
		        					
		        					Color bgColor = null;
		        					
		        					if (useGIFBackground && loader.backgroundPixel != -1) {
		        						
		        						bgColor = new Color(display, imageData.palette.getRGB(loader.backgroundPixel));
		        					}
		        					
		        					offScreenImageGC.setBackground(bgColor != null ? bgColor : background);
		        					
		        					offScreenImageGC.fillRectangle(imageData.x, imageData.y, imageData.width, imageData.height);
		        					
		        					if (bgColor != null) bgColor.dispose();
		        					
		        					break;
		        					
		        				case SWT.DM_FILL_PREVIOUS:
		        					
		        						/* Restore the previous image before drawing. */
		        					
		        					offScreenImageGC.drawImage(
		        							image,
		        							0,
		        							0,
		        							imageData.width,
		        							imageData.height,
		        							imageData.x,
		        							imageData.y,
		        							imageData.width,
		        							imageData.height);
		        					break;
	        				}

	        				imageDataIndex = (imageDataIndex + 1) % image_data.length;
	        				
	        				imageData = image_data[imageDataIndex];
	        				
	        				image.dispose();
	        				
	        				image = new Image(display, imageData);
	        				
	        				offScreenImageGC.drawImage(
	        						image,
	        						0,
	        						0,
	        						imageData.width,
	        						imageData.height,
	        						imageData.x,
	        						imageData.y,
	        						imageData.width,
	        						imageData.height);

	        					/* Draw the off-screen image to the shell. */
	        				
	        				canvas_gc.drawImage(offScreenImage, 0, 0);

	        					/* Sleep for the specified delay time (adding commonly-used slow-down fudge factors). */
	        				
	        				try {
	        					int ms = imageData.delayTime * 10;
	        					if (ms < 20) ms += 30;
	        					if (ms < 30) ms += 10;
	        					
	        					Thread.sleep(ms);
	        				} catch (InterruptedException e) {
	        				}

	        					/* If we have just drawn the last image, decrement the repeat count and start again. */
	        				
	        				if (imageDataIndex == image_data.length - 1) repeatCount--;
	        			}
	        		} catch (SWTException ex) {
	        			ex.printStackTrace();
	        		} finally {
	        			if (offScreenImage != null && !offScreenImage.isDisposed()) offScreenImage.dispose();
	        			if (offScreenImageGC != null && !offScreenImageGC.isDisposed()) offScreenImageGC.dispose();
	        			if (image != null && !image.isDisposed()) image.dispose();
	        		}
	        	}
	        }.start();
		}
		
		
		Label label = new Label(shell, SWT.NONE);
		label.setText(MessageText.getString( "progress.window.msg.filemove" ));
		GridData gridData = new GridData();
		label.setLayoutData(gridData);

		shell.pack();
		
		Utils.centreWindow( shell );

		shell.open();
	}
}
