/*******************************************************************************
 * Copyright (c) 2004 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.creation.ui.widgets;

import org.eclipse.jst.ws.internal.consumption.ui.widgets.PreferencesSelectionWidget;
import org.eclipse.jst.ws.internal.consumption.ui.widgets.WebServiceClientTypeWidget;
import org.eclipse.jst.ws.internal.consumption.ui.wsrt.WebServiceRuntimeExtensionUtils;
import org.eclipse.jst.ws.internal.data.LabelsAndIds;
import org.eclipse.jst.ws.internal.data.TypeRuntimeServer;
import org.eclipse.jst.ws.internal.ui.common.UIUtils;
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.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.command.internal.env.ui.widgets.SimpleWidgetDataContributor;
import org.eclipse.wst.command.internal.env.ui.widgets.WidgetDataEvents;
import org.eclipse.wst.command.internal.provisional.env.core.common.MessageUtils;
import org.eclipse.wst.command.internal.provisional.env.core.common.SimpleStatus;
import org.eclipse.wst.command.internal.provisional.env.core.common.Status;
import org.eclipse.wst.command.internal.provisional.env.core.context.ResourceContext;


public class ServerWizardWidget extends SimpleWidgetDataContributor
{   
  private WebServiceClientTypeWidget clientWidget_;
  private PreferencesSelectionWidget preferencesWidget_;
  private Listener                   statusListener_;
  private TypeRuntimeServer          ids_;
  private LabelsAndIds               labelIds_;
  private boolean                    displayPreferences_;
  
  /*CONTEXT_ID PWPR0001 for the Project Page*/
  private String INFOPOP_PWPR_PAGE = "PWPR0001";
  
  /*CONTEXT_ID PWPR0005 for the Generate Proxy check box of the Project Page*/
  private String INFOPOP_PWPR_CHECKBOX_GENERATE_PROXY = "PWPR0005";
  private Button  generateProxy_;
  
  /*CONTEXT_ID PWPR0010 for the Web Service Type combo box of the Project Page*/
  private String INFOPOP_PWPR_COMBO_TYPE = "PWPR0010";
  private Combo  webserviceType_;
  
  /*CONTEXT_ID PWPR0011 for the Wizard Scenario Service group of the Project Page*/
  private String INFOPOP_PWPR_GROUP_SCENARIO_SERVICE = "PWPR0011";
  private Button startService_;
  
  /*CONTEXT_ID PWPR0009 for the Start Web Project check box check box of the Project Page*/
  private String INFOPOP_PWPR_CHECKBOX_START_WEB_PROJECT = "PWPR0009";
  
  /*CONTEXT_ID PWPR0013 for the test service checkbox of the project page*/  
  private String INFOPOP_PWPR_CHECKBOX_TEST_SERVICE = "PWPR0013";
  private Button testService_;
  
  /*CONTEXT_ID PWPR0014 for the monitor service checkbox of the projec page*/
  private String INFOPOP_PWPR_CHECKBOX_MONITOR_SERVICE = "PWPR0014";
  private Button monitorService;
  
  /*CONTEXT_ID PWPR0012 for the Launch UDDI check box of the Project Page*/
  private String INFOPOP_PWPR_CHECKBOX_LAUNCH_WS = "PWPR0012";
  private Button launchUddi_;
  
  public ServerWizardWidget( boolean displayPreferences )
  {
    displayPreferences_ = displayPreferences;  
  }
  
  public WidgetDataEvents addControls( Composite parent, Listener statusListener)
  {
    String       pluginId = "org.eclipse.jst.ws.consumption.ui";
    String       createPluginId = "org.eclipse.jst.ws.creation.ui";
    MessageUtils msgUtils = new MessageUtils( pluginId + ".plugin", this );
    UIUtils      utils    = new UIUtils( msgUtils, createPluginId );
    
    statusListener_ = statusListener;
    
  	PlatformUI.getWorkbench().getHelpSystem().setHelp( parent, pluginId + "." +  INFOPOP_PWPR_PAGE );
  	
  	Composite serverComposite = utils.createComposite( parent, 1 );
  	
  	Group serviceGroup = utils.createGroup( serverComposite, "GROUP_SCENARIO_SERVICE",
  	                                        "TOOLTIP_PWPR_GROUP_SCENARIO_SERVICE", 
  	                                        INFOPOP_PWPR_GROUP_SCENARIO_SERVICE,
											2, 10, 10);
  	
  	
  	// Create webservice combo box.
    webserviceType_ = utils.createCombo( serviceGroup, "LABEL_WEBSERVICETYPE",
                                         "TOOLTIP_PWPR_COMBO_TYPE",
                                         INFOPOP_PWPR_COMBO_TYPE, 
										 SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY );
    webserviceType_.addListener( SWT.Modify, statusListener );
    
    Composite buttonsGroup = utils.createComposite( serviceGroup, 1 );
    GridData  buttonGrid   = new GridData();
    buttonGrid.horizontalSpan = 2;
    buttonsGroup.setLayoutData( buttonGrid );
    
    // Create start service check box.
    startService_ = utils.createCheckbox( buttonsGroup, "BUTTON_START_WEB_PROJECT",
                                          "TOOLTIP_PWPR_CHECKBOX_START_WEB_PROJECT",
                                          INFOPOP_PWPR_CHECKBOX_START_WEB_PROJECT );
    startService_.addSelectionListener( new SelectionAdapter()
                                        {
                                          public void widgetSelected( SelectionEvent evt )
                                          {
                                            handleStartPressed();
                                          }
                                        });
    
    launchUddi_ = utils.createCheckbox( buttonsGroup, "BUTTON_WS_PUBLISH",
                                        "TOOLTIP_PWPR_CHECKBOX_LAUNCH_WS",
                                        INFOPOP_PWPR_CHECKBOX_LAUNCH_WS );
    
    Composite proxyComposite = utils.createComposite( serverComposite, 1, 5, 0 );
    
    // Create generate proxy check box.
    generateProxy_ = utils.createCheckbox( proxyComposite, "BUTTON_GENERATE_PROXY",
                                           "TOOLTIP_PWPR_CHECKBOX_GENERATE_PROXY",
                                           INFOPOP_PWPR_CHECKBOX_GENERATE_PROXY );
    generateProxy_.addSelectionListener( new SelectionAdapter()
                                         {
                                           public void widgetSelected( SelectionEvent evt )
                                           {
                                             clientWidget_.enableWidget( generateProxy_.getSelection() );
                                           }
                                         });
    
    // Create client selection widget.
    clientWidget_ = new WebServiceClientTypeWidget();
    clientWidget_.addControls( serverComposite, statusListener );
    
    Composite testGroup = utils.createComposite(serverComposite,1);
    
    //  Create test service check box.
    testService_ = utils.createCheckbox( testGroup, "CHECKBOX_TEST_WEBSERVICE",
                                         "TOOLTIP_PWPR_CHECKBOX_TEST_SERVICE",
                                         INFOPOP_PWPR_CHECKBOX_TEST_SERVICE );

    monitorService = utils.createCheckbox( testGroup, "CHECKBOX_MONITOR_WEBSERVICE",
                                         "TOOLTIP_PWPR_CHECKBOX_MONITOR_SERVICE",
                                         INFOPOP_PWPR_CHECKBOX_MONITOR_SERVICE );
    
    if( displayPreferences_ )
    {
      // Create the preferences widgets.
      preferencesWidget_ = new PreferencesSelectionWidget();
      preferencesWidget_.addControls( serverComposite, statusListener );
    }
    
    return this;
  }

  private void handleStartPressed()
  {
    boolean enabled = startService_.getSelection();
    
    testService_.setEnabled( enabled );
    monitorService.setEnabled(enabled);
    launchUddi_.setEnabled( enabled );
    generateProxy_.setEnabled( enabled );
    clientWidget_.enableWidget( getGenerateProxy().booleanValue() );
  }
  
  public void setClientTypeRuntimeServer( TypeRuntimeServer ids )
  {
    clientWidget_.setTypeRuntimeServer( ids );
  }
  
  public TypeRuntimeServer getClientTypeRuntimeServer()
  {
    return clientWidget_.getTypeRuntimeServer();  
  }
  
  public void setServiceTypeRuntimeServer( TypeRuntimeServer ids )
  {
    LabelsAndIds                        labelIds   = WebServiceRuntimeExtensionUtils.getServiceTypeLabels();
	//rskreg
    int                                 selection  = 0;
    String[]                            serviceIds = labelIds.getIds_();
    String                              selectedId = ids.getTypeId();
    
    webserviceType_.removeListener( SWT.Modify, statusListener_ );
    webserviceType_.setItems( labelIds.getLabels_() );
        
    // Now find the selected one.
    for( int index = 0; index < serviceIds.length; index++ )
    {
      if( selectedId.equals( serviceIds[index ]) )
      {
        selection = index;
        break;
      }
    }
    
    webserviceType_.select( selection );
    webserviceType_.addListener( SWT.Modify, statusListener_ );
    ids_      = ids;  
    labelIds_ = labelIds;
  }
  
  public TypeRuntimeServer getServiceTypeRuntimeServer()
  {
    int selectionIndex = webserviceType_.getSelectionIndex();
    
    ids_.setTypeId( labelIds_.getIds_()[selectionIndex] );
    
    return ids_;  
  }
  
  public Boolean getStartService()
  {
    return new Boolean( startService_.getSelection() );  
  }
  
  public void setStartService( Boolean value )
  {
    startService_.setSelection( value.booleanValue() );
  }

  public Boolean getTestService()
  {
    return new Boolean( testService_.getSelection() && startService_.getSelection() );
  }
  
  public void setTestService( Boolean value )
  {
    testService_.setSelection( value.booleanValue() );  
  }
  
  public Boolean getMonitorService()
  {
    return new Boolean(monitorService.getSelection() && startService_.getSelection());
  }
  
  public void setMonitorService(Boolean value)
  {
    monitorService.setSelection(value.booleanValue());
  }

  public Boolean getPublishService()
  {
    return new Boolean( launchUddi_.getSelection() && startService_.getSelection() );
  }
  
  public void setPublishService( Boolean value )
  {
    launchUddi_.setSelection( value.booleanValue() );  
  }

  public Boolean getGenerateProxy()
  {
    return new Boolean( generateProxy_.getSelection() && startService_.getSelection() );
  }
  
  public void setGenerateProxy( Boolean value )
  {
    generateProxy_.setSelection( value.booleanValue() );  
  }

  public ResourceContext getResourceContext()
  {
    return preferencesWidget_.getResourceContext(); 
  }

  public void setResourceContext( ResourceContext context )
  {
    preferencesWidget_.setResourceContext( context );
  }

  public void internalize()
  {
    handleStartPressed();  
  }
  
  public Status getStatus()
  {
    Status status = new SimpleStatus( "" );
    
    // If the webservice has not been selected then user can not move
    // forward to the next page.
    if( webserviceType_.getText().equals("") )
    {
      status = new SimpleStatus( "", "", Status.ERROR );
    }
    
    return status;
  }
}
