/*******************************************************************************
 * Copyright (c) 2005 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.jst.ws.internal.consumption.ui.server;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.wizard.ProgressMonitorPart;
import org.eclipse.jst.ws.internal.consumption.command.common.StartServerCommand;
import org.eclipse.jst.ws.internal.consumption.ui.ConsumptionUIMessages;
import org.eclipse.jst.ws.internal.ui.common.UIUtils;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.command.internal.env.core.common.StatusUtils;
import org.eclipse.wst.command.internal.env.core.context.TransientResourceContext;
import org.eclipse.wst.command.internal.env.eclipse.EclipseEnvironment;
import org.eclipse.wst.command.internal.env.ui.eclipse.EclipseStatusHandler;
import org.eclipse.wst.command.internal.env.ui.widgets.SimpleWidgetDataContributor;
import org.eclipse.wst.command.internal.env.ui.widgets.WidgetDataEvents;
import org.eclipse.wst.common.environment.NullStatusHandler;
import org.eclipse.wst.server.core.IServer;

public class StartServerWidget extends SimpleWidgetDataContributor 
{
  private IServer             server_;
  private IStatus              status_;
  private Listener            statusListener_;
  private Button              button_;
  private JobChangeAdapter    jobChangeAdapter_;
  private Text                serverStateText_;
  private ProgressMonitorPart progressMonitor_;
  private String              pluginId_;
  private Composite           buttonGroup_;
    
  /*CONTEXT_ID SSWP0001 Start the server button. */
  private String INFOPOP_SSWP_SERVER_BUTTON = "SSWP0001";
  
  public StartServerWidget( IServer server )
  {
	pluginId_ = "org.eclipse.jst.ws.consumption.ui";
		
    server_ = server;
    
    jobChangeAdapter_ = new JobChangeAdapter()
                        {
                          public void done(final IJobChangeEvent event) 
                          {
                        	Display.getDefault().asyncExec( new Runnable()
                        			                        {
	        					                              public void run() 
							                                  {
	        						                            if( !progressMonitor_.isDisposed() )
	        						                            {
							                                      setServerState();	
							                                      progressMonitor_.done();
							                                      reportErrorIfRequired( (StartServerJob)event.getJob() );
	        						                            }
							                                  }
                        			                        });
                          }
                        };
  }
  
  public WidgetDataEvents addControls(Composite parent, Listener statusListener) 
  {
	statusListener_ = statusListener;
	
	UIUtils      uiUtils     = new UIUtils( pluginId_ );
	Composite    group       = uiUtils.createComposite( parent, 1 );
	
	Text         text1        = uiUtils.createText( group, null, null, null, SWT.READ_ONLY );
	text1.setText( NLS.bind(ConsumptionUIMessages.LABEL_START_SERVER_TEXT1, new String[]{ server_.getName() } ));
	
	Text         text2        = uiUtils.createText( group, null, null, null, SWT.READ_ONLY );
	text2.setText( NLS.bind(ConsumptionUIMessages.LABEL_START_SERVER_TEXT2, new String[]{ server_.getName() } ));
	
	Text         text3        = uiUtils.createText( group, null, null, null, SWT.READ_ONLY );
	text3.setText( NLS.bind(ConsumptionUIMessages.LABEL_START_SERVER_TEXT3, new String[]{ server_.getName() } ));
	
	Text         text4        = uiUtils.createText( group, null, null, null, SWT.READ_ONLY );
	text4.setText( NLS.bind(ConsumptionUIMessages.LABEL_START_SERVER_TEXT4, new String[]{ server_.getName() } )); 
	
	buttonGroup_ = uiUtils.createComposite( group, 2,-1, 0 );
	serverStateText_ = uiUtils.createText( buttonGroup_, null, null, null, SWT.READ_ONLY );
	serverStateText_.setLayoutData( new GridData() );
		
	button_ = uiUtils.createPushButton( buttonGroup_, 
			ConsumptionUIMessages.LABEL_START_SERVER_BUTTON,
			ConsumptionUIMessages.TOOLTIP_START_SERVER_BUTTON,
			                            INFOPOP_SSWP_SERVER_BUTTON );
	
	button_.addSelectionListener( new SelectionAdapter()
			                      {
									 public void widgetSelected( SelectionEvent evt )
		                             {
			                       	   serverStateText_.setText( getStateMessage( ConsumptionUIMessages.TEXT_SERVER_STATUS, ConsumptionUIMessages.TEXT_SERVER_STARTING ) );
			                    	   progressMonitor_.beginTask( getStateMessage( ConsumptionUIMessages.TEXT_SERVER_MSG, ConsumptionUIMessages.TEXT_SERVER_STARTING ), IProgressMonitor.UNKNOWN );
			                    	   button_.setEnabled( false );
			                    	   buttonGroup_.pack();
		                               startServerJob();
		                             }	                          
			                      } );	
	
	progressMonitor_ = new ProgressMonitorPart( group, new GridLayout() );
	progressMonitor_.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ));
	
	setServerState();
	return this;
  }

  public IStatus getStatus() 
  {
	return status_;
  }
  
  private void setServerState()
  {
	int state = server_.getServerState();
	
	switch( state )
	{
	  case IServer.STATE_STARTED:
	  {
		status_ = Status.OK_STATUS;
		button_.setEnabled( false );
		serverStateText_.setText( getStateMessage( ConsumptionUIMessages.TEXT_SERVER_STATUS, ConsumptionUIMessages.TEXT_SERVER_STARTED ) );
		
	    break;	  
	  }
	  
	  case IServer.STATE_STARTING:
	  {
		status_ = StatusUtils.errorStatus( "" );
		button_.setEnabled( false );  
		serverStateText_.setText( getStateMessage( ConsumptionUIMessages.TEXT_SERVER_STATUS, ConsumptionUIMessages.TEXT_SERVER_STARTING ) );
		progressMonitor_.beginTask( getStateMessage( ConsumptionUIMessages.TEXT_SERVER_MSG, ConsumptionUIMessages.TEXT_SERVER_STARTING ), IProgressMonitor.UNKNOWN );
		
		// The server is still starting so we need to reconnect to the job
		// that is starting it.
		startServerJob();
	    break;	  
	  }
	  
	  default:
	  {
		status_ = StatusUtils.errorStatus( "" );
        button_.setEnabled( true );
		serverStateText_.setText( getStateMessage( ConsumptionUIMessages.TEXT_SERVER_STATUS, ConsumptionUIMessages.TEXT_SERVER_STOPPED ) );
		break;  
	  }
	};
	
	statusListener_.handleEvent( null );
	buttonGroup_.pack();
  }  
  
  private String getStateMessage( String mainKey, String subKey )
  {
	return NLS.bind( mainKey, new String[]{ subKey } );
  }
  
  // Connect to an existing server thread otherwise start a new one.
  private void startServerJob()
  {
	IJobManager    jobManager     = Platform.getJobManager();
	Job[]          jobs           = jobManager.find( StartServerFamily );
	StartServerJob startServerJob = null;
	
	// There may be more than one job starting for different servers.
	// Therefore, we need to find the one for our server if it is available.
	for( int index = 0; index < jobs.length; index++ )
	{
	  StartServerJob jobFound = (StartServerJob)jobs[index];
	  
	  if( jobFound.getServer() == server_ )
	  {
	    startServerJob = jobFound;
	    break;
	  }
	}
	
	if( startServerJob != null )
	{
	  synchronized( StartServerFamily ) 
	  {
        IStatus status = startServerJob.getStatus();
        
        // We are using status to determine if the job has completed or not.
        // Normally, we would not get here if the job had already completed,
        // but there is a slim window where the job manager gives us the job
        // and then it immediately completes.
        if( status == null )
        {        
          // The job had not completed yet so we will add a job change listener.
          // We are adding the job listener here so that we don't have to assume
          // that this instance of this widget is the same as the previous instance.
          // If startServerJob already has "jobChangeAdapter_" added to it this
          // method call will not have an effect.(Which is what we want.)
          startServerJob.addJobChangeListener( jobChangeAdapter_ ); 
          
          // Note: this job was reporting progress to different progressMonitor_
          //       control.  We need to tell the job that it should report progress
          //       to our new progressMonitor_ control on this wizard page.
          ProgressMonitorWrapper monitor = (ProgressMonitorWrapper)startServerJob.getMonitor();
          monitor.setMonitor( progressMonitor_ );
        }
        else
        {
          // The job completed before we had a chance to add the job change listener
          // Therefore, we will just call jobChangeAdapter_ directly to notify
          // the UI that the job has completed.
          jobChangeAdapter_.done( null );
        }
	  }
	}
	else
	{
	  startServerJob = new StartServerJob();	
	  startServerJob.addJobChangeListener( jobChangeAdapter_ );
	  startServerJob.schedule();
	}
  }
     
  private void reportErrorIfRequired( StartServerJob serverJob )
  {
	  IStatus status = serverJob.getStatus();
	
	  if( status.getSeverity() == Status.ERROR )
	  {
	    Shell                shell   = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
      EclipseStatusHandler handler = new EclipseStatusHandler( shell );
      
      handler.reportError( status );
	  }
  }
  
  final private static String  StartServerFamily = "StartServerFamily";
  
  // This class is used to start up the server in an Eclipse job.
  private class StartServerJob extends Job
  {
	  private IStatus                status_ = null;
	  private ProgressMonitorWrapper envMonitor_;
	
	  public StartServerJob()
	  {
	    super( "StartServerJob" );
	  
	    envMonitor_ = new ProgressMonitorWrapper( progressMonitor_ );
	  }
	
	  public IServer getServer()
	  {
	    return server_;	
	  }
	
	  public ProgressMonitorWrapper getMonitor()
	  {
	    return envMonitor_;	
	  }
	
	  public boolean belongsTo(Object family) 
	  {
	    return family == StartServerFamily;
	  }

	  protected IStatus run(IProgressMonitor monitor) 
	  {
	    NullStatusHandler        handler         = new NullStatusHandler();
	    TransientResourceContext resourceContext = new TransientResourceContext();
	    EclipseEnvironment       environment     = new EclipseEnvironment( null,resourceContext, handler );
	    StartServerCommand       serverCommand   = new StartServerCommand( false, false );
	    
	    serverCommand.setServerInstanceId( server_.getId() );
      serverCommand.setEnvironment( environment );
	    
	    try
	    {
	      setStatus( serverCommand.execute( envMonitor_, null ) );		
	    }
	    catch( Throwable exc )
	    {
		    exc.printStackTrace();
	      setStatus( StatusUtils.errorStatus( exc ) );
	    }
	  	
	    return Status.OK_STATUS;
	  }
	
	  // Calls to this method need to first synchronize on the
	  // StartServerFamily object.
	  public IStatus getStatus()
	  {
	    return status_;
	  }
	
	  private void setStatus( IStatus status )
	  {
	    synchronized( StartServerFamily ) 
	    {
        status_ = status;
	    }
	  }
  }
    
  private class ProgressMonitorWrapper implements IProgressMonitor
  {
    private IProgressMonitor monitor_ = new NullProgressMonitor();
  	  	
    public ProgressMonitorWrapper( IProgressMonitor monitor )
    {
      monitor_ = monitor;  
    }
    
    public void setMonitor( IProgressMonitor monitor )
    {
      monitor_ = monitor;	
    }
    
    public void beginTask(final String name, final int totalWork) 
    {
      Display.getDefault().asyncExec( new Runnable()
      		                          {
                                        public void run()
                                        {
                                          if( !progressMonitor_.isDisposed() )
                                          {
                                      	    monitor_.beginTask( name, totalWork );
                                          }
                                        }
      		                          } );
    }

    public void done() 
    {
      Display.getDefault().asyncExec( new Runnable()
                                      {
                                        public void run()
                                        {
                                          if( !progressMonitor_.isDisposed() )
                                          {
              	                            monitor_.done();
                                          }
                                        }
                                      } );
    }

    public void internalWorked(final double work) 
    {
      Display.getDefault().asyncExec( new Runnable()
                                      {
                                        public void run()
                                        {
                                          if( !progressMonitor_.isDisposed() )
                                          {
              	                            monitor_.internalWorked( work );
                                          }
                                        }
                                      } );
    }

    public boolean isCanceled() 
    {
      return progressMonitor_.isDisposed() ? false : monitor_.isCanceled();
    }

    public void setCanceled(boolean value) 
    {
      if( !progressMonitor_.isDisposed() )
      {
  	    monitor_.setCanceled( value );
      }
    }

    public void setTaskName(final String name) 
    {
  	  Display.getDefault().asyncExec( new Runnable()
                                      {
                                        public void run()
                                        {
                                          if( !progressMonitor_.isDisposed() )
                                          {
                  	                        monitor_.setTaskName( name );
                                          }
                                        }
                                      } );
    }

    public void subTask( final String name) 
    {
  	  Display.getDefault().asyncExec( new Runnable()
                                      {
                                        public void run()
                                        {
                                          if( !progressMonitor_.isDisposed() )
                                          {
                  	                        monitor_.subTask( name );
                                          }
                                        }
                                      } );
    }

    public void worked(final int work) 
    {
      Display.getDefault().asyncExec( new Runnable()
                                      {
                                        public void run()
                                        {
                                          if( !progressMonitor_.isDisposed() )
                                          {
              	                            monitor_.worked( work );
                                          }
                                        }
                                      } );
    }
  }
}
