/*******************************************************************************
 * Copyright (c) 2003, 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
 *******************************************************************************/
/*
 * Created on Nov 10, 2003
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 */
package org.eclipse.jst.j2ee.internal.wizard;

import java.io.File;

import org.eclipse.core.resources.IProject;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jst.j2ee.datamodel.properties.IJ2EEComponentCreationDataModelProperties;
import org.eclipse.jst.j2ee.datamodel.properties.IJavaComponentCreationDataModelProperties;
import org.eclipse.jst.j2ee.internal.plugin.J2EEUIMessages;
import org.eclipse.jst.j2ee.internal.project.J2EECreationResourceHandler;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
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.common.componentcore.datamodel.properties.IComponentCreationDataModelProperties;
import org.eclipse.wst.common.frameworks.datamodel.DataModelPropertyDescriptor;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.frameworks.internal.DoNotUseMeThisWillBeDeletedPost15;
import org.eclipse.wst.common.frameworks.internal.datamodel.ui.DataModelWizardPage;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.core.ServerCore;
import org.eclipse.wst.server.ui.ServerUIUtil;


/**
 * This has been slated for removal post WTP 1.5. Do not use this class/interface
 * 
 * @deprecated
 */
public abstract class J2EEComponentCreationWizardPage extends DataModelWizardPage implements IJ2EEComponentCreationDataModelProperties, DoNotUseMeThisWillBeDeletedPost15{

    private static final boolean isWindows = SWT.getPlatform().toLowerCase().startsWith("win"); //$NON-NLS-1$
    protected static final String MODULE_VERSION = J2EEUIMessages.MODULE_VERSION_LABEL;
    protected NewModuleGroup projectNameGroup;
    protected Composite advancedComposite;
    protected Button advancedButton;
    protected boolean showAdvanced = false;
    protected AdvancedSizeController advancedController;
    protected boolean advancedControlsBuilt = false;
    protected ServerEarAndStandaloneGroup earGroup;
    protected Combo serverTargetCombo;
    protected Text moduleNameText = null;
    protected Text locationPathField = null;
    protected Button browseButton = null;
	protected Button supportMultipleModules = null;
    protected Combo projectNameCombo = null;
    protected Text sourceFolderNameText = null;
    
    private static final int SIZING_TEXT_FIELD_WIDTH = 305;
//    private static final String NEW_LABEL_UI = J2EEUIMessages.getResourceString(J2EEUIMessages.NEW_THREE_DOTS_E); //$NON-NLS-1$
    private static final String MODULE_NAME_UI = J2EEUIMessages.getResourceString(J2EEUIMessages.NAME_LABEL); //$NON-NLS-1$
    private String defBrowseButtonLabel = J2EEUIMessages.getResourceString(J2EEUIMessages.BROWSE_LABEL); //$NON-NLS-1$
    private static final String defDirDialogLabel = "Directory"; //$NON-NLS-1$

    /**
     *  This type is responsible for setting the Shell size based on the showAdvanced flag. It will
     * track the original size of the Shell even if the user resizes it. One problem that we may
     * face is that the Shell size could change by the framework prior to the Shell being made
     * visible but the page will already get an enter call. This means that we will need to set the
     * Shell size based on the showAdvanced flag when the Shell resize event is called and the Shell
     * is visible.
     */
    private class AdvancedSizeController implements ControlListener {
        private int advancedHeight = -1;
        private Point originalSize;
        private boolean ignoreShellResize = false;

        private AdvancedSizeController(Shell aShell) {
            originalSize = aShell.getSize();
            aShell.addControlListener(this);
        }

        public void controlMoved(ControlEvent e) {
            //do nothing
        }

        public void controlResized(ControlEvent e) {
            if (!ignoreShellResize) {
                Control control = (Control) e.getSource();
                if (control.isVisible()) {
                    originalSize = control.getSize();
                    if (advancedHeight == -1)
                        setShellSizeForAdvanced();
                }
            }
        }

        protected void resetOriginalShellSize() {
            setShellSize(originalSize.x, originalSize.y);
        }

        private void setShellSize(int x, int y) {
            ignoreShellResize = true;
            try {
                getShell().setSize(x, y);
            } finally {
                ignoreShellResize = false;
            }
        }

        protected void setShellSizeForAdvanced() {
            int height = calculateAdvancedShellHeight();
            if (height != -1)
                setShellSize(getShell().getSize().x, height);
        }

        private int calculateAdvancedShellHeight() {
            Point advancedCompSize = advancedComposite.getSize();
            if (advancedCompSize.x == 0)
                return -1;
            int height = computeAdvancedHeight();
            if (!showAdvanced && height != -1)
                height = height - advancedComposite.getSize().y;
            return height;
        }

        /*
         * Compute the height with the advanced section showing. @return
         */
        private int computeAdvancedHeight() {
            if (advancedHeight == -1) {
                Point controlSize = getControl().getSize();
                if (controlSize.x != 0) {
                	Point pageSize = getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT);
                    int minHeight = originalSize.y - controlSize.y;
                    advancedHeight = pageSize.y + minHeight;
                }
            }
            return advancedHeight;
        }
    }
    
    public J2EEComponentCreationWizardPage(IDataModel dataModel, String pageName) {
        super(dataModel, pageName);
    }
    
    protected Composite createTopLevelComposite(Composite parent) {
        Composite top = new Composite(parent, SWT.NONE);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(top, getInfopopID());
        top.setLayout(new GridLayout());
        top.setData(new GridData(GridData.FILL_BOTH));
        Composite composite = new Composite(top, SWT.NONE);
        GridLayout layout = new GridLayout(3, false);
        composite.setLayout(layout);
        createModuleGroup(composite);
        Composite detail = new Composite(top, SWT.NONE);
        detail.setLayout(new GridLayout());
        detail.setData(new GridData(GridData.FILL_BOTH));
        createAdvancedComposite(detail);
        return top;
    }

    protected Composite createAdvancedComposite(Composite parent) {
        advancedControlsBuilt = true;
        advancedButton = new Button(parent, SWT.TOGGLE);
        setAdvancedLabelText();
        final Cursor hand = new Cursor(advancedButton.getDisplay(), SWT.CURSOR_HAND);
        advancedButton.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                hand.dispose();
            }
        });
        advancedComposite = new Composite(parent, SWT.NONE);
        //toggleAdvanced(false);
        GridLayout layout = new GridLayout(3, false);
        GridData data = new GridData();
        advancedComposite.setData(data);
        advancedComposite.setLayout(layout);
        advancedButton.addSelectionListener(new SelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                toggleAdvanced(true);
            }

            public void widgetDefaultSelected(SelectionEvent e) {
                //do nothing
            }
        });
        advancedButton.addListener(SWT.MouseHover, new Listener() {
            public void handleEvent(Event event) {
                if (event.type == SWT.MouseHover)
                    advancedButton.setCursor(hand);
            }
        });
        addToAdvancedComposite(advancedComposite);
        return advancedComposite;
    }
    
    protected void createModuleGroup(Composite parent) {
        createProjectNameGroup(parent);
        createProjectLocationGroup(parent);
    }
    
    /**
     *  
     */
    private void createProjectNameGroup(Composite parent) {
        // set up project name label
        Label projectNameLabel = new Label(parent, SWT.NONE);
        projectNameLabel.setText(MODULE_NAME_UI);
        GridData data = new GridData();
        projectNameLabel.setLayoutData(data);
        // set up project name entry field
        moduleNameText = new Text(parent, SWT.BORDER);
        data = new GridData(GridData.FILL_HORIZONTAL);
        data.widthHint = SIZING_TEXT_FIELD_WIDTH;
        moduleNameText.setLayoutData(data);
        new Label(parent, SWT.NONE); // pad
        synchHelper.synchText(moduleNameText, COMPONENT_NAME, new Control[]{projectNameLabel});
        moduleNameText.setFocus();
    }

    /**
     *  
     */
    private void createProjectLocationGroup(Composite parent) {
        //      set up location path label
        Label locationPathLabel = new Label(parent, SWT.NONE);
        locationPathLabel.setText(J2EEUIMessages.getResourceString(J2EEUIMessages.PROJECT_LOC_LBL));
        GridData data = new GridData();
        locationPathLabel.setLayoutData(data);
        // set up location path entry field
        locationPathField = new Text(parent, SWT.BORDER | SWT.READ_ONLY);
        data = new GridData(GridData.FILL_HORIZONTAL);
        data.widthHint = SIZING_TEXT_FIELD_WIDTH;
        locationPathField.setLayoutData(data);
        // set up browse button
        browseButton = new Button(parent, SWT.PUSH);
        browseButton.setText(defBrowseButtonLabel);
        browseButton.setLayoutData((new GridData(GridData.FILL_HORIZONTAL)));
        browseButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                handleLocationBrowseButtonPressed();
            }
        });
        browseButton.setEnabled(true);
        locationPathField.setEditable(true);
        synchHelper.synchText(locationPathField, LOCATION, null);
    }
    /**
     * Open an appropriate directory browser
     */
    protected void handleLocationBrowseButtonPressed() {
        DirectoryDialog dialog = new DirectoryDialog(locationPathField.getShell());
        dialog.setMessage(defDirDialogLabel);
        String dirName = getDataModel().getStringProperty(LOCATION);
        if ((dirName != null) && (dirName.length() != 0)) {
            File path = new File(dirName);
            if (path.exists()) {
                dialog.setFilterPath(dirName);
            }
        }
        String selectedDirectory = dialog.open();
        if (selectedDirectory != null) {
            getDataModel().setProperty(LOCATION, selectedDirectory);
        }
    }

    protected void addToAdvancedComposite(Composite advanced) {
        createServerTargetComposite(advanced);
        createVersionComposite(advanced);
        createServerEarAndStandaloneGroup(advanced);
    }


    protected void createServerTargetComposite(Composite parent) {
        Label label = new Label(parent, SWT.NONE);
        label.setText(J2EEUIMessages.getResourceString(J2EEUIMessages.TARGET_RUNTIME_LBL));
        serverTargetCombo = new Combo(parent, SWT.BORDER | SWT.READ_ONLY);
        serverTargetCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        Button newServerTargetButton = new Button(parent, SWT.NONE);
        newServerTargetButton.setText(J2EEUIMessages.getResourceString(J2EEUIMessages.NEW_THREE_DOTS_E));
        newServerTargetButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                if(!J2EEComponentCreationWizardPage.launchNewRuntimeWizard(getShell(), model)){
                	setErrorMessage(J2EECreationResourceHandler.ServerTargetDataModel_UI_9);
                }
            }
        });
        Control[] deps = new Control[]{label, newServerTargetButton};
        synchHelper.synchCombo(serverTargetCombo, RUNTIME_TARGET_ID, deps);
        if(serverTargetCombo.getSelectionIndex() == -1 && serverTargetCombo.getVisibleItemCount() != 0)
            serverTargetCombo.select(0);
    }

    protected void createServerEarAndStandaloneGroup(Composite parent) {
        earGroup = new ServerEarAndStandaloneGroup(parent, getDataModel(), synchHelper);
    }
    /**@deprecated 
	 * If this method is not used it should be removed at a later time, marking as deprecated
	 * Warning cleanup 12/07/2005
	 */
	private void createProjectsComboGroup(Composite parent) {
		// set up project name label
		
		Label projectNameLabel = new Label(parent, SWT.NONE);
		projectNameLabel.setText(J2EEUIMessages.getResourceString(J2EEUIMessages.MODULES_DEPENDENCY_PAGE_TABLE_PROJECT));
		
		// set up project name entry field
		projectNameCombo = new Combo(parent, SWT.NONE | SWT.READ_ONLY);
		projectNameCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		projectNameCombo.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				String projectName = projectNameCombo.getText();

				//update the project location with this information, make it readable
				//update Server info RUNTIME_TARGET_ID, make it readable
				if (projectName!=null && projectName.length()!=0) {
					IProject project = ProjectUtilities.getProject(projectName);
					if (project !=null) {
						IRuntime runtime = ServerCore.getProjectProperties(project).getRuntimeTarget();
						if (runtime != null){
							//serverTargetText.setText(runtime.getName());
							synchHelper.getDataModel().setProperty(IJavaComponentCreationDataModelProperties.RUNTIME_TARGET_ID, runtime.getName());
						}
						synchHelper.getDataModel().setProperty(IComponentCreationDataModelProperties.PROJECT_NAME, projectName);
						synchHelper.getDataModel().setProperty(IComponentCreationDataModelProperties.LOCATION, project.getLocation().toOSString());
					}
				}				

			}
		});
	}

	/**
	 * @return
	 */
//	private IProject getSelectedProject() {
//		IWorkbenchWindow window = Workbench.getInstance().getActiveWorkbenchWindow();
//		if (window == null)
//			return null;
//		ISelection selection = window.getSelectionService().getSelection();
//		if (selection == null || !(selection instanceof StructuredSelection))
//			return null;
//		StructuredSelection stucturedSelection = (StructuredSelection) selection;
//		Object obj = stucturedSelection.getFirstElement();
//		if (obj instanceof IProject)
//			return (IProject) obj;
//		return null;
//	}
	
    protected String[] getValidationPropertyNames() {
        return new String[]{IComponentCreationDataModelProperties.PROJECT_NAME, RUNTIME_TARGET_ID, COMPONENT_VERSION, COMPONENT_NAME, LOCATION, EAR_COMPONENT_NAME, ADD_TO_EAR, JAVASOURCE_FOLDER };    }

    protected void createSourceFolderComposite(Composite parent) {
        
		Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.horizontalSpan = 3;
		separator.setLayoutData(gd);
		
        Label label = new Label(parent, SWT.NONE);
        label.setText(getSourceFolderLabel());
        GridData data = new GridData();      
        label.setLayoutData(data);
        // set up project name entry field
        sourceFolderNameText = new Text(parent, SWT.BORDER);
        data = new GridData(GridData.FILL_HORIZONTAL);
        data.widthHint = SIZING_TEXT_FIELD_WIDTH;
        sourceFolderNameText.setLayoutData(data);
        new Label(parent, SWT.NONE); // pad
        synchHelper.synchText(sourceFolderNameText, JAVASOURCE_FOLDER, null);
    }	

    
    protected void createVersionComposite(Composite parent) {
        createVersionComposite(parent, getVersionLabel(), COMPONENT_VERSION);
    }

    protected String getVersionLabel() {
        return J2EEUIMessages.getResourceString(J2EEUIMessages.MODULE_VERSION_LABEL);
    }

    protected String getSourceFolderLabel() {
        return J2EEUIMessages.getResourceString(J2EEUIMessages.SOURCEFOLDER);
    }
    
    public void dispose() {
        super.dispose();
        if (earGroup != null)
            earGroup.dispose();
        if (projectNameGroup != null)
            projectNameGroup.dispose();
    }
    
    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.wst.common.frameworks.internal.ui.wizard.WTPWizardPage#enter()
     */
    protected void enter() {
        if (advancedControlsBuilt) {
            if (isFirstTimeToPage)
                initializeAdvancedController();
            if (isWindows) {
                advancedController.setShellSizeForAdvanced();
            }
        }
        super.enter();
    }

    private void initializeAdvancedController() {
        advancedController = new AdvancedSizeController(getShell());
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.wst.common.frameworks.internal.ui.wizard.WTPWizardPage#exit()
     */
    protected void exit() {
        if (advancedControlsBuilt && isWindows && advancedController!=null) {
            advancedController.resetOriginalShellSize();
        }
        super.exit();
    }
    
    /*
     * (non-Javadoc)
     * @see org.eclipse.wst.common.frameworks.internal.ui.wizard.WTPWizardPage#storeDefaultSettings()
     */
    public void storeDefaultSettings() {
        super.storeDefaultSettings();
        if (advancedControlsBuilt) {
            IDialogSettings settings = getDialogSettings();
            if (settings != null)
                settings.put(getShowAdvancedKey(), showAdvanced);
        }
    }

    protected String getShowAdvancedKey() {
        return getClass().getName() + "_SHOW_ADVANCED"; //$NON-NLS-1$
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.wst.common.frameworks.internal.ui.wizard.WTPWizardPage#restoreDefaultSettings()
     */
    protected void restoreDefaultSettings() {
        super.restoreDefaultSettings();
        if (advancedControlsBuilt) {
            IDialogSettings settings = getDialogSettings();
            if (settings != null)
                showAdvanced = !settings.getBoolean(getShowAdvancedKey());
            advancedButton.setSelection(!showAdvanced); //set opposite b/c toggleAdvanced(boolean)
            // will flip it
            toggleAdvanced(false);
        }
    }

    /**
     * @param advancedLabel
     */
    private void setAdvancedLabelText() {
        if (advancedControlsBuilt) {
            if (showAdvanced)
                advancedButton.setText(J2EEUIMessages.getResourceString("J2EEProjectCreationPage_UI_0")); //$NON-NLS-1$
            else
                advancedButton.setText(J2EEUIMessages.getResourceString("J2EEProjectCreationPage_UI_1")); //$NON-NLS-1$
        }
    }

    /**
     * @param advancedLabel
     */
    protected void toggleAdvanced(boolean setSize) {
        if (advancedControlsBuilt) {
            showAdvanced = !showAdvanced;
            advancedComposite.setVisible(showAdvanced);
            setAdvancedLabelText();
            if (setSize && isWindows) {
                if (advancedControlsBuilt) {
                    if (advancedController == null)
                        initializeAdvancedController();
                    if (isWindows) {
                        advancedController.setShellSizeForAdvanced();
                    }
                }
//                advancedController.setShellSizeForAdvanced();
            }   
        }
    }

    protected void createVersionComposite(Composite parent, String labelText, String versionProp) {
        Label label = new Label(parent, SWT.NONE);
        label.setText(labelText);
        Combo versionCombo = new Combo(parent, SWT.BORDER | SWT.READ_ONLY);
        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        gridData.widthHint = 305;
        versionCombo.setLayoutData(gridData);
        Control[] deps = new Control[]{label};
        synchHelper.synchCombo(versionCombo, versionProp, deps);
        if (versionCombo.getSelectionIndex() == -1) {
	        String[] items = versionCombo.getItems();
	        if (items != null && items.length > 0)
	            versionCombo.select(items.length - 1);
        }
        new Label(parent, SWT.NONE); //pad
    }   
    

    
    public static boolean launchNewRuntimeWizard(Shell shell, IDataModel model) {
        DataModelPropertyDescriptor[] preAdditionDescriptors = model.getValidPropertyDescriptors(RUNTIME_TARGET_ID);
        boolean isOK = ServerUIUtil.showNewRuntimeWizard(shell, "", "");  //$NON-NLS-1$  //$NON-NLS-2$
        if (isOK && model != null) {

            DataModelPropertyDescriptor[] postAdditionDescriptors = model.getValidPropertyDescriptors(RUNTIME_TARGET_ID);
            Object[] preAddition = new Object[preAdditionDescriptors.length];
            for (int i = 0; i < preAddition.length; i++) {
                preAddition[i] = preAdditionDescriptors[i].getPropertyValue();
            }
            Object[] postAddition = new Object[postAdditionDescriptors.length];
            for (int i = 0; i < postAddition.length; i++) {
                postAddition[i] = postAdditionDescriptors[i].getPropertyValue();
            }
            Object newAddition = ProjectUtilities.getNewObject(preAddition, postAddition);

            model.notifyPropertyChange(RUNTIME_TARGET_ID, IDataModel.VALID_VALUES_CHG);
            if (newAddition != null)
                model.setProperty(RUNTIME_TARGET_ID, newAddition);
            else
            	return false;
        }
        return isOK;
    }   

}
