/*
 * Created on 28.11.2003
 * Copyright (C) 2003, 2004, 2005, 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.common.util;

import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.disk.DiskManager;
import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
import org.gudy.azureus2.core3.disk.DiskManagerListener;
import org.gudy.azureus2.core3.disk.DiskManagerPiece;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.DownloadManagerDiskListener;
import org.gudy.azureus2.core3.download.DownloadManagerState;
import org.gudy.azureus2.core3.download.impl.DownloadManagerAdapter;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.global.impl.GlobalManagerAdpater;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.util.AEMonitor;
import org.gudy.azureus2.core3.util.AEThread;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;

import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.URL;

/**
 * Contains methods to alert the user of certain events.
 * @author Rene Leonhardt
 */

public class 
UserAlerts 
{
  	private AudioClip 	audio_clip 		= null;
  	private String		audio_resource	= "";
  	
    private AEMonitor	this_mon 	= new AEMonitor( "UserAlerts" );
    
    private boolean startup = true;
    
	public 
	UserAlerts(
		GlobalManager	global_manager ) 
 	{	
		final DownloadManagerAdapter download_manager_listener = 
			new DownloadManagerAdapter()
			{
				public void
				downloadComplete(DownloadManager manager)
				{
					if( !manager.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )){
						
						activityFinished(true, manager.getDisplayName(), manager);
					}
				}
			}; 
		
		final DiskManagerListener	disk_listener = 
			new DiskManagerListener()
			{
				public void
				stateChanged(
					int oldState, 
					int	newState )
				{	
				}
				
				public void
				filePriorityChanged(
					DiskManagerFileInfo		file )
				{
				}
	
				public void
				pieceDoneChanged(
					DiskManagerPiece		piece )
				{
				}
				
				public void
				fileAccessModeChanged(
					DiskManagerFileInfo		file,
					int						old_mode,
					int						new_mode )
				{
					DownloadManager dm = file.getDownloadManager();
				
					if ( 	old_mode == DiskManagerFileInfo.WRITE &&
							new_mode == DiskManagerFileInfo.READ ){
						
						if( dm == null || !dm.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )){

							activityFinished(false, file.getFile(true).getName(), file.getDiskManager());
						}
					}
				
					/*
					System.out.println( 
						"amc:" + 
						file.getDownloadManager().getDisplayName() + "/" + 
						file.getName() + ":" + old_mode + " -> " + new_mode );
					*/
				}
			};
			
		final DownloadManagerDiskListener dm_disk_listener = 
			new DownloadManagerDiskListener()
			{
				public void
				diskManagerAdded(
					DiskManager	dm )
				{
					dm.addListener( disk_listener );
				}
				
				public void
				diskManagerRemoved(
					DiskManager	dm )
				{
					dm.removeListener( disk_listener );
				}
				
    			public boolean
    			syncInvokeRequired()
    			{
    				return( false );
    			}
			};

    	global_manager.addListener(
    		new GlobalManagerAdpater()
    		{
				public void 
				downloadManagerAdded(DownloadManager manager) 
				{
						// don't pop up for non-persistent as these get added late in the day every time
						// so we'll notify for each download every startup
					
					if (!startup && manager.isPersistent()) {
						
						boolean bPopup = COConfigurationManager.getBooleanParameter("Popup Download Added");

						if ( bPopup ){

							if( !manager.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )){

								String popup_text = MessageText.getString("popup.download.added",
										new String[] { manager.getDisplayName()
								});
								Logger.log(new LogAlert(manager, true, LogAlert.AT_INFORMATION, popup_text));
							}
						}
					}
					
					manager.addListener( download_manager_listener );
					
					manager.addDiskListener( dm_disk_listener );
				}

				public void 
				downloadManagerRemoved(DownloadManager manager) 
				{
					manager.removeListener(download_manager_listener);
					
					manager.removeDiskListener( dm_disk_listener );
				}  
				
				public void
				destroyed()
				{
					tidyUp();
				} 		
			}); 
    	startup = false;
     }

  	protected void activityFinished(boolean	download, String item_name, Object relatedObject)
  	{
  		final String sound_enabler;
  		final String sound_file;
  		final String default_sound 	= "org/gudy/azureus2/ui/icons/downloadFinished.wav";
  		
  		final String speech_enabler;
  		final String speech_text;
  		
  		final String popup_enabler;
  		final String popup_def_text;
  		
  		if ( download ){
	 		sound_enabler 	= "Play Download Finished";
	  		sound_file		= "Play Download Finished File";
	  		
	  		speech_enabler 	= "Play Download Finished Announcement";
	  		speech_text		= "Play Download Finished Announcement Text";
	  		
	  		popup_enabler   = "Popup Download Finished";
	  		popup_def_text  = "popup.download.finished";
  		}else{
	 		sound_enabler 	= "Play File Finished";
	  		sound_file		= "Play File Finished File";
	  		
	  		speech_enabler 	= "Play File Finished Announcement";
	  		speech_text		= "Play File Finished Announcement Text";
	  		
	  		popup_enabler   = "Popup File Finished";
	  		popup_def_text  = "popup.file.finished";
  		}
  		
  		try{
  			this_mon.enter();
  			
  			if (COConfigurationManager.getBooleanParameter(popup_enabler)) {
  				String popup_text = MessageText.getString(popup_def_text, new String[]{item_name});
  				Logger.log(new LogAlert(relatedObject, true, LogAlert.AT_INFORMATION, popup_text));
  			}

            if(Constants.isOSX) { // OS X cannot concurrently use SWT and AWT
                new AEThread("DownloadSound") {
                    public void runSupport()
                    {
                        try {
                            if(COConfigurationManager.getBooleanParameter( speech_enabler ))
                                Runtime.getRuntime().exec(new String[]{"say", COConfigurationManager.getStringParameter( speech_text )}); // Speech Synthesis services

                            if(COConfigurationManager.getBooleanParameter( sound_enabler ))
                                Runtime.getRuntime().exec(new String[]{"osascript", "-e" ,"beep"}); // Beep alert type is in accordance with System Preferences

                            Thread.sleep(2500);
                        }
                        catch(Throwable e) {}
                    }
                }.start();
            }
	    	else if( COConfigurationManager.getBooleanParameter( sound_enabler, false)){

	    		String	file = COConfigurationManager.getStringParameter( sound_file );

    			file = file.trim();

	    			// turn "<default>" into blank

	    		if ( file.startsWith( "<" )){

	    			file	= "";
	    		}

	    		if ( audio_clip == null || !file.equals( audio_resource )){

	    			audio_clip	= null;

	    				// try explicit file

	    			if ( file.length() != 0 ){

	    				File	f = new File( file );

	    				try{

			    			if ( f.exists()){

		    					URL	file_url = f.toURL();

		    					audio_clip = Applet.newAudioClip( file_url );
			    			}

	    				}catch( Throwable  e ){

	    					Debug.printStackTrace(e);

	    				}finally{

	    					if ( audio_clip == null ){
	    						Logger.log(new LogAlert(relatedObject, LogAlert.UNREPEATABLE,
										LogAlert.AT_ERROR, "Failed to load audio file '" + file
												+ "'"));
	    					}
	    				}
	    			}

	    				// either non-explicit or explicit missing

	    			if ( audio_clip == null ){

	    				audio_clip = Applet.newAudioClip(UserAlerts.class.getClassLoader().getResource( default_sound ));

	    			}

	    			audio_resource	= file;
	    		}

	    		if ( audio_clip != null ){

	            	new AEThread("DownloadSound")
					{
		        		public void
						runSupport()
		        		{
		        			try{
		        				audio_clip.play();

		        				Thread.sleep(2500);

		        			}catch( Throwable e ){

		        			}
		        		}
		        	}.start();
		        }
	    	}
  		}catch( Throwable e ){
  			
  			Debug.printStackTrace( e );
  			
  		}finally{
  			
  			this_mon.exit();
  		}
  	}
  	
  	protected void
  	tidyUp()
  	{
		/*
		The Java audio system keeps some threads running even after playback is finished.
		One of them, named "Java Sound event dispatcher", is *not* a daemon
		thread and keeps the VM alive.
		We have to locate and interrupt it explicitely.
		*/
		
		try{
		
			ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
			
			Thread[] threadList = new Thread[threadGroup.activeCount()];
			
			threadGroup.enumerate(threadList);
			
			for (int i = 0;	i < threadList.length;	i++){
			
				if(threadList[i] != null && "Java Sound event dispatcher".equals(threadList[i].getName())){
									
					threadList[i].interrupt();
				}
			}
		}catch( Throwable e ){
			
			Debug.printStackTrace( e );
		}
  	}
}