/*
 * Copyright (C) 2010 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.editors.layout.gle2;

import static com.android.SdkConstants.ATTR_LAYOUT;
import static com.android.SdkConstants.EXT_XML;
import static com.android.SdkConstants.FD_RESOURCES;
import static com.android.SdkConstants.FD_RES_LAYOUT;
import static com.android.SdkConstants.TOOLS_URI;
import static com.android.SdkConstants.VIEW_FRAGMENT;
import static com.android.SdkConstants.VIEW_INCLUDE;
import static com.android.ide.eclipse.adt.AdtConstants.WS_LAYOUTS;
import static com.android.ide.eclipse.adt.AdtConstants.WS_SEP;
import static com.android.resources.ResourceType.LAYOUT;
import static org.eclipse.core.resources.IResourceDelta.ADDED;
import static org.eclipse.core.resources.IResourceDelta.CHANGED;
import static org.eclipse.core.resources.IResourceDelta.CONTENT;
import static org.eclipse.core.resources.IResourceDelta.REMOVED;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.annotations.VisibleForTesting;
import com.android.ide.common.resources.ResourceFile;
import com.android.ide.common.resources.ResourceFolder;
import com.android.ide.common.resources.ResourceItem;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager.IResourceListener;
import com.android.ide.eclipse.adt.io.IFileWrapper;
import com.android.io.IAbstractFile;
import com.android.resources.ResourceType;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.swt.widgets.Display;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * The include finder finds other XML files that are including a given XML file, and does
 * so efficiently (caching results across IDE sessions etc).
 */
@SuppressWarnings("restriction") // XML model
public class IncludeFinder {
    /** Qualified name for the per-project persistent property include-map */
    private final static QualifiedName CONFIG_INCLUDES = new QualifiedName(AdtPlugin.PLUGIN_ID,
            "includes");//$NON-NLS-1$

    /**
     * Qualified name for the per-project non-persistent property storing the
     * {@link IncludeFinder} for this project
     */
    private final static QualifiedName INCLUDE_FINDER = new QualifiedName(AdtPlugin.PLUGIN_ID,
            "includefinder"); //$NON-NLS-1$

    /** Project that the include finder locates includes for */
    private final IProject mProject;

    /** Map from a layout resource name to a set of layouts included by the given resource */
    private Map<String, List<String>> mIncludes = null;

    /**
     * Reverse map of {@link #mIncludes}; points to other layouts that are including a
     * given layouts
     */
    private Map<String, List<String>> mIncludedBy = null;

    /** Flag set during a refresh; ignore updates when this is true */
    private static boolean sRefreshing;

    /** Global (cross-project) resource listener */
    private static ResourceListener sListener;

    /**
     * Constructs an {@link IncludeFinder} for the given project. Don't use this method;
     * use the {@link #get} factory method instead.
     *
     * @param project project to create an {@link IncludeFinder} for
     */
    private IncludeFinder(IProject project) {
        mProject = project;
    }

    /**
     * Returns the {@link IncludeFinder} for the given project
     *
     * @param project the project the finder is associated with
     * @return an {@link IncludeFinder} for the given project, never null
     */
    @NonNull
    public static IncludeFinder get(IProject project) {
        IncludeFinder finder = null;
        try {
            finder = (IncludeFinder) project.getSessionProperty(INCLUDE_FINDER);
        } catch (CoreException e) {
            // Not a problem; we will just create a new one
        }

        if (finder == null) {
            finder = new IncludeFinder(project);
            try {
                project.setSessionProperty(INCLUDE_FINDER, finder);
            } catch (CoreException e) {
                AdtPlugin.log(e, "Can't store IncludeFinder");
            }
        }

        return finder;
    }

    /**
     * Returns a list of resource names that are included by the given resource
     *
     * @param includer the resource name to return included layouts for
     * @return the layouts included by the given resource
     */
    private List<String> getIncludesFrom(String includer) {
        ensureInitialized();

        return mIncludes.get(includer);
    }

    /**
     * Gets the list of all other layouts that are including the given layout.
     *
     * @param included the file that is included
     * @return the files that are including the given file, or null or empty
     */
    @Nullable
    public List<Reference> getIncludedBy(IResource included) {
        ensureInitialized();
        String mapKey = getMapKey(included);
        List<String> result = mIncludedBy.get(mapKey);
        if (result == null) {
            String name = getResourceName(included);
            if (!name.equals(mapKey)) {
                result = mIncludedBy.get(name);
            }
        }

        if (result != null && result.size() > 0) {
            List<Reference> references = new ArrayList<Reference>(result.size());
            for (String s : result) {
                references.add(new Reference(mProject, s));
            }
            return references;
        } else {
            return null;
        }
    }

    /**
     * Returns true if the given resource is included from some other layout in the
     * project
     *
     * @param included the resource to check
     * @return true if the file is included by some other layout
     */
    public boolean isIncluded(IResource included) {
        ensureInitialized();
        String mapKey = getMapKey(included);
        List<String> result = mIncludedBy.get(mapKey);
        if (result == null) {
            String name = getResourceName(included);
            if (!name.equals(mapKey)) {
                result = mIncludedBy.get(name);
            }
        }

        return result != null && result.size() > 0;
    }

    @VisibleForTesting
    /* package */ List<String> getIncludedBy(String included) {
        ensureInitialized();
        return mIncludedBy.get(included);
    }

    /** Initialize the inclusion data structures, if not already done */
    private void ensureInitialized() {
        if (mIncludes == null) {
            // Initialize
            if (!readSettings()) {
                // Couldn't read settings: probably the first time this code is running
                // so there is no known data about includes.

                // Yes, these should be multimaps! If we start using Guava replace
                // these with multimaps.
                mIncludes = new HashMap<String, List<String>>();
                mIncludedBy = new HashMap<String, List<String>>();

                scanProject();
                saveSettings();
            }
        }
    }

    // ----- Persistence -----

    /**
     * Create a String serialization of the includes map. The map attempts to be compact;
     * it strips out the @layout/ prefix, and eliminates the values for empty string
     * values. The map can be restored by calling {@link #decodeMap}. The encoded String
     * will have sorted keys.
     *
     * @param map the map to be serialized
     * @return a serialization (never null) of the given map
     */
    @VisibleForTesting
    public static String encodeMap(Map<String, List<String>> map) {
        StringBuilder sb = new StringBuilder();

        if (map != null) {
            // Process the keys in sorted order rather than just
            // iterating over the entry set to ensure stable output
            List<String> keys = new ArrayList<String>(map.keySet());
            Collections.sort(keys);
            for (String key : keys) {
                List<String> values = map.get(key);

                if (sb.length() > 0) {
                    sb.append(',');
                }
                sb.append(key);
                if (values.size() > 0) {
                    sb.append('=').append('>');
                    sb.append('{');
                    boolean first = true;
                    for (String value : values) {
                        if (first) {
                            first = false;
                        } else {
                            sb.append(',');
                        }
                        sb.append(value);
                    }
                    sb.append('}');
                }
            }
        }

        return sb.toString();
    }

    /**
     * Decodes the encoding (produced by {@link #encodeMap}) back into the original map,
     * modulo any key sorting differences.
     *
     * @param encoded an encoding of a map created by {@link #encodeMap}
     * @return a map corresponding to the encoded values, never null
     */
    @VisibleForTesting
    public static Map<String, List<String>> decodeMap(String encoded) {
        HashMap<String, List<String>> map = new HashMap<String, List<String>>();

        if (encoded.length() > 0) {
            int i = 0;
            int end = encoded.length();

            while (i < end) {

                // Find key range
                int keyBegin = i;
                int keyEnd = i;
                while (i < end) {
                    char c = encoded.charAt(i);
                    if (c == ',') {
                        break;
                    } else if (c == '=') {
                        i += 2; // Skip =>
                        break;
                    }
                    i++;
                    keyEnd = i;
                }

                List<String> values = new ArrayList<String>();
                // Find values
                if (i < end && encoded.charAt(i) == '{') {
                    i++;
                    while (i < end) {
                        int valueBegin = i;
                        int valueEnd = i;
                        char c = 0;
                        while (i < end) {
                            c = encoded.charAt(i);
                            if (c == ',' || c == '}') {
                                valueEnd = i;
                                break;
                            }
                            i++;
                        }
                        if (valueEnd > valueBegin) {
                            values.add(encoded.substring(valueBegin, valueEnd));
                        }

                        if (c == '}') {
                            if (i < end-1 && encoded.charAt(i+1) == ',') {
                                i++;
                            }
                            break;
                        }
                        assert c == ',';
                        i++;
                    }
                }

                String key = encoded.substring(keyBegin, keyEnd);
                map.put(key, values);
                i++;
            }
        }

        return map;
    }

    /**
     * Stores the settings in the persistent project storage.
     */
    private void saveSettings() {
        // Serialize the mIncludes map into a compact String. The mIncludedBy map can be
        // inferred from it.
        String encoded = encodeMap(mIncludes);

        try {
            if (encoded.length() >= 2048) {
                // The maximum length of a setting key is 2KB, according to the javadoc
                // for the project class. It's unlikely that we'll
                // hit this -- even with an average layout root name of 20 characters
                // we can still store over a hundred names. But JUST IN CASE we run
                // into this, we'll clear out the key in this name which means that the
                // information will need to be recomputed in the next IDE session.
                mProject.setPersistentProperty(CONFIG_INCLUDES, null);
            } else {
                String existing = mProject.getPersistentProperty(CONFIG_INCLUDES);
                if (!encoded.equals(existing)) {
                    mProject.setPersistentProperty(CONFIG_INCLUDES, encoded);
                }
            }
        } catch (CoreException e) {
            AdtPlugin.log(e, "Can't store include settings");
        }
    }

    /**
     * Reads previously stored settings from the persistent project storage
     *
     * @return true iff settings were restored from the project
     */
    private boolean readSettings() {
        try {
            String encoded = mProject.getPersistentProperty(CONFIG_INCLUDES);
            if (encoded != null) {
                mIncludes = decodeMap(encoded);

                // Set up a reverse map, pointing from included files to the files that
                // included them
                mIncludedBy = new HashMap<String, List<String>>(2 * mIncludes.size());
                for (Map.Entry<String, List<String>> entry : mIncludes.entrySet()) {
                    // File containing the <include>
                    String includer = entry.getKey();
                    // Files being <include>'ed by the above file
                    List<String> included = entry.getValue();
                    setIncludedBy(includer, included);
                }

                return true;
            }
        } catch (CoreException e) {
            AdtPlugin.log(e, "Can't read include settings");
        }

        return false;
    }

    // ----- File scanning -----

    /**
     * Scan the whole project for XML layout resources that are performing includes.
     */
    private void scanProject() {
        ProjectResources resources = ResourceManager.getInstance().getProjectResources(mProject);
        if (resources != null) {
            Collection<ResourceItem> layouts = resources.getResourceItemsOfType(LAYOUT);
            for (ResourceItem layout : layouts) {
                List<ResourceFile> sources = layout.getSourceFileList();
                for (ResourceFile source : sources) {
                    updateFileIncludes(source, false);
                }
            }

            return;
        }
    }

    /**
     * Scans the given {@link ResourceFile} and if it is a layout resource, updates the
     * includes in it.
     *
     * @param resourceFile the {@link ResourceFile} to be scanned for includes (doesn't
     *            have to be only layout XML files; this method will filter the type)
     * @param singleUpdate true if this is a single file being updated, false otherwise
     *            (e.g. during initial project scanning)
     * @return true if we updated the includes for the resource file
     */
    private boolean updateFileIncludes(ResourceFile resourceFile, boolean singleUpdate) {
        Collection<ResourceType> resourceTypes = resourceFile.getResourceTypes();
        for (ResourceType type : resourceTypes) {
            if (type == ResourceType.LAYOUT) {
                ensureInitialized();

                List<String> includes = Collections.emptyList();
                if (resourceFile.getFile() instanceof IFileWrapper) {
                    IFile file = ((IFileWrapper) resourceFile.getFile()).getIFile();

                    // See if we have an existing XML model for this file; if so, we can
                    // just look directly at the parse tree
                    boolean hadXmlModel = false;
                    IStructuredModel model = null;
                    try {
                        IModelManager modelManager = StructuredModelManager.getModelManager();
                        model = modelManager.getExistingModelForRead(file);
                        if (model instanceof IDOMModel) {
                            IDOMModel domModel = (IDOMModel) model;
                            Document document = domModel.getDocument();
                            includes = findIncludesInDocument(document);
                            hadXmlModel = true;
                        }
                    } finally {
                        if (model != null) {
                            model.releaseFromRead();
                        }
                    }

                    // If no XML model we have to read the XML contents and (possibly) parse it.
                    // The actual file may not exist anymore (e.g. when deleting a layout file
                    // or when the workspace is out of sync.)
                    if (!hadXmlModel) {
                        String xml = AdtPlugin.readFile(file);
                        if (xml != null) {
                            includes = findIncludes(xml);
                        }
                    }
                } else {
                    String xml = AdtPlugin.readFile(resourceFile);
                    if (xml != null) {
                        includes = findIncludes(xml);
                    }
                }

                String key = getMapKey(resourceFile);
                if (includes.equals(getIncludesFrom(key))) {
                    // Common case -- so avoid doing settings flush etc
                    return false;
                }

                boolean detectCycles = singleUpdate;
                setIncluded(key, includes, detectCycles);

                if (singleUpdate) {
                    saveSettings();
                }

                return true;
            }
        }

        return false;
    }

    /**
     * Finds the list of includes in the given XML content. It attempts quickly return
     * empty if the file does not include any include tags; it does this by only parsing
     * if it detects the string &lt;include in the file.
     */
    @VisibleForTesting
    @NonNull
    static List<String> findIncludes(@NonNull String xml) {
        int index = xml.indexOf(ATTR_LAYOUT);
        if (index != -1) {
            return findIncludesInXml(xml);
        }

        return Collections.emptyList();
    }

    /**
     * Parses the given XML content and extracts all the included URLs and returns them
     *
     * @param xml layout XML content to be parsed for includes
     * @return a list of included urls, or null
     */
    @VisibleForTesting
    @NonNull
    static List<String> findIncludesInXml(@NonNull String xml) {
        Document document = DomUtilities.parseDocument(xml, false /*logParserErrors*/);
        if (document != null) {
            return findIncludesInDocument(document);
        }

        return Collections.emptyList();
    }

    /** Searches the given DOM document and returns the list of includes, if any */
    @NonNull
    private static List<String> findIncludesInDocument(@NonNull Document document) {
        List<String> includes = findIncludesInDocument(document, null);
        if (includes == null) {
            includes = Collections.emptyList();
        }
        return includes;
    }

    @Nullable
    private static List<String> findIncludesInDocument(@NonNull Node node,
            @Nullable List<String> urls) {
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            String tag = node.getNodeName();
            boolean isInclude = tag.equals(VIEW_INCLUDE);
            boolean isFragment = tag.equals(VIEW_FRAGMENT);
            if (isInclude || isFragment) {
                Element element = (Element) node;
                String url;
                if (isInclude) {
                    url = element.getAttribute(ATTR_LAYOUT);
                } else {
                    url = element.getAttributeNS(TOOLS_URI, ATTR_LAYOUT);
                }
                if (url.length() > 0) {
                    String resourceName = urlToLocalResource(url);
                    if (resourceName != null) {
                        if (urls == null) {
                            urls = new ArrayList<String>();
                        }
                        urls.add(resourceName);
                    }
                }

            }
        }

        NodeList children = node.getChildNodes();
        for (int i = 0, n = children.getLength(); i < n; i++) {
            urls = findIncludesInDocument(children.item(i), urls);
        }

        return urls;
    }


    /**
     * Returns the layout URL to a local resource name (provided the URL is a local
     * resource, not something in @android etc.) Returns null otherwise.
     */
    private static String urlToLocalResource(String url) {
        if (!url.startsWith("@")) { //$NON-NLS-1$
            return null;
        }
        int typeEnd = url.indexOf('/', 1);
        if (typeEnd == -1) {
            return null;
        }
        int nameBegin = typeEnd + 1;
        int typeBegin = 1;
        int colon = url.lastIndexOf(':', typeEnd);
        if (colon != -1) {
            String packageName = url.substring(typeBegin, colon);
            if ("android".equals(packageName)) { //$NON-NLS-1$
                // Don't want to point to non-local resources
                return null;
            }

            typeBegin = colon + 1;
            assert "layout".equals(url.substring(typeBegin, typeEnd)); //$NON-NLS-1$
        }

        return url.substring(nameBegin);
    }

    /**
     * Record the list of included layouts from the given layout
     *
     * @param includer the layout including other layouts
     * @param included the layouts that were included by the including layout
     * @param detectCycles if true, check for cycles and report them as project errors
     */
    @VisibleForTesting
    /* package */ void setIncluded(String includer, List<String> included, boolean detectCycles) {
        // Remove previously linked inverse mappings
        List<String> oldIncludes = mIncludes.get(includer);
        if (oldIncludes != null && oldIncludes.size() > 0) {
            for (String includee : oldIncludes) {
                List<String> includers = mIncludedBy.get(includee);
                if (includers != null) {
                    includers.remove(includer);
                }
            }
        }

        mIncludes.put(includer, included);
        // Reverse mapping: for included items, point back to including file
        setIncludedBy(includer, included);

        if (detectCycles) {
            detectCycles(includer);
        }
    }

    /** Record the list of included layouts from the given layout */
    private void setIncludedBy(String includer, List<String> included) {
        for (String target : included) {
            List<String> list = mIncludedBy.get(target);
            if (list == null) {
                list = new ArrayList<String>(2); // We don't expect many includes
                mIncludedBy.put(target, list);
            }
            if (!list.contains(includer)) {
                list.add(includer);
            }
        }
    }

    /** Start listening on project resources */
    public static void start() {
        assert sListener == null;
        sListener = new ResourceListener();
        ResourceManager.getInstance().addListener(sListener);
    }

    /** Stop listening on project resources */
    public static void stop() {
        assert sListener != null;
        ResourceManager.getInstance().addListener(sListener);
    }

    private static String getMapKey(ResourceFile resourceFile) {
        IAbstractFile file = resourceFile.getFile();
        String name = file.getName();
        String folderName = file.getParentFolder().getName();
        return getMapKey(folderName, name);
    }

    private static String getMapKey(IResource resourceFile) {
        String folderName = resourceFile.getParent().getName();
        String name = resourceFile.getName();
        return getMapKey(folderName, name);
    }

    private static String getResourceName(IResource resourceFile) {
        String name = resourceFile.getName();
        int baseEnd = name.length() - EXT_XML.length() - 1; // -1: the dot
        if (baseEnd > 0) {
            name = name.substring(0, baseEnd);
        }

        return name;
    }

    private static String getMapKey(String folderName, String name) {
        int baseEnd = name.length() - EXT_XML.length() - 1; // -1: the dot
        if (baseEnd > 0) {
            name = name.substring(0, baseEnd);
        }

        // Create a map key for the given resource file
        // This will map
        //     /res/layout/foo.xml => "foo"
        //     /res/layout-land/foo.xml => "-land/foo"

        if (FD_RES_LAYOUT.equals(folderName)) {
            // Normal case -- keep just the basename
            return name;
        } else {
            // Store the relative path from res/ on down, so
            // /res/layout-land/foo.xml becomes "layout-land/foo"
            //if (folderName.startsWith(FD_LAYOUT)) {
            //    folderName = folderName.substring(FD_LAYOUT.length());
            //}

            return folderName + WS_SEP + name;
        }
    }

    /** Listener of resource file saves, used to update layout inclusion data structures */
    private static class ResourceListener implements IResourceListener {
        @Override
        public void fileChanged(IProject project, ResourceFile file, int eventType) {
            if (sRefreshing) {
                return;
            }

            if ((eventType & (CHANGED | ADDED | REMOVED | CONTENT)) == 0) {
                return;
            }

            IncludeFinder finder = get(project);
            if (finder != null) {
                if (finder.updateFileIncludes(file, true)) {
                    finder.saveSettings();
                }
            }
        }

        @Override
        public void folderChanged(IProject project, ResourceFolder folder, int eventType) {
            // We only care about layout resource files
        }
    }

    // ----- Cycle detection -----

    private void detectCycles(String from) {
        // Perform DFS on the include graph and look for a cycle; if we find one, produce
        // a chain of includes on the way back to show to the user
        if (mIncludes.size() > 0) {
            Set<String> visiting = new HashSet<String>(mIncludes.size());
            String chain = dfs(from, visiting);
            if (chain != null) {
                addError(from, chain);
            } else {
                // Is there an existing error for us to clean up?
                removeErrors(from);
            }
        }
    }

    /** Format to chain include cycles in: a=>b=>c=>d etc */
    private final String CHAIN_FORMAT = "%1$s=>%2$s"; //$NON-NLS-1$

    private String dfs(String from, Set<String> visiting) {
        visiting.add(from);

        List<String> includes = mIncludes.get(from);
        if (includes != null && includes.size() > 0) {
            for (String include : includes) {
                if (visiting.contains(include)) {
                    return String.format(CHAIN_FORMAT, from, include);
                }
                String chain = dfs(include, visiting);
                if (chain != null) {
                    return String.format(CHAIN_FORMAT, from, chain);
                }
            }
        }

        visiting.remove(from);

        return null;
    }

    private void removeErrors(String from) {
        final IResource resource = findResource(from);
        if (resource != null) {
            try {
                final String markerId = IMarker.PROBLEM;

                IMarker[] markers = resource.findMarkers(markerId, true, IResource.DEPTH_ZERO);

                for (final IMarker marker : markers) {
                    String tmpMsg = marker.getAttribute(IMarker.MESSAGE, null);
                    if (tmpMsg == null || tmpMsg.startsWith(MESSAGE)) {
                        // Remove
                        runLater(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    sRefreshing = true;
                                    marker.delete();
                                } catch (CoreException e) {
                                    AdtPlugin.log(e, "Can't delete problem marker");
                                } finally {
                                    sRefreshing = false;
                                }
                            }
                        });
                    }
                }
            } catch (CoreException e) {
                // if we couldn't get the markers, then we just mark the file again
                // (since markerAlreadyExists is initialized to false, we do nothing)
            }
        }
    }

    /** Error message for cycles */
    private static final String MESSAGE = "Found cyclical <include> chain";

    private void addError(String from, String chain) {
        final IResource resource = findResource(from);
        if (resource != null) {
            final String markerId = IMarker.PROBLEM;
            final String message = String.format("%1$s: %2$s", MESSAGE, chain);
            final int lineNumber = 1;
            final int severity = IMarker.SEVERITY_ERROR;

            // check if there's a similar marker already, since aapt is launched twice
            boolean markerAlreadyExists = false;
            try {
                IMarker[] markers = resource.findMarkers(markerId, true, IResource.DEPTH_ZERO);

                for (IMarker marker : markers) {
                    int tmpLine = marker.getAttribute(IMarker.LINE_NUMBER, -1);
                    if (tmpLine != lineNumber) {
                        break;
                    }

                    int tmpSeverity = marker.getAttribute(IMarker.SEVERITY, -1);
                    if (tmpSeverity != severity) {
                        break;
                    }

                    String tmpMsg = marker.getAttribute(IMarker.MESSAGE, null);
                    if (tmpMsg == null || tmpMsg.equals(message) == false) {
                        break;
                    }

                    // if we're here, all the marker attributes are equals, we found it
                    // and exit
                    markerAlreadyExists = true;
                    break;
                }

            } catch (CoreException e) {
                // if we couldn't get the markers, then we just mark the file again
                // (since markerAlreadyExists is initialized to false, we do nothing)
            }

            if (!markerAlreadyExists) {
                runLater(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            sRefreshing = true;

                            // Adding a resource will force a refresh on the file;
                            // ignore these updates
                            BaseProjectHelper.markResource(resource, markerId, message, lineNumber,
                                    severity);
                        } finally {
                            sRefreshing = false;
                        }
                    }
                });
            }
        }
    }

    // FIXME: Find more standard Eclipse way to do this.
    // We need to run marker registration/deletion "later", because when the include
    // scanning is running it's in the middle of resource notification, so the IDE
    // throws an exception
    private static void runLater(Runnable runnable) {
        Display display = Display.findDisplay(Thread.currentThread());
        if (display != null) {
            display.asyncExec(runnable);
        } else {
            AdtPlugin.log(IStatus.WARNING, "Could not find display");
        }
    }

    /**
     * Finds the project resource for the given layout path
     *
     * @param from the resource name
     * @return the {@link IResource}, or null if not found
     */
    private IResource findResource(String from) {
        final IResource resource = mProject.findMember(WS_LAYOUTS + WS_SEP + from + '.' + EXT_XML);
        return resource;
    }

    /**
     * Creates a blank, project-less {@link IncludeFinder} <b>for use by unit tests
     * only</b>
     */
    @VisibleForTesting
    /* package */ static IncludeFinder create() {
        IncludeFinder finder = new IncludeFinder(null);
        finder.mIncludes = new HashMap<String, List<String>>();
        finder.mIncludedBy = new HashMap<String, List<String>>();
        return finder;
    }

    /** A reference to a particular file in the project */
    public static class Reference {
        /** The unique id referencing the file, such as (for res/layout-land/main.xml)
         * "layout-land/main") */
        private final String mId;

        /** The project containing the file */
        private final IProject mProject;

        /** The resource name of the file, such as (for res/layout/main.xml) "main" */
        private String mName;

        /** Creates a new include reference */
        private Reference(IProject project, String id) {
            super();
            mProject = project;
            mId = id;
        }

        /**
         * Returns the id identifying the given file within the project
         *
         * @return the id identifying the given file within the project
         */
        public String getId() {
            return mId;
        }

        /**
         * Returns the {@link IFile} in the project for the given file. May return null if
         * there is an error in locating the file or if the file no longer exists.
         *
         * @return the project file, or null
         */
        public IFile getFile() {
            String reference = mId;
            if (!reference.contains(WS_SEP)) {
                reference = FD_RES_LAYOUT + WS_SEP + reference;
            }

            String projectPath = FD_RESOURCES + WS_SEP + reference + '.' + EXT_XML;
            IResource member = mProject.findMember(projectPath);
            if (member instanceof IFile) {
                return (IFile) member;
            }

            return null;
        }

        /**
         * Returns a description of this reference, suitable to be shown to the user
         *
         * @return a display name for the reference
         */
        public String getDisplayName() {
            // The ID is deliberately kept in a pretty user-readable format but we could
            // consider prepending layout/ on ids that don't have it (to make the display
            // more uniform) or ripping out all layout[-constraint] prefixes out and
            // instead prepending @ etc.
            return mId;
        }

        /**
         * Returns the name of the reference, suitable for resource lookup. For example,
         * for "res/layout/main.xml", as well as for "res/layout-land/main.xml", this
         * would be "main".
         *
         * @return the resource name of the reference
         */
        public String getName() {
            if (mName == null) {
                mName = mId;
                int index = mName.lastIndexOf(WS_SEP);
                if (index != -1) {
                    mName = mName.substring(index + 1);
                }
            }

            return mName;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((mId == null) ? 0 : mId.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Reference other = (Reference) obj;
            if (mId == null) {
                if (other.mId != null)
                    return false;
            } else if (!mId.equals(other.mId))
                return false;
            return true;
        }

        @Override
        public String toString() {
            return "Reference [getId()=" + getId() //$NON-NLS-1$
                    + ", getDisplayName()=" + getDisplayName() //$NON-NLS-1$
                    + ", getName()=" + getName() //$NON-NLS-1$
                    + ", getFile()=" + getFile() + "]"; //$NON-NLS-1$
        }

        /**
         * Creates a reference to the given file
         *
         * @param file the file to create a reference for
         * @return a reference to the given file
         */
        public static Reference create(IFile file) {
            return new Reference(file.getProject(), getMapKey(file));
        }

        /**
         * Returns the resource name of this layout, such as {@code @layout/foo}.
         *
         * @return the resource name
         */
        public String getResourceName() {
            return '@' + FD_RES_LAYOUT + '/' + getName();
        }
    }

    /**
     * Returns a collection of layouts (expressed as resource names, such as
     * {@code @layout/foo} which would be invalid includes in the given layout
     * (because it would introduce a cycle)
     *
     * @param layout the layout file to check for cyclic dependencies from
     * @return a collection of layout resources which cannot be included from
     *         the given layout, never null
     */
    public Collection<String> getInvalidIncludes(IFile layout) {
        IProject project = layout.getProject();
        Reference self = Reference.create(layout);

        // Add anyone who transitively can reach this file via includes.
        LinkedList<Reference> queue = new LinkedList<Reference>();
        List<Reference> invalid = new ArrayList<Reference>();
        queue.add(self);
        invalid.add(self);
        Set<String> seen = new HashSet<String>();
        seen.add(self.getId());
        while (!queue.isEmpty()) {
            Reference reference = queue.removeFirst();
            String refId = reference.getId();

            // Look up both configuration specific includes as well as includes in the
            // base versions
            List<String> included = getIncludedBy(refId);
            if (refId.indexOf('/') != -1) {
                List<String> baseIncluded = getIncludedBy(reference.getName());
                if (included == null) {
                    included = baseIncluded;
                } else if (baseIncluded != null) {
                    included = new ArrayList<String>(included);
                    included.addAll(baseIncluded);
                }
            }

            if (included != null && included.size() > 0) {
                for (String id : included) {
                    if (!seen.contains(id)) {
                        seen.add(id);
                        Reference ref = new Reference(project, id);
                        invalid.add(ref);
                        queue.addLast(ref);
                    }
                }
            }
        }

        List<String> result = new ArrayList<String>();
        for (Reference reference : invalid) {
            result.add(reference.getResourceName());
        }

        return result;
    }
}
