/*
 * 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.internal.launch.junit;

import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AndroidConstants;
import com.android.ide.eclipse.adt.internal.launch.MainLaunchConfigTab;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.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 static final String TAG = "AndroidJUnitLaunchConfigurationTab"; //$NON-NLS-1$
    private String[] mInstrumentations = null;
    private InstrumentationRunnerValidator mInstrValidator = 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(
                "Run all tests in the selected project, or package"); 
        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"); //$NON-NLS-1$
        }
        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"); //$NON-NLS-1$
            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"); //$NON-NLS-1$
        }

        validateInstrumentation();
    }

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

    private void validateInstrumentation() {
        String instrumentation = getSelectedInstrumentation();
        if (instrumentation == null) {
            setErrorMessage("Instrumentation runner not specified");
            return;
        }
        String result = mInstrValidator.validateInstrumentationRunner(instrumentation);
        if (result != InstrumentationRunnerValidator.INSTRUMENTATION_OK) {
            setErrorMessage(result);
            return;
        }
    }

    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[] { 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);
            }
        };      

        AndroidJavaElementContentProvider provider = new AndroidJavaElementContentProvider();
        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
     * instrumentations in <code>mInstrumentations</code>.
     * 
     * @param project the {@link IProject} to load the instrumentations from.
     */
    private void loadInstrumentations(IProject project) {
        try {
        mInstrValidator = new InstrumentationRunnerValidator(project);
        mInstrumentations = (mInstrValidator == null ? null : 
            mInstrValidator.getInstrumentationNames());
        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;
        }
        } catch (CoreException e) {
            AdtPlugin.logAndPrintError(e, TAG, "ERROR: Failed to get instrumentations for %1$s",
                    project.getName());
        }
        // 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.
        mInstrValidator = null;
        mInstrumentations = null;
        mInstrumentationCombo.removeAll();
    }

    /**
     * Overrides the {@link StandardJavaElementContentProvider} to only display Android projects
     */
    private static class AndroidJavaElementContentProvider
            extends StandardJavaElementContentProvider {

        /**
         * Override parent to return only Android projects if at the root. Otherwise, use parent 
         * functionality.
         */
        @Override
        public Object[] getChildren(Object element) {
            if (element instanceof IJavaModel) {
                return BaseProjectHelper.getAndroidProjects((IJavaModel) element);
            }
            return super.getChildren(element);
        }
    }
}
