/*
 * Copyright (C) 2007 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.project;

import static com.android.ide.eclipse.adt.AdtConstants.COMPILER_COMPLIANCE_PREFERRED;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.ide.common.xml.ManifestData;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.build.builders.PostCompilerBuilder;
import com.android.ide.eclipse.adt.internal.build.builders.PreCompilerBuilder;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.IAndroidTarget;
import com.android.utils.Pair;

import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstall2;
import org.eclipse.jdt.launching.IVMInstallType;
import org.eclipse.jdt.launching.JavaRuntime;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * Utility class to manipulate Project parameters/properties.
 */
public final class ProjectHelper {
    public final static int COMPILER_COMPLIANCE_OK = 0;
    public final static int COMPILER_COMPLIANCE_LEVEL = 1;
    public final static int COMPILER_COMPLIANCE_SOURCE = 2;
    public final static int COMPILER_COMPLIANCE_CODEGEN_TARGET = 3;

    /**
     * Adds the given ClasspathEntry object to the class path entries.
     * This method does not check whether the entry is already defined in the project.
     *
     * @param entries The class path entries to read. A copy will be returned.
     * @param newEntry The new class path entry to add.
     * @return A new class path entries array.
     */
    public static IClasspathEntry[] addEntryToClasspath(
            IClasspathEntry[] entries, IClasspathEntry newEntry) {
        int n = entries.length;
        IClasspathEntry[] newEntries = new IClasspathEntry[n + 1];
        System.arraycopy(entries, 0, newEntries, 0, n);
        newEntries[n] = newEntry;
        return newEntries;
    }

    /**
     * Replaces the given ClasspathEntry in the classpath entries.
     *
     * If the classpath does not yet exists (Check is based on entry path), then it is added.
     *
     * @param entries The class path entries to read. The same array (replace) or a copy (add)
     *                will be returned.
     * @param newEntry The new class path entry to add.
     * @return The same array (replace) or a copy (add) will be returned.
     *
     * @see IClasspathEntry#getPath()
     */
    public static IClasspathEntry[] replaceEntryInClasspath(
            IClasspathEntry[] entries, IClasspathEntry newEntry) {

        IPath path = newEntry.getPath();
        for (int i = 0, count = entries.length; i < count ; i++) {
            if (path.equals(entries[i].getPath())) {
                entries[i] = newEntry;
                return entries;
            }
        }

        return addEntryToClasspath(entries, newEntry);
    }

    /**
     * Adds the corresponding source folder to the project's class path entries.
     * This method does not check whether the entry is already defined in the project.
     *
     * @param javaProject The java project of which path entries to update.
     * @param newEntry The new class path entry to add.
     * @throws JavaModelException
     */
    public static void addEntryToClasspath(IJavaProject javaProject, IClasspathEntry newEntry)
            throws JavaModelException {

        IClasspathEntry[] entries = javaProject.getRawClasspath();
        entries = addEntryToClasspath(entries, newEntry);
        javaProject.setRawClasspath(entries, new NullProgressMonitor());
    }

    /**
     * Checks whether the given class path entry is already defined in the project.
     *
     * @param javaProject The java project of which path entries to check.
     * @param newEntry The parent source folder to remove.
     * @return True if the class path entry is already defined.
     * @throws JavaModelException
     */
    public static boolean isEntryInClasspath(IJavaProject javaProject, IClasspathEntry newEntry)
            throws JavaModelException {

        IClasspathEntry[] entries = javaProject.getRawClasspath();
        for (IClasspathEntry entry : entries) {
            if (entry.equals(newEntry)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Remove a classpath entry from the array.
     * @param entries The class path entries to read. A copy will be returned
     * @param index The index to remove.
     * @return A new class path entries array.
     */
    public static IClasspathEntry[] removeEntryFromClasspath(
            IClasspathEntry[] entries, int index) {
        int n = entries.length;
        IClasspathEntry[] newEntries = new IClasspathEntry[n-1];

        // copy the entries before index
        System.arraycopy(entries, 0, newEntries, 0, index);

        // copy the entries after index
        System.arraycopy(entries, index + 1, newEntries, index,
                entries.length - index - 1);

        return newEntries;
    }

    /**
     * Converts a OS specific path into a path valid for the java doc location
     * attributes of a project.
     * @param javaDocOSLocation The OS specific path.
     * @return a valid path for the java doc location.
     */
    public static String getJavaDocPath(String javaDocOSLocation) {
        // first thing we do is convert the \ into /
        String javaDoc = javaDocOSLocation.replaceAll("\\\\", //$NON-NLS-1$
                AdtConstants.WS_SEP);

        // then we add file: at the beginning for unix path, and file:/ for non
        // unix path
        if (javaDoc.startsWith(AdtConstants.WS_SEP)) {
            return "file:" + javaDoc; //$NON-NLS-1$
        }

        return "file:/" + javaDoc; //$NON-NLS-1$
    }

    /**
     * Look for a specific classpath entry by full path and return its index.
     * @param entries The entry array to search in.
     * @param entryPath The OS specific path of the entry.
     * @param entryKind The kind of the entry. Accepted values are 0
     * (no filter), IClasspathEntry.CPE_LIBRARY, IClasspathEntry.CPE_PROJECT,
     * IClasspathEntry.CPE_SOURCE, IClasspathEntry.CPE_VARIABLE,
     * and IClasspathEntry.CPE_CONTAINER
     * @return the index of the found classpath entry or -1.
     */
    public static int findClasspathEntryByPath(IClasspathEntry[] entries,
            String entryPath, int entryKind) {
        for (int i = 0 ; i < entries.length ; i++) {
            IClasspathEntry entry = entries[i];

            int kind = entry.getEntryKind();

            if (kind == entryKind || entryKind == 0) {
                // get the path
                IPath path = entry.getPath();

                String osPathString = path.toOSString();
                if (osPathString.equals(entryPath)) {
                    return i;
                }
            }
        }

        // not found, return bad index.
        return -1;
    }

    /**
     * Look for a specific classpath entry for file name only and return its
     *  index.
     * @param entries The entry array to search in.
     * @param entryName The filename of the entry.
     * @param entryKind The kind of the entry. Accepted values are 0
     * (no filter), IClasspathEntry.CPE_LIBRARY, IClasspathEntry.CPE_PROJECT,
     * IClasspathEntry.CPE_SOURCE, IClasspathEntry.CPE_VARIABLE,
     * and IClasspathEntry.CPE_CONTAINER
     * @param startIndex Index where to start the search
     * @return the index of the found classpath entry or -1.
     */
    public static int findClasspathEntryByName(IClasspathEntry[] entries,
            String entryName, int entryKind, int startIndex) {
        if (startIndex < 0) {
            startIndex = 0;
        }
        for (int i = startIndex ; i < entries.length ; i++) {
            IClasspathEntry entry = entries[i];

            int kind = entry.getEntryKind();

            if (kind == entryKind || entryKind == 0) {
                // get the path
                IPath path = entry.getPath();
                String name = path.segment(path.segmentCount()-1);

                if (name.equals(entryName)) {
                    return i;
                }
            }
        }

        // not found, return bad index.
        return -1;
    }

    public static boolean updateProject(IJavaProject project) {
        return updateProjects(new IJavaProject[] { project});
    }

    /**
     * Update the android-specific projects's classpath containers.
     * @param projects the projects to update
     * @return
     */
    public static boolean updateProjects(IJavaProject[] projects) {
        boolean r = AndroidClasspathContainerInitializer.updateProjects(projects);
        if (r) {
            return LibraryClasspathContainerInitializer.updateProjects(projects);
        }
        return false;
    }

    /**
     * Fix the project. This checks the SDK location.
     * @param project The project to fix.
     * @throws JavaModelException
     */
    public static void fixProject(IProject project) throws JavaModelException {
        if (AdtPlugin.getOsSdkFolder().length() == 0) {
            AdtPlugin.printToConsole(project, "Unknown SDK Location, project not fixed.");
            return;
        }

        // get a java project
        IJavaProject javaProject = JavaCore.create(project);
        fixProjectClasspathEntries(javaProject);
    }

    /**
     * Fix the project classpath entries. The method ensures that:
     * <ul>
     * <li>The project does not reference any old android.zip/android.jar archive.</li>
     * <li>The project does not use its output folder as a sourc folder.</li>
     * <li>The project does not reference a desktop JRE</li>
     * <li>The project references the AndroidClasspathContainer.
     * </ul>
     * @param javaProject The project to fix.
     * @throws JavaModelException
     */
    public static void fixProjectClasspathEntries(IJavaProject javaProject)
            throws JavaModelException {

        // get the project classpath
        IClasspathEntry[] entries = javaProject.getRawClasspath();
        IClasspathEntry[] oldEntries = entries;
        boolean forceRewriteOfCPE = false;

        // check if the JRE is set as library
        int jreIndex = ProjectHelper.findClasspathEntryByPath(entries, JavaRuntime.JRE_CONTAINER,
                IClasspathEntry.CPE_CONTAINER);
        if (jreIndex != -1) {
            // the project has a JRE included, we remove it
            entries = ProjectHelper.removeEntryFromClasspath(entries, jreIndex);
        }

        // get the output folder
        IPath outputFolder = javaProject.getOutputLocation();

        boolean foundFrameworkContainer = false;
        IClasspathEntry foundLibrariesContainer = null;
        IClasspathEntry foundDependenciesContainer = null;

        for (int i = 0 ; i < entries.length ;) {
            // get the entry and kind
            IClasspathEntry entry = entries[i];
            int kind = entry.getEntryKind();

            if (kind == IClasspathEntry.CPE_SOURCE) {
                IPath path = entry.getPath();

                if (path.equals(outputFolder)) {
                    entries = ProjectHelper.removeEntryFromClasspath(entries, i);

                    // continue, to skip the i++;
                    continue;
                }
            } else if (kind == IClasspathEntry.CPE_CONTAINER) {
                String path = entry.getPath().toString();
                if (AdtConstants.CONTAINER_FRAMEWORK.equals(path)) {
                    foundFrameworkContainer = true;
                } else if (AdtConstants.CONTAINER_PRIVATE_LIBRARIES.equals(path)) {
                    foundLibrariesContainer = entry;
                } else if (AdtConstants.CONTAINER_DEPENDENCIES.equals(path)) {
                    foundDependenciesContainer = entry;
                }
            }

            i++;
        }

        // look to see if we have the m2eclipse nature
        boolean m2eNature = false;
        try {
            m2eNature = javaProject.getProject().hasNature("org.eclipse.m2e.core.maven2Nature");
        } catch (CoreException e) {
            AdtPlugin.log(e, "Failed to query project %s for m2e nature",
                    javaProject.getProject().getName());
        }


        // if the framework container is not there, we add it
        if (!foundFrameworkContainer) {
            // add the android container to the array
            entries = ProjectHelper.addEntryToClasspath(entries,
                    JavaCore.newContainerEntry(new Path(AdtConstants.CONTAINER_FRAMEWORK)));
        }

        // same thing for the library container
        if (foundLibrariesContainer == null) {
            // add the exported libraries android container to the array
            entries = ProjectHelper.addEntryToClasspath(entries,
                    JavaCore.newContainerEntry(
                            new Path(AdtConstants.CONTAINER_PRIVATE_LIBRARIES), true));
        } else if (!m2eNature && !foundLibrariesContainer.isExported()) {
            // the container is present but it's not exported and since there's no m2e nature
            // we do want it to be exported.
            // keep all the other parameters the same.
            entries = ProjectHelper.replaceEntryInClasspath(entries,
                    JavaCore.newContainerEntry(
                            new Path(AdtConstants.CONTAINER_PRIVATE_LIBRARIES),
                            foundLibrariesContainer.getAccessRules(),
                            foundLibrariesContainer.getExtraAttributes(),
                            true));
            forceRewriteOfCPE = true;
        }

        // same thing for the dependencies container
        if (foundDependenciesContainer == null) {
            // add the android dependencies container to the array
            entries = ProjectHelper.addEntryToClasspath(entries,
                    JavaCore.newContainerEntry(
                            new Path(AdtConstants.CONTAINER_DEPENDENCIES), true));
        } else if (!m2eNature && !foundDependenciesContainer.isExported()) {
            // the container is present but it's not exported and since there's no m2e nature
            // we do want it to be exported.
            // keep all the other parameters the same.
            entries = ProjectHelper.replaceEntryInClasspath(entries,
                    JavaCore.newContainerEntry(
                            new Path(AdtConstants.CONTAINER_DEPENDENCIES),
                            foundDependenciesContainer.getAccessRules(),
                            foundDependenciesContainer.getExtraAttributes(),
                            true));
            forceRewriteOfCPE = true;
        }

        // set the new list of entries to the project
        if (entries != oldEntries || forceRewriteOfCPE) {
            javaProject.setRawClasspath(entries, new NullProgressMonitor());
        }

        // If needed, check and fix compiler compliance and source compatibility
        ProjectHelper.checkAndFixCompilerCompliance(javaProject);
    }


    /**
     * Checks the project compiler compliance level is supported.
     * @param javaProject The project to check
     * @return A pair with the first integer being an error code, and the second value
     *   being the invalid value found or null. The error code can be: <ul>
     * <li><code>COMPILER_COMPLIANCE_OK</code> if the project is properly configured</li>
     * <li><code>COMPILER_COMPLIANCE_LEVEL</code> for unsupported compiler level</li>
     * <li><code>COMPILER_COMPLIANCE_SOURCE</code> for unsupported source compatibility</li>
     * <li><code>COMPILER_COMPLIANCE_CODEGEN_TARGET</code> for unsupported .class format</li>
     * </ul>
     */
    public static final Pair<Integer, String> checkCompilerCompliance(IJavaProject javaProject) {
        // get the project compliance level option
        String compliance = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);

        // check it against a list of valid compliance level strings.
        if (!checkCompliance(javaProject, compliance)) {
            // if we didn't find the proper compliance level, we return an error
            return Pair.of(COMPILER_COMPLIANCE_LEVEL, compliance);
        }

        // otherwise we check source compatibility
        String source = javaProject.getOption(JavaCore.COMPILER_SOURCE, true);

        // check it against a list of valid compliance level strings.
        if (!checkCompliance(javaProject, source)) {
            // if we didn't find the proper compliance level, we return an error
            return Pair.of(COMPILER_COMPLIANCE_SOURCE, source);
        }

        // otherwise check codegen level
        String codeGen = javaProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true);

        // check it against a list of valid compliance level strings.
        if (!checkCompliance(javaProject, codeGen)) {
            // if we didn't find the proper compliance level, we return an error
            return Pair.of(COMPILER_COMPLIANCE_CODEGEN_TARGET, codeGen);
        }

        return Pair.of(COMPILER_COMPLIANCE_OK, null);
    }

    /**
     * Checks the project compiler compliance level is supported.
     * @param project The project to check
     * @return A pair with the first integer being an error code, and the second value
     *   being the invalid value found or null. The error code can be: <ul>
     * <li><code>COMPILER_COMPLIANCE_OK</code> if the project is properly configured</li>
     * <li><code>COMPILER_COMPLIANCE_LEVEL</code> for unsupported compiler level</li>
     * <li><code>COMPILER_COMPLIANCE_SOURCE</code> for unsupported source compatibility</li>
     * <li><code>COMPILER_COMPLIANCE_CODEGEN_TARGET</code> for unsupported .class format</li>
     * </ul>
     */
    public static final Pair<Integer, String> checkCompilerCompliance(IProject project) {
        // get the java project from the IProject resource object
        IJavaProject javaProject = JavaCore.create(project);

        // check and return the result.
        return checkCompilerCompliance(javaProject);
    }


    /**
     * Checks, and fixes if needed, the compiler compliance level, and the source compatibility
     * level
     * @param project The project to check and fix.
     */
    public static final void checkAndFixCompilerCompliance(IProject project) {
        // FIXME This method is never used. Shall we just removed it?
        // {@link #checkAndFixCompilerCompliance(IJavaProject)} is used instead.

        // get the java project from the IProject resource object
        IJavaProject javaProject = JavaCore.create(project);

        // Now we check the compiler compliance level and make sure it is valid
        checkAndFixCompilerCompliance(javaProject);
    }

    /**
     * Checks, and fixes if needed, the compiler compliance level, and the source compatibility
     * level
     * @param javaProject The Java project to check and fix.
     */
    public static final void checkAndFixCompilerCompliance(IJavaProject javaProject) {
        Pair<Integer, String> result = checkCompilerCompliance(javaProject);
        if (result.getFirst().intValue() != COMPILER_COMPLIANCE_OK) {
            // setup the preferred compiler compliance level.
            javaProject.setOption(JavaCore.COMPILER_COMPLIANCE,
                    AdtConstants.COMPILER_COMPLIANCE_PREFERRED);
            javaProject.setOption(JavaCore.COMPILER_SOURCE,
                    AdtConstants.COMPILER_COMPLIANCE_PREFERRED);
            javaProject.setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,
                    AdtConstants.COMPILER_COMPLIANCE_PREFERRED);

            // clean the project to make sure we recompile
            try {
                javaProject.getProject().build(IncrementalProjectBuilder.CLEAN_BUILD,
                        new NullProgressMonitor());
            } catch (CoreException e) {
                AdtPlugin.printErrorToConsole(javaProject.getProject(),
                        "Project compiler settings changed. Clean your project.");
            }
        }
    }

    /**
     * Makes the given project use JDK 6 (or more specifically,
     * {@link AdtConstants#COMPILER_COMPLIANCE_PREFERRED} as the compilation
     * target, regardless of what the default IDE JDK level is, provided a JRE
     * of the given level is installed.
     *
     * @param javaProject the Java project
     * @throws CoreException if the IDE throws an exception setting the compiler
     *             level
     */
    @SuppressWarnings("restriction") // JDT API for setting compliance options
    public static void enforcePreferredCompilerCompliance(@NonNull IJavaProject javaProject)
            throws CoreException {
        String compliance = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
        if (compliance == null ||
                JavaModelUtil.isVersionLessThan(compliance, COMPILER_COMPLIANCE_PREFERRED)) {
            IVMInstallType[] types = JavaRuntime.getVMInstallTypes();
            for (int i = 0; i < types.length; i++) {
                IVMInstallType type = types[i];
                IVMInstall[] installs = type.getVMInstalls();
                for (int j = 0; j < installs.length; j++) {
                    IVMInstall install = installs[j];
                    if (install instanceof IVMInstall2) {
                        IVMInstall2 install2 = (IVMInstall2) install;
                        // Java version can be 1.6.0, and preferred is 1.6
                        if (install2.getJavaVersion().startsWith(COMPILER_COMPLIANCE_PREFERRED)) {
                            Map<String, String> options = javaProject.getOptions(false);
                            JavaCore.setComplianceOptions(COMPILER_COMPLIANCE_PREFERRED, options);
                            JavaModelUtil.setDefaultClassfileOptions(options,
                                    COMPILER_COMPLIANCE_PREFERRED);
                            javaProject.setOptions(options);
                            return;
                        }
                    }
                }
            }
        }
    }

    /**
     * Returns a {@link IProject} by its running application name, as it returned by the AVD.
     * <p/>
     * <var>applicationName</var> will in most case be the package declared in the manifest, but
     * can, in some cases, be a custom process name declared in the manifest, in the
     * <code>application</code>, <code>activity</code>, <code>receiver</code>, or
     * <code>service</code> nodes.
     * @param applicationName The application name.
     * @return a project or <code>null</code> if no matching project were found.
     */
    public static IProject findAndroidProjectByAppName(String applicationName) {
        // Get the list of project for the current workspace
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IProject[] projects = workspace.getRoot().getProjects();

        // look for a project that matches the packageName of the app
        // we're trying to debug
        for (IProject p : projects) {
            if (p.isOpen()) {
                try {
                    if (p.hasNature(AdtConstants.NATURE_DEFAULT) == false) {
                        // ignore non android projects
                        continue;
                    }
                } catch (CoreException e) {
                    // failed to get the nature? skip project.
                    continue;
                }

                // check that there is indeed a manifest file.
                IFile manifestFile = getManifest(p);
                if (manifestFile == null) {
                    // no file? skip this project.
                    continue;
                }

                ManifestData data = AndroidManifestHelper.parseForData(manifestFile);
                if (data == null) {
                    // skip this project.
                    continue;
                }

                String manifestPackage = data.getPackage();

                if (manifestPackage != null && manifestPackage.equals(applicationName)) {
                    // this is the project we were looking for!
                    return p;
                } else {
                    // if the package and application name don't match,
                    // we look for other possible process names declared in the manifest.
                    String[] processes = data.getProcesses();
                    for (String process : processes) {
                        if (process.equals(applicationName)) {
                            return p;
                        }
                    }
                }
            }
        }

        return null;

    }

    public static void fixProjectNatureOrder(IProject project) throws CoreException {
        IProjectDescription description = project.getDescription();
        String[] natures = description.getNatureIds();

        // if the android nature is not the first one, we reorder them
        if (AdtConstants.NATURE_DEFAULT.equals(natures[0]) == false) {
            // look for the index
            for (int i = 0 ; i < natures.length ; i++) {
                if (AdtConstants.NATURE_DEFAULT.equals(natures[i])) {
                    // if we try to just reorder the array in one pass, this doesn't do
                    // anything. I guess JDT check that we are actually adding/removing nature.
                    // So, first we'll remove the android nature, and then add it back.

                    // remove the android nature
                    removeNature(project, AdtConstants.NATURE_DEFAULT);

                    // now add it back at the first index.
                    description = project.getDescription();
                    natures = description.getNatureIds();

                    String[] newNatures = new String[natures.length + 1];

                    // first one is android
                    newNatures[0] = AdtConstants.NATURE_DEFAULT;

                    // next the rest that was before the android nature
                    System.arraycopy(natures, 0, newNatures, 1, natures.length);

                    // set the new natures
                    description.setNatureIds(newNatures);
                    project.setDescription(description, null);

                    // and stop
                    break;
                }
            }
        }
    }


    /**
     * Removes a specific nature from a project.
     * @param project The project to remove the nature from.
     * @param nature The nature id to remove.
     * @throws CoreException
     */
    public static void removeNature(IProject project, String nature) throws CoreException {
        IProjectDescription description = project.getDescription();
        String[] natures = description.getNatureIds();

        // check if the project already has the android nature.
        for (int i = 0; i < natures.length; ++i) {
            if (nature.equals(natures[i])) {
                String[] newNatures = new String[natures.length - 1];
                if (i > 0) {
                    System.arraycopy(natures, 0, newNatures, 0, i);
                }
                System.arraycopy(natures, i + 1, newNatures, i, natures.length - i - 1);
                description.setNatureIds(newNatures);
                project.setDescription(description, null);

                return;
            }
        }

    }

    /**
     * Returns if the project has error level markers.
     * @param includeReferencedProjects flag to also test the referenced projects.
     * @throws CoreException
     */
    public static boolean hasError(IProject project, boolean includeReferencedProjects)
    throws CoreException {
        IMarker[] markers = project.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
        if (markers != null && markers.length > 0) {
            // the project has marker(s). even though they are "problem" we
            // don't know their severity. so we loop on them and figure if they
            // are warnings or errors
            for (IMarker m : markers) {
                int s = m.getAttribute(IMarker.SEVERITY, -1);
                if (s == IMarker.SEVERITY_ERROR) {
                    return true;
                }
            }
        }

        // test the referenced projects if needed.
        if (includeReferencedProjects) {
            List<IProject> projects = getReferencedProjects(project);

            for (IProject p : projects) {
                if (hasError(p, false)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Saves a String property into the persistent storage of a resource.
     * @param resource The resource into which the string value is saved.
     * @param propertyName the name of the property. The id of the plug-in is added to this string.
     * @param value the value to save
     * @return true if the save succeeded.
     */
    public static boolean saveStringProperty(IResource resource, String propertyName,
            String value) {
        QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID, propertyName);

        try {
            resource.setPersistentProperty(qname, value);
        } catch (CoreException e) {
            return false;
        }

        return true;
    }

    /**
     * Loads a String property from the persistent storage of a resource.
     * @param resource The resource from which the string value is loaded.
     * @param propertyName the name of the property. The id of the plug-in is added to this string.
     * @return the property value or null if it was not found.
     */
    public static String loadStringProperty(IResource resource, String propertyName) {
        QualifiedName qname = new QualifiedName(AdtPlugin.PLUGIN_ID, propertyName);

        try {
            String value = resource.getPersistentProperty(qname);
            return value;
        } catch (CoreException e) {
            return null;
        }
    }

    /**
     * Saves a property into the persistent storage of a resource.
     * @param resource The resource into which the boolean value is saved.
     * @param propertyName the name of the property. The id of the plug-in is added to this string.
     * @param value the value to save
     * @return true if the save succeeded.
     */
    public static boolean saveBooleanProperty(IResource resource, String propertyName,
            boolean value) {
        return saveStringProperty(resource, propertyName, Boolean.toString(value));
    }

    /**
     * Loads a boolean property from the persistent storage of a resource.
     * @param resource The resource from which the boolean value is loaded.
     * @param propertyName the name of the property. The id of the plug-in is added to this string.
     * @param defaultValue The default value to return if the property was not found.
     * @return the property value or the default value if the property was not found.
     */
    public static boolean loadBooleanProperty(IResource resource, String propertyName,
            boolean defaultValue) {
        String value = loadStringProperty(resource, propertyName);
        if (value != null) {
            return Boolean.parseBoolean(value);
        }

        return defaultValue;
    }

    public static Boolean loadBooleanProperty(IResource resource, String propertyName) {
        String value = loadStringProperty(resource, propertyName);
        if (value != null) {
            return Boolean.valueOf(value);
        }

        return null;
    }

    /**
     * Saves the path of a resource into the persistent storage of a resource.
     * @param resource The resource into which the resource path is saved.
     * @param propertyName the name of the property. The id of the plug-in is added to this string.
     * @param value The resource to save. It's its path that is actually stored. If null, an
     *      empty string is stored.
     * @return true if the save succeeded
     */
    public static boolean saveResourceProperty(IResource resource, String propertyName,
            IResource value) {
        if (value != null) {
            IPath iPath = value.getFullPath();
            return saveStringProperty(resource, propertyName, iPath.toString());
        }

        return saveStringProperty(resource, propertyName, ""); //$NON-NLS-1$
    }

    /**
     * Loads the path of a resource from the persistent storage of a resource, and returns the
     * corresponding IResource object.
     * @param resource The resource from which the resource path is loaded.
     * @param propertyName the name of the property. The id of the plug-in is added to this string.
     * @return The corresponding IResource object (or children interface) or null
     */
    public static IResource loadResourceProperty(IResource resource, String propertyName) {
        String value = loadStringProperty(resource, propertyName);

        if (value != null && value.length() > 0) {
            return ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(value));
        }

        return null;
    }

    /**
     * Returns the list of referenced project that are opened and Java projects.
     * @param project
     * @return a new list object containing the opened referenced java project.
     * @throws CoreException
     */
    public static List<IProject> getReferencedProjects(IProject project) throws CoreException {
        IProject[] projects = project.getReferencedProjects();

        ArrayList<IProject> list = new ArrayList<IProject>();

        for (IProject p : projects) {
            if (p.isOpen() && p.hasNature(JavaCore.NATURE_ID)) {
                list.add(p);
            }
        }

        return list;
    }


    /**
     * Checks a Java project compiler level option against a list of supported versions.
     * @param optionValue the Compiler level option.
     * @return true if the option value is supported.
     */
    private static boolean checkCompliance(@NonNull IJavaProject project, String optionValue) {
        for (String s : AdtConstants.COMPILER_COMPLIANCE) {
            if (s != null && s.equals(optionValue)) {
                return true;
            }
        }

        if (JavaCore.VERSION_1_7.equals(optionValue)) {
            // Requires API 19 and buildTools 19
            Sdk currentSdk = Sdk.getCurrent();
            if (currentSdk != null) {
                IProject p = project.getProject();
                IAndroidTarget target = currentSdk.getTarget(p);
                if (target == null || target.getVersion().getApiLevel() < 19) {
                    return false;
                }

                ProjectState projectState = Sdk.getProjectState(p);
                if (projectState != null) {
                    BuildToolInfo buildToolInfo = projectState.getBuildToolInfo();
                    if (buildToolInfo == null) {
                        buildToolInfo = currentSdk.getLatestBuildTool();
                    }
                    if (buildToolInfo == null || buildToolInfo.getRevision().getMajor() < 19) {
                        return false;
                    }
                }

                return true;
            }
        }

        return false;
    }

    /**
     * Returns the apk filename for the given project
     * @param project The project.
     * @param config An optional config name. Can be null.
     */
    public static String getApkFilename(IProject project, String config) {
        if (config != null) {
            return project.getName() + "-" + config + SdkConstants.DOT_ANDROID_PACKAGE; //$NON-NLS-1$
        }

        return project.getName() + SdkConstants.DOT_ANDROID_PACKAGE;
    }

    /**
     * Find the list of projects on which this JavaProject is dependent on at the compilation level.
     *
     * @param javaProject Java project that we are looking for the dependencies.
     * @return A list of Java projects for which javaProject depend on.
     * @throws JavaModelException
     */
    public static List<IJavaProject> getAndroidProjectDependencies(IJavaProject javaProject)
        throws JavaModelException {
        String[] requiredProjectNames = javaProject.getRequiredProjectNames();

        // Go from java project name to JavaProject name
        IJavaModel javaModel = javaProject.getJavaModel();

        // loop through all dependent projects and keep only those that are Android projects
        List<IJavaProject> projectList = new ArrayList<IJavaProject>(requiredProjectNames.length);
        for (String javaProjectName : requiredProjectNames) {
            IJavaProject androidJavaProject = javaModel.getJavaProject(javaProjectName);

            //Verify that the project has also the Android Nature
            try {
                if (!androidJavaProject.getProject().hasNature(AdtConstants.NATURE_DEFAULT)) {
                    continue;
                }
            } catch (CoreException e) {
                continue;
            }

            projectList.add(androidJavaProject);
        }

        return projectList;
    }

    /**
     * Returns the android package file as an IFile object for the specified
     * project.
     * @param project The project
     * @return The android package as an IFile object or null if not found.
     */
    public static IFile getApplicationPackage(IProject project) {
        // get the output folder
        IFolder outputLocation = BaseProjectHelper.getAndroidOutputFolder(project);

        if (outputLocation == null) {
            AdtPlugin.printErrorToConsole(project,
                    "Failed to get the output location of the project. Check build path properties"
                    );
            return null;
        }


        // get the package path
        String packageName = project.getName() + SdkConstants.DOT_ANDROID_PACKAGE;
        IResource r = outputLocation.findMember(packageName);

        // check the package is present
        if (r instanceof IFile && r.exists()) {
            return (IFile)r;
        }

        String msg = String.format("Could not find %1$s!", packageName);
        AdtPlugin.printErrorToConsole(project, msg);

        return null;
    }

    /**
     * Returns an {@link IFile} object representing the manifest for the given project.
     *
     * @param project The project containing the manifest file.
     * @return An IFile object pointing to the manifest or null if the manifest
     *         is missing.
     */
    public static IFile getManifest(IProject project) {
        IResource r = project.findMember(AdtConstants.WS_SEP
                + SdkConstants.FN_ANDROID_MANIFEST_XML);

        if (r == null || r.exists() == false || (r instanceof IFile) == false) {
            return null;
        }
        return (IFile) r;
    }

    /**
     * Does a full release build of the application, including the libraries. Do not build the
     * package.
     *
     * @param project The project to be built.
     * @param monitor A eclipse runtime progress monitor to be updated by the builders.
     * @throws CoreException
     */
    @SuppressWarnings("unchecked")
    public static void compileInReleaseMode(IProject project, IProgressMonitor monitor)
            throws CoreException {
        compileInReleaseMode(project, true /*includeDependencies*/, monitor);
    }

    /**
     * Does a full release build of the application, including the libraries. Do not build the
     * package.
     *
     * @param project The project to be built.
     * @param monitor A eclipse runtime progress monitor to be updated by the builders.
     * @throws CoreException
     */
    @SuppressWarnings("unchecked")
    private static void compileInReleaseMode(IProject project, boolean includeDependencies,
            IProgressMonitor monitor)
            throws CoreException {

        if (includeDependencies) {
            ProjectState projectState = Sdk.getProjectState(project);

            // this gives us all the library projects, direct and indirect dependencies,
            // so no need to run this method recursively.
            List<IProject> libraries = projectState.getFullLibraryProjects();

            // build dependencies in reverse order to prevent libraries being rebuilt
            // due to refresh of other libraries (they would be compiled in the wrong mode).
            for (int i = libraries.size() - 1 ; i >= 0 ; i--) {
                IProject lib = libraries.get(i);
                compileInReleaseMode(lib, false /*includeDependencies*/, monitor);

                // force refresh of the dependency.
                lib.refreshLocal(IResource.DEPTH_INFINITE, monitor);
            }
        }

        // do a full build on all the builders to guarantee that the builders are called.
        // (Eclipse does an optimization where builders are not called if there aren't any
        // deltas).

        ICommand[] commands = project.getDescription().getBuildSpec();
        for (ICommand command : commands) {
            String name = command.getBuilderName();
            if (PreCompilerBuilder.ID.equals(name)) {
                Map newArgs = new HashMap();
                newArgs.put(PreCompilerBuilder.RELEASE_REQUESTED, "");
                if (command.getArguments() != null) {
                    newArgs.putAll(command.getArguments());
                }

                project.build(IncrementalProjectBuilder.FULL_BUILD,
                        PreCompilerBuilder.ID, newArgs, monitor);
            } else if (PostCompilerBuilder.ID.equals(name)) {
                if (includeDependencies == false) {
                    // this is a library, we need to build it!
                    project.build(IncrementalProjectBuilder.FULL_BUILD, name,
                            command.getArguments(), monitor);
                }
            } else {

                project.build(IncrementalProjectBuilder.FULL_BUILD, name,
                        command.getArguments(), monitor);
            }
        }
    }

    /**
     * Force building the project and all its dependencies.
     *
     * @param project the project to build
     * @param kind the build kind
     * @param monitor
     * @throws CoreException
     */
    public static void buildWithDeps(IProject project, int kind, IProgressMonitor monitor)
            throws CoreException {
        // Get list of projects that we depend on
        ProjectState projectState = Sdk.getProjectState(project);

        // this gives us all the library projects, direct and indirect dependencies,
        // so no need to run this method recursively.
        List<IProject> libraries = projectState.getFullLibraryProjects();

        // build dependencies in reverse order to prevent libraries being rebuilt
        // due to refresh of other libraries (they would be compiled in the wrong mode).
        for (int i = libraries.size() - 1 ; i >= 0 ; i--) {
            IProject lib = libraries.get(i);
            lib.build(kind, monitor);
            lib.refreshLocal(IResource.DEPTH_INFINITE, monitor);
        }

        project.build(kind, monitor);
    }


    /**
     * Build project incrementally, including making the final packaging even if it is disabled
     * by default.
     *
     * @param project The project to be built.
     * @param monitor A eclipse runtime progress monitor to be updated by the builders.
     * @throws CoreException
     */
    public static void doFullIncrementalDebugBuild(IProject project, IProgressMonitor monitor)
            throws CoreException {
        // Get list of projects that we depend on
        List<IJavaProject> androidProjectList = new ArrayList<IJavaProject>();
        try {
            androidProjectList = getAndroidProjectDependencies(
                                    BaseProjectHelper.getJavaProject(project));
        } catch (JavaModelException e) {
            AdtPlugin.printErrorToConsole(project, e);
        }
        // Recursively build dependencies
        for (IJavaProject dependency : androidProjectList) {
            doFullIncrementalDebugBuild(dependency.getProject(), monitor);
        }

        // Do an incremental build to pick up all the deltas
        project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor);

        // If the preferences indicate not to use post compiler optimization
        // then the incremental build will have done everything necessary, otherwise,
        // we have to run the final builder manually (if requested).
        if (AdtPrefs.getPrefs().getBuildSkipPostCompileOnFileSave()) {
            // Create the map to pass to the PostC builder
            Map<String, String> args = new TreeMap<String, String>();
            args.put(PostCompilerBuilder.POST_C_REQUESTED, ""); //$NON-NLS-1$

            // call the post compiler manually, forcing FULL_BUILD otherwise Eclipse won't
            // call the builder since the delta is empty.
            project.build(IncrementalProjectBuilder.FULL_BUILD,
                          PostCompilerBuilder.ID, args, monitor);
        }

        // because the post compiler builder does a delayed refresh due to
        // library not picking the refresh up if it's done during the build,
        // we want to force a refresh here as this call is generally asking for
        // a build to use the apk right after the call.
        project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
    }
}
