/*******************************************************************************
 * Copyright (c) 2003, 2007 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.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jst.j2ee.datamodel.properties.IJ2EEComponentCreationDataModelProperties;
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.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);
    }


	
    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;
    }   

}
