/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.eclipse.org/org/documents/epl-v10.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.ide.eclipse.adt.launch.junit;

import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.launch.MainLaunchConfigTab;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.ProjectChooserHelper;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.junit.Messages;
import org.eclipse.jdt.internal.junit.launcher.ITestKind;
import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants;
import org.eclipse.jdt.internal.junit.launcher.JUnitMigrationDelegate;
import org.eclipse.jdt.internal.junit.launcher.TestKindRegistry;
import org.eclipse.jdt.internal.junit.launcher.TestSelectionDialog;
import org.eclipse.jdt.internal.junit.ui.JUnitMessages;
import org.eclipse.jdt.internal.junit.util.LayoutUtil;
import org.eclipse.jdt.internal.junit.util.TestSearchEngine;
import org.eclipse.jdt.internal.ui.wizards.TypedElementSelectionValidator;
import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.ui.JavaElementComparator;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.StandardJavaElementContentProvider;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.dialogs.SelectionDialog;

import java.lang.reflect.InvocationTargetException;

/**
 * The launch config UI tab for Android JUnit
 * <p/>
 * Based on org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationTab
 */
@SuppressWarnings("restriction")
public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurationTab {

    // Project UI widgets
    private Label mProjLabel;
    private Text mProjText;
    private Button mProjButton;
    
    // Test class UI widgets
    private Text mTestText;
    private Button mSearchButton;
    private String mOriginalTestMethodName;
    private Label mTestMethodLabel;
    private Text mContainerText;
    private IJavaElement mContainerElement;
    private final ILabelProvider mJavaElementLabelProvider = new JavaElementLabelProvider();

    private Button mContainerSearchButton;
    private Button mTestContainerRadioButton;
    private Button mTestRadioButton;
    private Label mTestLabel; 

    // Android specific members
    private Image mTabIcon = null;
    private Combo mInstrumentationCombo;
    private static final String EMPTY_STRING = ""; //$NON-NLS-1$
    private String[] mInstrumentations = null;
    private ProjectChooserHelper mProjectChooserHelper;

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent) {
        mProjectChooserHelper = new ProjectChooserHelper(parent.getShell());

        Composite comp = new Composite(parent, SWT.NONE);
        setControl(comp);

        GridLayout topLayout = new GridLayout();
        topLayout.numColumns = 3;
        comp.setLayout(topLayout);      
        
        createSingleTestSection(comp);
        createTestContainerSelectionGroup(comp);
        
        createSpacer(comp);
        
        createInstrumentationGroup(comp);

        createSpacer(comp);
        
        Dialog.applyDialogFont(comp);
        // TODO: add help link here when available
        //PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), 
        //      IJUnitHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_JUNIT_MAIN_TAB);
        validatePage();
    }


    private void createSpacer(Composite comp) {
        Label label = new Label(comp, SWT.NONE);
        GridData gd = new GridData();
        gd.horizontalSpan = 3;
        label.setLayoutData(gd);
    }
    
    private void createSingleTestSection(Composite comp) {
        mTestRadioButton = new Button(comp, SWT.RADIO);
        mTestRadioButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_oneTest); 
        GridData gd = new GridData();
        gd.horizontalSpan = 3;
        mTestRadioButton.setLayoutData(gd); 
        mTestRadioButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (mTestRadioButton.getSelection()) {
                    testModeChanged();
                }    
            }
        });
        
        mProjLabel = new Label(comp, SWT.NONE);
        mProjLabel.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_project); 
        gd = new GridData();
        gd.horizontalIndent = 25;
        mProjLabel.setLayoutData(gd);
        
        mProjText = new Text(comp, SWT.SINGLE | SWT.BORDER);
        mProjText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        mProjText.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent evt) {
                validatePage();
                updateLaunchConfigurationDialog();              
                mSearchButton.setEnabled(mTestRadioButton.getSelection() && 
                        mProjText.getText().length() > 0);
            }
        });
            
        mProjButton = new Button(comp, SWT.PUSH);
        mProjButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_browse); 
        mProjButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent evt) {
                handleProjectButtonSelected();
            }
        });
        setButtonGridData(mProjButton);
        
        mTestLabel = new Label(comp, SWT.NONE);
        gd = new GridData();
        gd.horizontalIndent = 25;
        mTestLabel.setLayoutData(gd);
        mTestLabel.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_test); 
        
    
        mTestText = new Text(comp, SWT.SINGLE | SWT.BORDER);
        mTestText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        mTestText.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent evt) {
                validatePage();
                updateLaunchConfigurationDialog();
            }
        });
        
        mSearchButton = new Button(comp, SWT.PUSH);
        mSearchButton.setEnabled(mProjText.getText().length() > 0);
        mSearchButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_search); 
        mSearchButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent evt) {
                handleSearchButtonSelected();
            }
        });
        setButtonGridData(mSearchButton);
        
        new Label(comp, SWT.NONE);
        
        mTestMethodLabel = new Label(comp, SWT.NONE);
        mTestMethodLabel.setText("");  //$NON-NLS-1$
        gd = new GridData();
        gd.horizontalSpan = 2;
        mTestMethodLabel.setLayoutData(gd);
    }

    private void createTestContainerSelectionGroup(Composite comp) {
        mTestContainerRadioButton = new Button(comp, SWT.RADIO);
        mTestContainerRadioButton.setText(
                JUnitMessages.JUnitLaunchConfigurationTab_label_containerTest); 
        GridData gd = new GridData();
        gd.horizontalSpan = 3;
        mTestContainerRadioButton.setLayoutData(gd);
        mTestContainerRadioButton.addSelectionListener(new SelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                if (mTestContainerRadioButton.getSelection()) {
                    testModeChanged();
                }    
            }
            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });
        
        mContainerText = new Text(comp, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
        gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalIndent = 25;
        gd.horizontalSpan = 2;
        mContainerText.setLayoutData(gd);
        mContainerText.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent evt) {
                updateLaunchConfigurationDialog();
            }
        });
        
        mContainerSearchButton = new Button(comp, SWT.PUSH);
        mContainerSearchButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_search); 
        mContainerSearchButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent evt) {
                handleContainerSearchButtonSelected();
            }
        });
        setButtonGridData(mContainerSearchButton);  
    }
    
    private void createInstrumentationGroup(Composite comp) {
        Label loaderLabel = new Label(comp, SWT.NONE);
        loaderLabel.setText("Instrumentation runner:");
        GridData gd = new GridData();
        gd.horizontalIndent = 0;
        loaderLabel.setLayoutData(gd);
        
        mInstrumentationCombo = new Combo(comp, SWT.DROP_DOWN | SWT.READ_ONLY);
        gd = new GridData(GridData.FILL_HORIZONTAL);
        mInstrumentationCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        mInstrumentationCombo.clearSelection();
        mInstrumentationCombo.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                validatePage();
                updateLaunchConfigurationDialog();
            }
        });
    }

    private void handleContainerSearchButtonSelected() {
        IJavaElement javaElement = chooseContainer(mContainerElement);
        if (javaElement != null) {
            setContainerElement(javaElement);
        }    
    }

    private void setContainerElement(IJavaElement javaElement) {
        mContainerElement = javaElement;
        mContainerText.setText(getPresentationName(javaElement));
        validatePage();
        updateLaunchConfigurationDialog();
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
     */
    public void initializeFrom(ILaunchConfiguration config) {
        String projectName = updateProjectFromConfig(config);
        String containerHandle = EMPTY_STRING;
        try {
            containerHandle = config.getAttribute(
                    JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, EMPTY_STRING);
        } catch (CoreException ce) {
            // ignore
        }
        
        if (containerHandle.length() > 0) {
            updateTestContainerFromConfig(config);
        } else {
            updateTestTypeFromConfig(config);
        }    

        IProject proj = mProjectChooserHelper.getAndroidProject(projectName);
        loadInstrumentations(proj);
        updateInstrumentationFromConfig(config);
        
        validatePage();
    }

    private void updateInstrumentationFromConfig(ILaunchConfiguration config) {
        boolean found = false;
        try {
            String currentInstrumentation = config.getAttribute(
                    AndroidJUnitLaunchConfigDelegate.ATTR_INSTR_NAME, EMPTY_STRING);
            if (mInstrumentations != null) {
                // look for the name of the instrumentation in the combo.
                for (int i = 0; i < mInstrumentations.length; i++) {
                   if (currentInstrumentation.equals(mInstrumentations[i])) {
                       found = true;
                       mInstrumentationCombo.select(i);
                       break;
                    }
                }
            }    
        } catch (CoreException ce) {
            // ignore
        }
        if (!found) {
            mInstrumentationCombo.clearSelection();
        }    
    }

    private String updateProjectFromConfig(ILaunchConfiguration config) {
        String projectName = EMPTY_STRING;
        try {
            projectName = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME,
                    EMPTY_STRING);
        } catch (CoreException ce) {
            // ignore
        }
        mProjText.setText(projectName);
        return projectName;
    }

    private void updateTestTypeFromConfig(ILaunchConfiguration config) {
        String testTypeName = EMPTY_STRING;
        mOriginalTestMethodName = EMPTY_STRING;
        try {
            testTypeName = config.getAttribute(
                    IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, ""); //$NON-NLS-1$
            mOriginalTestMethodName = config.getAttribute(
                    JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME, ""); //$NON-NLS-1$
        } catch (CoreException ce) {
            // ignore
        }
        mTestRadioButton.setSelection(true);
        setEnableSingleTestGroup(true);
        setEnableContainerTestGroup(false);     
        mTestContainerRadioButton.setSelection(false);
        mTestText.setText(testTypeName);
        mContainerText.setText(EMPTY_STRING); 
        setTestMethodLabel(mOriginalTestMethodName);
    }

    private void setTestMethodLabel(String testMethodName) {
        if (!EMPTY_STRING.equals(testMethodName)) {
            mTestMethodLabel.setText(
                    JUnitMessages.JUnitLaunchConfigurationTab_label_method + 
                    mOriginalTestMethodName); 
        } else {
            mTestMethodLabel.setText(EMPTY_STRING);
        }
    }

    private void updateTestContainerFromConfig(ILaunchConfiguration config) {
        String containerHandle = EMPTY_STRING;
        IJavaElement containerElement = null;
        try {
            containerHandle = config.getAttribute(
                    JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, EMPTY_STRING);
            if (containerHandle.length() > 0) {
                containerElement = JavaCore.create(containerHandle);
            }
        } catch (CoreException ce) {
            // ignore
        }
        if (containerElement != null) {
            mContainerElement = containerElement;
        }    
        mTestContainerRadioButton.setSelection(true);
        setEnableSingleTestGroup(false);
        setEnableContainerTestGroup(true);              
        mTestRadioButton.setSelection(false);
        if (mContainerElement != null) {
            mContainerText.setText(getPresentationName(mContainerElement));
        }    
        mTestText.setText(EMPTY_STRING);
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
     */
    public void performApply(ILaunchConfigurationWorkingCopy config) {
        if (mTestContainerRadioButton.getSelection() && mContainerElement != null) {
            config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, 
                    mContainerElement.getJavaProject().getElementName());
            config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, 
                    mContainerElement.getHandleIdentifier());
            config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME,
                    EMPTY_STRING);
             //workaround for Eclipse bug 65399
            config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME,
                    EMPTY_STRING);
        } else {
            config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME,
                    mProjText.getText());
            config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME,
                    mTestText.getText());
            config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER,
                    EMPTY_STRING);
            config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME,
                    mOriginalTestMethodName);
        }
        try {
            mapResources(config);
        } catch (CoreException e) {
            // TODO: does the real error need to be extracted out of CoreException
            AdtPlugin.log(e, "Error occurred saving configuration");
        }
        AndroidJUnitLaunchConfigDelegate.setJUnitDefaults(config);
        
        config.setAttribute(AndroidJUnitLaunchConfigDelegate.ATTR_INSTR_NAME,
                getSelectedInstrumentation());
    }

    private void mapResources(ILaunchConfigurationWorkingCopy config)  throws CoreException {
        JUnitMigrationDelegate.mapResources(config);
    }   

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#dispose()
     */
    @Override
    public void dispose() {
        super.dispose();
        if (mTabIcon != null) {
            mTabIcon.dispose();
            mTabIcon = null;
        }
        mJavaElementLabelProvider.dispose();
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getImage()
     */
    @Override
    public Image getImage() {
        // reuse icon from the Android App Launch config tab
        if (mTabIcon == null) {
            mTabIcon= AdtPlugin.getImageLoader().loadImage(MainLaunchConfigTab.LAUNCH_TAB_IMAGE,
                    null);
        }
        return mTabIcon;
    }

    /**
     * Show a dialog that lists all main types
     */
    private void handleSearchButtonSelected() {
        Shell shell = getShell();

        IJavaProject javaProject = getJavaProject();

        IType[] types = new IType[0];
        boolean[] radioSetting = new boolean[2];
        try {
            // fix for Eclipse bug 66922 Wrong radio behaviour when switching
            // remember the selected radio button
            radioSetting[0] = mTestRadioButton.getSelection();
            radioSetting[1] = mTestContainerRadioButton.getSelection();
            
            types = TestSearchEngine.findTests(getLaunchConfigurationDialog(), javaProject,
                    getTestKind()); 
        } catch (InterruptedException e) {
            setErrorMessage(e.getMessage());
            return;
        } catch (InvocationTargetException e) {
            AdtPlugin.log(e.getTargetException(), "Error finding test types");
            return;
        } finally {
            mTestRadioButton.setSelection(radioSetting[0]);
            mTestContainerRadioButton.setSelection(radioSetting[1]);
        }

        SelectionDialog dialog = new TestSelectionDialog(shell, types);
        dialog.setTitle(JUnitMessages.JUnitLaunchConfigurationTab_testdialog_title); 
        dialog.setMessage(JUnitMessages.JUnitLaunchConfigurationTab_testdialog_message); 
        if (dialog.open() == Window.CANCEL) {
            return;
        }

        Object[] results = dialog.getResult();
        if ((results == null) || (results.length < 1)) {
            return;
        }       
        IType type = (IType) results[0];

        if (type != null) {
            mTestText.setText(type.getFullyQualifiedName('.'));
            javaProject = type.getJavaProject();
            mProjText.setText(javaProject.getElementName());
        }
    }

    private ITestKind getTestKind() {
        // harddcode this to JUnit 3
        return TestKindRegistry.getDefault().getKind(TestKindRegistry.JUNIT3_TEST_KIND_ID);
    }

    /**
     * Show a dialog that lets the user select a Android project.  This in turn provides
     * context for the main type, allowing the user to key a main type name, or
     * constraining the search for main types to the specified project.
     */
    private void handleProjectButtonSelected() {
        IJavaProject project = mProjectChooserHelper.chooseJavaProject(getProjectName());
        if (project == null) {
            return;
        }

        String projectName = project.getElementName();
        mProjText.setText(projectName);
        loadInstrumentations(project.getProject());   
    }

    /**
     * Return the IJavaProject corresponding to the project name in the project name
     * text field, or null if the text does not match a Android project name.
     */
    private IJavaProject getJavaProject() {
        String projectName = getProjectName();
        return getJavaModel().getJavaProject(projectName);      
    }

    /**
     * Returns the name of the currently specified project. Null if no project is selected.
     */
    private String getProjectName() {
        String projectName = mProjText.getText().trim();
        if (projectName.length() < 1) {
            return null;
        }
        return projectName;
    }

    /**
     * Convenience method to get the workspace root.
     */
    private IWorkspaceRoot getWorkspaceRoot() {
        return ResourcesPlugin.getWorkspace().getRoot();
    }

    /**
     * Convenience method to get access to the java model.
     */
    private IJavaModel getJavaModel() {
        return JavaCore.create(getWorkspaceRoot());
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
     */
    @Override
    public boolean isValid(ILaunchConfiguration config) {
        validatePage();
        return getErrorMessage() == null;
    }

    private void testModeChanged() {
        boolean isSingleTestMode = mTestRadioButton.getSelection();
        setEnableSingleTestGroup(isSingleTestMode);
        setEnableContainerTestGroup(!isSingleTestMode);
        if (!isSingleTestMode && mContainerText.getText().length() == 0) {
            String projText = mProjText.getText();
            if (Path.EMPTY.isValidSegment(projText)) {
                IJavaProject javaProject = getJavaModel().getJavaProject(projText);
                if (javaProject != null && javaProject.exists()) {
                    setContainerElement(javaProject);
                }    
            }
        }
        validatePage();
        updateLaunchConfigurationDialog();
    }

    private void validatePage() {       
        setErrorMessage(null);
        setMessage(null);

        if (mTestContainerRadioButton.getSelection()) {
            if (mContainerElement == null) {
                setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_noContainer);
                return;
            }
            validateJavaProject(mContainerElement.getJavaProject());
            return;
        }

        String projectName = mProjText.getText().trim();
        if (projectName.length() == 0) {
            setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_projectnotdefined);
            return;
        }

        IStatus status = ResourcesPlugin.getWorkspace().validatePath(IPath.SEPARATOR + projectName,
                IResource.PROJECT);
        if (!status.isOK() || !Path.ROOT.isValidSegment(projectName)) {
            setErrorMessage(Messages.format(
                    JUnitMessages.JUnitLaunchConfigurationTab_error_invalidProjectName, 
                    projectName));
            return;
        }

        IProject project = getWorkspaceRoot().getProject(projectName);
        if (!project.exists()) {
            setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_projectnotexists);
            return;
        }
        IJavaProject javaProject = JavaCore.create(project);
        validateJavaProject(javaProject);

        try {
            if (!project.hasNature(AndroidConstants.NATURE)) {
                setErrorMessage("Specified project is not an Android project");
                return;
            }
            String className = mTestText.getText().trim();
            if (className.length() == 0) {
                setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_testnotdefined);
                return;
            }
            if (javaProject.findType(className) == null) {
                setErrorMessage(Messages.format(
                        JUnitMessages.JUnitLaunchConfigurationTab_error_test_class_not_found,
                        new String[] { className, projectName }));
                return;
            }          
        } catch (CoreException e) {
            AdtPlugin.log(e, "validatePage failed");
        }

        validateInstrumentation(javaProject);
    }

    private void validateJavaProject(IJavaProject javaProject) {
        if (!TestSearchEngine.hasTestCaseType(javaProject)) {
            setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_testcasenotonpath); 
            return;             
        }
    }

    private void validateInstrumentation(IJavaProject javaProject) {
        if (mInstrumentations == null || mInstrumentations.length < 1) {
            setErrorMessage("Specified project has no defined instrumentations");
        }
        String instrumentation = getSelectedInstrumentation();
        if (instrumentation == null) {
            setErrorMessage("Instrumentation not specified");
        }
    }

    private String getSelectedInstrumentation() {
        int selectionIndex = mInstrumentationCombo.getSelectionIndex();
        if (mInstrumentations != null && selectionIndex >= 0 && 
                selectionIndex < mInstrumentations.length) {
            return mInstrumentations[selectionIndex];
        }
        return null;
    }

    private void setEnableContainerTestGroup(boolean enabled) {
        mContainerSearchButton.setEnabled(enabled);
        mContainerText.setEnabled(enabled);
    }

    private void setEnableSingleTestGroup(boolean enabled) {
        mProjLabel.setEnabled(enabled);
        mProjText.setEnabled(enabled);
        mProjButton.setEnabled(enabled);
        mTestLabel.setEnabled(enabled);
        mTestText.setEnabled(enabled);
        mSearchButton.setEnabled(enabled && mProjText.getText().length() > 0);
        mTestMethodLabel.setEnabled(enabled);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
     */
    public void setDefaults(ILaunchConfigurationWorkingCopy config) {
        IJavaElement javaElement = getContext();
        if (javaElement != null) {
            initializeJavaProject(javaElement, config);
        } else {
            // We set empty attributes for project & main type so that when one config is
            // compared to another, the existence of empty attributes doesn't cause an
            // incorrect result (the performApply() method can result in empty values
            // for these attributes being set on a config if there is nothing in the
            // corresponding text boxes)
            config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, EMPTY_STRING);
            config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER,
                    EMPTY_STRING);
        }
        initializeTestAttributes(javaElement, config);
    }

    private void initializeTestAttributes(IJavaElement javaElement,
            ILaunchConfigurationWorkingCopy config) {
        if (javaElement != null && javaElement.getElementType() < IJavaElement.COMPILATION_UNIT) { 
            initializeTestContainer(javaElement, config);
        } else {
            initializeTestType(javaElement, config);
        }    
    }

    private void initializeTestContainer(IJavaElement javaElement,
            ILaunchConfigurationWorkingCopy config) {
        config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER,
                javaElement.getHandleIdentifier());
        initializeName(config, javaElement.getElementName());
    }

    private void initializeName(ILaunchConfigurationWorkingCopy config, String name) {
        if (name == null) {
            name = EMPTY_STRING;
        }
        if (name.length() > 0) {
            int index = name.lastIndexOf('.');
            if (index > 0) {
                name = name.substring(index + 1);
            }
            name = getLaunchConfigurationDialog().generateName(name);
            config.rename(name);
        }
    }

    /**
     * Sets the main type & name attributes on the working copy based on the IJavaElement
     */
    private void initializeTestType(IJavaElement javaElement,
            ILaunchConfigurationWorkingCopy config) {
        String name = EMPTY_STRING;
        String testKindId = null;
        try {
            // only do a search for compilation units or class files or source references
            if (javaElement instanceof ISourceReference) {
                ITestKind testKind = TestKindRegistry.getContainerTestKind(javaElement);
                testKindId = testKind.getId();

                IType[] types = TestSearchEngine.findTests(getLaunchConfigurationDialog(),
                        javaElement, testKind); 
                if ((types == null) || (types.length < 1)) {
                    return;
                }
                // Simply grab the first main type found in the searched element
                name = types[0].getFullyQualifiedName('.');
                
            }   
        } catch (InterruptedException ie) {
            // ignore
        } catch (InvocationTargetException ite) {
            // ignore
        }
        config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, name);
        if (testKindId != null) {
            config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_RUNNER_KIND,
                    testKindId);
        }    
        initializeName(config, name);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
     */
    public String getName() {
        return JUnitMessages.JUnitLaunchConfigurationTab_tab_label; 
    }

    @SuppressWarnings("unchecked")
    private IJavaElement chooseContainer(IJavaElement initElement) {
        Class[] acceptedClasses = new Class[] { IPackageFragmentRoot.class, IJavaProject.class,
                IPackageFragment.class };
        TypedElementSelectionValidator validator = new TypedElementSelectionValidator(
                acceptedClasses, false) {
            @Override
            public boolean isSelectedValid(Object element) {
                return true;
            }
        };

        acceptedClasses = new Class[] { IJavaModel.class, IPackageFragmentRoot.class,
                IJavaProject.class, IPackageFragment.class };
        ViewerFilter filter = new TypedViewerFilter(acceptedClasses) {
            @Override
            public boolean select(Viewer viewer, Object parent, Object element) {
                if (element instanceof IPackageFragmentRoot && 
                        ((IPackageFragmentRoot) element).isArchive()) {
                    return false;
                }    
                try {
                    if (element instanceof IPackageFragment &&
                            !((IPackageFragment) element).hasChildren()) {
                        return false;
                    }
                } catch (JavaModelException e) {
                    return false;
                }
                return super.select(viewer, parent, element);
            }
        };      

        StandardJavaElementContentProvider provider = new StandardJavaElementContentProvider();
        ILabelProvider labelProvider = new JavaElementLabelProvider(
                JavaElementLabelProvider.SHOW_DEFAULT); 
        ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), 
                labelProvider, provider);
        dialog.setValidator(validator);
        dialog.setComparator(new JavaElementComparator());
        dialog.setTitle(JUnitMessages.JUnitLaunchConfigurationTab_folderdialog_title);  
        dialog.setMessage(JUnitMessages.JUnitLaunchConfigurationTab_folderdialog_message);  
        dialog.addFilter(filter);
        dialog.setInput(JavaCore.create(getWorkspaceRoot()));
        dialog.setInitialSelection(initElement);
        dialog.setAllowMultiple(false);

        if (dialog.open() == Window.OK) {
            Object element = dialog.getFirstResult();
            return (IJavaElement) element;
        }
        return null;
    }

    private String getPresentationName(IJavaElement element) {
        return mJavaElementLabelProvider.getText(element);
    }

    /**
     * Returns the current Java element context from which to initialize
     * default settings, or <code>null</code> if none.
     * 
     * @return Java element context.
     */
    private IJavaElement getContext() {
        IWorkbenchWindow activeWorkbenchWindow =
            PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        if (activeWorkbenchWindow == null) {
            return null;
        }
        IWorkbenchPage page = activeWorkbenchWindow.getActivePage();
        if (page != null) {
            ISelection selection = page.getSelection();
            if (selection instanceof IStructuredSelection) {
                IStructuredSelection ss = (IStructuredSelection) selection;
                if (!ss.isEmpty()) {
                    Object obj = ss.getFirstElement();
                    if (obj instanceof IJavaElement) {
                        return (IJavaElement) obj;
                    }
                    if (obj instanceof IResource) {
                        IJavaElement je = JavaCore.create((IResource) obj);
                        if (je == null) {
                            IProject pro = ((IResource) obj).getProject();
                            je = JavaCore.create(pro);
                        }
                        if (je != null) {
                            return je;
                        }
                    }
                }
            }
            IEditorPart part = page.getActiveEditor();
            if (part != null) {
                IEditorInput input = part.getEditorInput();
                return (IJavaElement) input.getAdapter(IJavaElement.class);
            }
        }
        return null;
    }

    private void initializeJavaProject(IJavaElement javaElement,
            ILaunchConfigurationWorkingCopy config) {
        IJavaProject javaProject = javaElement.getJavaProject();
        String name = null;
        if (javaProject != null && javaProject.exists()) {
            name = javaProject.getElementName();
        }
        config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, name);
    }

    private void setButtonGridData(Button button) {
        GridData gridData = new GridData();
        button.setLayoutData(gridData);
        LayoutUtil.setButtonDimensionHint(button);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getId()
     */
    @Override
    public String getId() {
        return "com.android.ide.eclipse.adt.launch.AndroidJUnitLaunchConfigurationTab"; //$NON-NLS-1$
    }

    /**
     * Loads the UI with the instrumentations of the specified project, and stores the
     * activities in <code>mActivities</code>.
     * <p/>
     * First activity is selected by default if present.
     * 
     * @param project the {@link IProject} to load the instrumentations from.
     */
    private void loadInstrumentations(IProject project) {
        mInstrumentations = AndroidJUnitLaunchConfigDelegate.getInstrumentationsForProject(project);
        if (mInstrumentations != null) {
            mInstrumentationCombo.removeAll();
            for (String instrumentation : mInstrumentations) {
                mInstrumentationCombo.add(instrumentation);
            }
            // the selection will be set when we update the ui from the current
            // config object.
            return;
        }

        // if we reach this point, either project is null, or we got an exception during
        // the parsing. In either case, we empty the instrumentation list.
        mInstrumentations = null;
        mInstrumentationCombo.removeAll();
    }
}
