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

import static com.android.SdkConstants.ANDROID_NS_NAME;
import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ANDROID_WIDGET_PREFIX;
import static com.android.SdkConstants.ATTR_ID;
import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT;
import static com.android.SdkConstants.ATTR_LAYOUT_RESOURCE_PREFIX;
import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH;
import static com.android.SdkConstants.ID_PREFIX;
import static com.android.SdkConstants.NEW_ID_PREFIX;
import static com.android.SdkConstants.XMLNS;
import static com.android.SdkConstants.XMLNS_PREFIX;

import com.android.annotations.NonNull;
import com.android.annotations.VisibleForTesting;
import com.android.ide.common.xml.XmlFormatStyle;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.formatting.EclipseXmlFormatPreferences;
import com.android.ide.eclipse.adt.internal.editors.formatting.EclipseXmlPrettyPrinter;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationDescription;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart;
import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.utils.Pair;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
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.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.ChangeDescriptor;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * Parent class for the various visual refactoring operations; contains shared
 * implementations needed by most of them
 */
@SuppressWarnings("restriction") // XML model
public abstract class VisualRefactoring extends Refactoring {
    private static final String KEY_FILE = "file";                      //$NON-NLS-1$
    private static final String KEY_PROJECT = "proj";                   //$NON-NLS-1$
    private static final String KEY_SEL_START = "sel-start";            //$NON-NLS-1$
    private static final String KEY_SEL_END = "sel-end";                //$NON-NLS-1$

    protected final IFile mFile;
    protected final LayoutEditorDelegate mDelegate;
    protected final IProject mProject;
    protected int mSelectionStart = -1;
    protected int mSelectionEnd = -1;
    protected final List<Element> mElements;
    protected final ITreeSelection mTreeSelection;
    protected final ITextSelection mSelection;
    /** Same as {@link #mSelectionStart} but not adjusted to element edges */
    protected int mOriginalSelectionStart = -1;
    /** Same as {@link #mSelectionEnd} but not adjusted to element edges */
    protected int mOriginalSelectionEnd = -1;

    protected final Map<Element, String> mGeneratedIdMap = new HashMap<Element, String>();
    protected final Set<String> mGeneratedIds = new HashSet<String>();

    protected List<Change> mChanges;
    private String mAndroidNamespacePrefix;

    /**
     * This constructor is solely used by {@link VisualRefactoringDescriptor},
     * to replay a previous refactoring.
     * @param arguments argument map created by #createArgumentMap.
     */
    VisualRefactoring(Map<String, String> arguments) {
        IPath path = Path.fromPortableString(arguments.get(KEY_PROJECT));
        mProject = (IProject) ResourcesPlugin.getWorkspace().getRoot().findMember(path);
        path = Path.fromPortableString(arguments.get(KEY_FILE));
        mFile = (IFile) ResourcesPlugin.getWorkspace().getRoot().findMember(path);
        mSelectionStart = Integer.parseInt(arguments.get(KEY_SEL_START));
        mSelectionEnd = Integer.parseInt(arguments.get(KEY_SEL_END));
        mOriginalSelectionStart = mSelectionStart;
        mOriginalSelectionEnd = mSelectionEnd;
        mDelegate = null;
        mElements = null;
        mSelection = null;
        mTreeSelection = null;
    }

    @VisibleForTesting
    VisualRefactoring(List<Element> elements, LayoutEditorDelegate delegate) {
        mElements = elements;
        mDelegate = delegate;

        mFile = delegate != null ? delegate.getEditor().getInputFile() : null;
        mProject = delegate != null ? delegate.getEditor().getProject() : null;
        mSelectionStart = 0;
        mSelectionEnd = 0;
        mOriginalSelectionStart = 0;
        mOriginalSelectionEnd = 0;
        mSelection = null;
        mTreeSelection = null;

        int end = Integer.MIN_VALUE;
        int start = Integer.MAX_VALUE;
        for (Element element : elements) {
            if (element instanceof IndexedRegion) {
                IndexedRegion region = (IndexedRegion) element;
                start = Math.min(start, region.getStartOffset());
                end = Math.max(end, region.getEndOffset());
            }
        }
        if (start >= 0) {
            mSelectionStart = start;
            mSelectionEnd = end;
            mOriginalSelectionStart = start;
            mOriginalSelectionEnd = end;
        }
    }

    public VisualRefactoring(IFile file, LayoutEditorDelegate editor, ITextSelection selection,
            ITreeSelection treeSelection) {
        mFile = file;
        mDelegate = editor;
        mProject = file.getProject();
        mSelection = selection;
        mTreeSelection = treeSelection;

        // Initialize mSelectionStart and mSelectionEnd based on the selection context, which
        // is either a treeSelection (when invoked from the layout editor or the outline), or
        // a selection (when invoked from an XML editor)
        if (treeSelection != null) {
            int end = Integer.MIN_VALUE;
            int start = Integer.MAX_VALUE;
            for (TreePath path : treeSelection.getPaths()) {
                Object lastSegment = path.getLastSegment();
                if (lastSegment instanceof CanvasViewInfo) {
                    CanvasViewInfo viewInfo = (CanvasViewInfo) lastSegment;
                    UiViewElementNode uiNode = viewInfo.getUiViewNode();
                    if (uiNode == null) {
                        continue;
                    }
                    Node xmlNode = uiNode.getXmlNode();
                    if (xmlNode instanceof IndexedRegion) {
                        IndexedRegion region = (IndexedRegion) xmlNode;

                        start = Math.min(start, region.getStartOffset());
                        end = Math.max(end, region.getEndOffset());
                    }
                }
            }
            if (start >= 0) {
                mSelectionStart = start;
                mSelectionEnd = end;
                mOriginalSelectionStart = mSelectionStart;
                mOriginalSelectionEnd = mSelectionEnd;
            }
            if (selection != null) {
                mOriginalSelectionStart = selection.getOffset();
                mOriginalSelectionEnd = mOriginalSelectionStart + selection.getLength();
            }
        } else if (selection != null) {
            // TODO: update selection to boundaries!
            mSelectionStart = selection.getOffset();
            mSelectionEnd = mSelectionStart + selection.getLength();
            mOriginalSelectionStart = mSelectionStart;
            mOriginalSelectionEnd = mSelectionEnd;
        }

        mElements = initElements();
    }

    @NonNull
    protected abstract List<Change> computeChanges(IProgressMonitor monitor);

    @Override
    public RefactoringStatus checkFinalConditions(IProgressMonitor monitor) throws CoreException,
            OperationCanceledException {
        RefactoringStatus status = new RefactoringStatus();
        mChanges = new ArrayList<Change>();
        try {
            monitor.beginTask("Checking post-conditions...", 5);

            // Reset state for each computeChanges call, in case the user goes back
            // and forth in the refactoring wizard
            mGeneratedIdMap.clear();
            mGeneratedIds.clear();
            List<Change> changes = computeChanges(monitor);
            mChanges.addAll(changes);

            monitor.worked(1);
        } finally {
            monitor.done();
        }

        return status;
    }

    @Override
    public Change createChange(IProgressMonitor monitor) throws CoreException,
            OperationCanceledException {
        try {
            monitor.beginTask("Applying changes...", 1);

            CompositeChange change = new CompositeChange(
                    getName(),
                    mChanges.toArray(new Change[mChanges.size()])) {
                @Override
                public ChangeDescriptor getDescriptor() {
                    VisualRefactoringDescriptor desc = createDescriptor();
                    return new RefactoringChangeDescriptor(desc);
                }
            };

            monitor.worked(1);
            return change;

        } finally {
            monitor.done();
        }
    }

    protected abstract VisualRefactoringDescriptor createDescriptor();

    protected Map<String, String> createArgumentMap() {
        HashMap<String, String> args = new HashMap<String, String>();
        args.put(KEY_PROJECT, mProject.getFullPath().toPortableString());
        args.put(KEY_FILE, mFile.getFullPath().toPortableString());
        args.put(KEY_SEL_START, Integer.toString(mSelectionStart));
        args.put(KEY_SEL_END, Integer.toString(mSelectionEnd));

        return args;
    }

    IFile getFile() {
        return mFile;
    }

    // ---- Shared functionality ----


    protected void openFile(IFile file) {
        GraphicalEditorPart graphicalEditor = mDelegate.getGraphicalEditor();
        IFile leavingFile = graphicalEditor.getEditedFile();

        try {
            // Duplicate the current state into the newly created file
            String state = ConfigurationDescription.getDescription(leavingFile);

            // TODO: Look for a ".NoTitleBar.Fullscreen" theme version of the current
            // theme to show.

            file.setSessionProperty(GraphicalEditorPart.NAME_INITIAL_STATE, state);
        } catch (CoreException e) {
            // pass
        }

        /* TBD: "Show Included In" if supported.
         * Not sure if this is a good idea.
        if (graphicalEditor.renderingSupports(Capability.EMBEDDED_LAYOUT)) {
            try {
                Reference include = Reference.create(graphicalEditor.getEditedFile());
                file.setSessionProperty(GraphicalEditorPart.NAME_INCLUDE, include);
            } catch (CoreException e) {
                // pass - worst that can happen is that we don't start with inclusion
            }
        }
        */

        try {
            IEditorPart part =
                IDE.openEditor(mDelegate.getEditor().getEditorSite().getPage(), file);
            if (part instanceof AndroidXmlEditor && AdtPrefs.getPrefs().getFormatGuiXml()) {
                AndroidXmlEditor newEditor = (AndroidXmlEditor) part;
                newEditor.reformatDocument();
            }
        } catch (PartInitException e) {
            AdtPlugin.log(e, "Can't open new included layout");
        }
    }


    /** Produce a list of edits to replace references to the given id with the given new id */
    protected static List<TextEdit> replaceIds(String androidNamePrefix,
            IStructuredDocument doc, int skipStart, int skipEnd,
            String rootId, String referenceId) {
        if (rootId == null) {
            return Collections.emptyList();
        }

        // We need to search for either @+id/ or @id/
        String match1 = rootId;
        String match2;
        if (match1.startsWith(ID_PREFIX)) {
            match2 = '"' + NEW_ID_PREFIX + match1.substring(ID_PREFIX.length()) + '"';
            match1 = '"' + match1 + '"';
        } else if (match1.startsWith(NEW_ID_PREFIX)) {
            match2 = '"' + ID_PREFIX + match1.substring(NEW_ID_PREFIX.length()) + '"';
            match1 = '"' + match1 + '"';
        } else {
            return Collections.emptyList();
        }

        String namePrefix = androidNamePrefix + ':' + ATTR_LAYOUT_RESOURCE_PREFIX;
        List<TextEdit> edits = new ArrayList<TextEdit>();

        IStructuredDocumentRegion region = doc.getFirstStructuredDocumentRegion();
        for (; region != null; region = region.getNext()) {
            ITextRegionList list = region.getRegions();
            int regionStart = region.getStart();

            // Look at all attribute values and look for an id reference match
            String attributeName = ""; //$NON-NLS-1$
            for (int j = 0; j < region.getNumberOfRegions(); j++) {
                ITextRegion subRegion = list.get(j);
                String type = subRegion.getType();
                if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(type)) {
                    attributeName = region.getText(subRegion);
                } else if (DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(type)) {
                    // Only replace references in layout attributes
                    if (!attributeName.startsWith(namePrefix)) {
                        continue;
                    }
                    // Skip occurrences in the given skip range
                    int subRegionStart = regionStart + subRegion.getStart();
                    if (subRegionStart >= skipStart && subRegionStart <= skipEnd) {
                        continue;
                    }

                    String attributeValue = region.getText(subRegion);
                    if (attributeValue.equals(match1) || attributeValue.equals(match2)) {
                        int start = subRegionStart + 1; // skip quote
                        int end = start + rootId.length();

                        edits.add(new ReplaceEdit(start, end - start, referenceId));
                    }
                }
            }
        }

        return edits;
    }

    /** Get the id of the root selected element, if any */
    protected String getRootId() {
        Element primary = getPrimaryElement();
        if (primary != null) {
            String oldId = primary.getAttributeNS(ANDROID_URI, ATTR_ID);
            // id null check for https://bugs.eclipse.org/bugs/show_bug.cgi?id=272378
            if (oldId != null && oldId.length() > 0) {
                return oldId;
            }
        }

        return null;
    }

    protected String getAndroidNamespacePrefix() {
        if (mAndroidNamespacePrefix == null) {
            List<Attr> attributeNodes = findNamespaceAttributes();
            for (Node attributeNode : attributeNodes) {
                String prefix = attributeNode.getPrefix();
                if (XMLNS.equals(prefix)) {
                    String name = attributeNode.getNodeName();
                    String value = attributeNode.getNodeValue();
                    if (value.equals(ANDROID_URI)) {
                        mAndroidNamespacePrefix = name;
                        if (mAndroidNamespacePrefix.startsWith(XMLNS_PREFIX)) {
                            mAndroidNamespacePrefix =
                                mAndroidNamespacePrefix.substring(XMLNS_PREFIX.length());
                        }
                    }
                }
            }

            if (mAndroidNamespacePrefix == null) {
                mAndroidNamespacePrefix = ANDROID_NS_NAME;
            }
        }

        return mAndroidNamespacePrefix;
    }

    protected static String getAndroidNamespacePrefix(Document document) {
        String nsPrefix = null;
        List<Attr> attributeNodes = findNamespaceAttributes(document);
        for (Node attributeNode : attributeNodes) {
            String prefix = attributeNode.getPrefix();
            if (XMLNS.equals(prefix)) {
                String name = attributeNode.getNodeName();
                String value = attributeNode.getNodeValue();
                if (value.equals(ANDROID_URI)) {
                    nsPrefix = name;
                    if (nsPrefix.startsWith(XMLNS_PREFIX)) {
                        nsPrefix =
                            nsPrefix.substring(XMLNS_PREFIX.length());
                    }
                }
            }
        }

        if (nsPrefix == null) {
            nsPrefix = ANDROID_NS_NAME;
        }

        return nsPrefix;
    }

    protected List<Attr> findNamespaceAttributes() {
        Document document = getDomDocument();
        return findNamespaceAttributes(document);
    }

    protected static List<Attr> findNamespaceAttributes(Document document) {
        if (document != null) {
            Element root = document.getDocumentElement();
            return findNamespaceAttributes(root);
        }

        return Collections.emptyList();
    }

    protected static List<Attr> findNamespaceAttributes(Node root) {
        List<Attr> result = new ArrayList<Attr>();
        NamedNodeMap attributes = root.getAttributes();
        for (int i = 0, n = attributes.getLength(); i < n; i++) {
            Node attributeNode = attributes.item(i);

            String prefix = attributeNode.getPrefix();
            if (XMLNS.equals(prefix)) {
                result.add((Attr) attributeNode);
            }
        }

        return result;
    }

    protected List<Attr> findLayoutAttributes(Node root) {
        List<Attr> result = new ArrayList<Attr>();
        NamedNodeMap attributes = root.getAttributes();
        for (int i = 0, n = attributes.getLength(); i < n; i++) {
            Node attributeNode = attributes.item(i);

            String name = attributeNode.getLocalName();
            if (name.startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)
                    && ANDROID_URI.equals(attributeNode.getNamespaceURI())) {
                result.add((Attr) attributeNode);
            }
        }

        return result;
    }

    protected String insertNamespace(String xmlText, String namespaceDeclarations) {
        // Insert namespace declarations into the extracted XML fragment
        int firstSpace = xmlText.indexOf(' ');
        int elementEnd = xmlText.indexOf('>');
        int insertAt;
        if (firstSpace != -1 && firstSpace < elementEnd) {
            insertAt = firstSpace;
        } else {
            insertAt = elementEnd;
        }
        xmlText = xmlText.substring(0, insertAt) + namespaceDeclarations
                + xmlText.substring(insertAt);

        return xmlText;
    }

    /** Remove sections of the document that correspond to top level layout attributes;
     * these are placed on the include element instead */
    protected String stripTopLayoutAttributes(Element primary, int start, String xml) {
        if (primary != null) {
            // List of attributes to remove
            List<IndexedRegion> skip = new ArrayList<IndexedRegion>();
            NamedNodeMap attributes = primary.getAttributes();
            for (int i = 0, n = attributes.getLength(); i < n; i++) {
                Node attr = attributes.item(i);
                String name = attr.getLocalName();
                if (name.startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)
                        && ANDROID_URI.equals(attr.getNamespaceURI())) {
                    if (name.equals(ATTR_LAYOUT_WIDTH) || name.equals(ATTR_LAYOUT_HEIGHT)) {
                        // These are special and are left in
                        continue;
                    }

                    if (attr instanceof IndexedRegion) {
                        skip.add((IndexedRegion) attr);
                    }
                }
            }
            if (skip.size() > 0) {
                Collections.sort(skip, new Comparator<IndexedRegion>() {
                    // Sort in start order
                    @Override
                    public int compare(IndexedRegion r1, IndexedRegion r2) {
                        return r1.getStartOffset() - r2.getStartOffset();
                    }
                });

                // Successively cut out the various layout attributes
                // TODO remove adjacent whitespace too (but not newlines, unless they
                // are newly adjacent)
                StringBuilder sb = new StringBuilder(xml.length());
                int nextStart = 0;

                // Copy out all the sections except the skip sections
                for (IndexedRegion r : skip) {
                    int regionStart = r.getStartOffset();
                    // Adjust to string offsets since we've copied the string out of
                    // the document
                    regionStart -= start;

                    sb.append(xml.substring(nextStart, regionStart));

                    nextStart = regionStart + r.getLength();
                }
                if (nextStart < xml.length()) {
                    sb.append(xml.substring(nextStart));
                }

                return sb.toString();
            }
        }

        return xml;
    }

    protected static String getIndent(String line, int max) {
        int i = 0;
        int n = Math.min(max, line.length());
        for (; i < n; i++) {
            char c = line.charAt(i);
            if (!Character.isWhitespace(c)) {
                return line.substring(0, i);
            }
        }

        if (n < line.length()) {
            return line.substring(0, n);
        } else {
            return line;
        }
    }

    protected static String dedent(String xml) {
        String[] lines = xml.split("\n"); //$NON-NLS-1$
        if (lines.length < 2) {
            // The first line never has any indentation since we copy it out from the
            // element start index
            return xml;
        }

        String indentPrefix = getIndent(lines[1], lines[1].length());
        for (int i = 2, n = lines.length; i < n; i++) {
            String line = lines[i];

            // Ignore blank lines
            if (line.trim().length() == 0) {
                continue;
            }

            indentPrefix = getIndent(line, indentPrefix.length());

            if (indentPrefix.length() == 0) {
                return xml;
            }
        }

        StringBuilder sb = new StringBuilder();
        for (String line : lines) {
            if (line.startsWith(indentPrefix)) {
                sb.append(line.substring(indentPrefix.length()));
            } else {
                sb.append(line);
            }
            sb.append('\n');
        }
        return sb.toString();
    }

    protected String getText(int start, int end) {
        try {
            IStructuredDocument document = mDelegate.getEditor().getStructuredDocument();
            return document.get(start, end - start);
        } catch (BadLocationException e) {
            // the region offset was invalid. ignore.
            return null;
        }
    }

    protected List<Element> getElements() {
        return mElements;
    }

    protected List<Element> initElements() {
        List<Element> nodes = new ArrayList<Element>();

        assert mTreeSelection == null || mSelection == null :
            "treeSel= " + mTreeSelection + ", sel=" + mSelection;

        // Initialize mSelectionStart and mSelectionEnd based on the selection context, which
        // is either a treeSelection (when invoked from the layout editor or the outline), or
        // a selection (when invoked from an XML editor)
        if (mTreeSelection != null) {
            int end = Integer.MIN_VALUE;
            int start = Integer.MAX_VALUE;
            for (TreePath path : mTreeSelection.getPaths()) {
                Object lastSegment = path.getLastSegment();
                if (lastSegment instanceof CanvasViewInfo) {
                    CanvasViewInfo viewInfo = (CanvasViewInfo) lastSegment;
                    UiViewElementNode uiNode = viewInfo.getUiViewNode();
                    if (uiNode == null) {
                        continue;
                    }
                    Node xmlNode = uiNode.getXmlNode();
                    if (xmlNode instanceof Element) {
                        Element element = (Element) xmlNode;
                        nodes.add(element);
                        IndexedRegion region = getRegion(element);
                        start = Math.min(start, region.getStartOffset());
                        end = Math.max(end, region.getEndOffset());
                    }
                }
            }
            if (start >= 0) {
                mSelectionStart = start;
                mSelectionEnd = end;
            }
        } else if (mSelection != null) {
            mSelectionStart = mSelection.getOffset();
            mSelectionEnd = mSelectionStart + mSelection.getLength();
            mOriginalSelectionStart = mSelectionStart;
            mOriginalSelectionEnd = mSelectionEnd;

            // Figure out the range of selected nodes from the document offsets
            IStructuredDocument doc = mDelegate.getEditor().getStructuredDocument();
            Pair<Element, Element> range = DomUtilities.getElementRange(doc,
                    mSelectionStart, mSelectionEnd);
            if (range != null) {
                Element first = range.getFirst();
                Element last = range.getSecond();

                // Adjust offsets to get rid of surrounding text nodes (if you happened
                // to select a text range and included whitespace on either end etc)
                mSelectionStart = getRegion(first).getStartOffset();
                mSelectionEnd = getRegion(last).getEndOffset();

                if (mSelectionStart > mSelectionEnd) {
                    int tmp = mSelectionStart;
                    mSelectionStart = mSelectionEnd;
                    mSelectionEnd = tmp;
                }

                if (first == last) {
                    nodes.add(first);
                } else if (first.getParentNode() == last.getParentNode()) {
                    // Add the range
                    Node node = first;
                    while (node != null) {
                        if (node instanceof Element) {
                            nodes.add((Element) node);
                        }
                        if (node == last) {
                            break;
                        }
                        node = node.getNextSibling();
                    }
                } else {
                    // Different parents: this means we have an uneven selection, selecting
                    // elements from different levels. We can't extract ranges like that.
                }
            }
        } else {
            assert false;
        }

        // Make sure that the list of elements is unique
        //Set<Element> seen = new HashSet<Element>();
        //for (Element element : nodes) {
        //   assert !seen.contains(element) : element;
        //   seen.add(element);
        //}

        return nodes;
    }

    protected Element getPrimaryElement() {
        List<Element> elements = getElements();
        if (elements != null && elements.size() == 1) {
            return elements.get(0);
        }

        return null;
    }

    protected Document getDomDocument() {
        if (mDelegate.getUiRootNode() != null) {
            return mDelegate.getUiRootNode().getXmlDocument();
        } else {
            return getElements().get(0).getOwnerDocument();
        }
    }

    protected List<CanvasViewInfo> getSelectedViewInfos() {
        List<CanvasViewInfo> infos = new ArrayList<CanvasViewInfo>();
        if (mTreeSelection != null) {
            for (TreePath path : mTreeSelection.getPaths()) {
                Object lastSegment = path.getLastSegment();
                if (lastSegment instanceof CanvasViewInfo) {
                    infos.add((CanvasViewInfo) lastSegment);
                }
            }
        }
        return infos;
    }

    protected boolean validateNotEmpty(List<CanvasViewInfo> infos, RefactoringStatus status) {
        if (infos.size() == 0) {
            status.addFatalError("No selection to extract");
            return false;
        }

        return true;
    }

    protected boolean validateNotRoot(List<CanvasViewInfo> infos, RefactoringStatus status) {
        for (CanvasViewInfo info : infos) {
            if (info.isRoot()) {
                status.addFatalError("Cannot refactor the root");
                return false;
            }
        }

        return true;
    }

    protected boolean validateContiguous(List<CanvasViewInfo> infos, RefactoringStatus status) {
        if (infos.size() > 1) {
            // All elements must be siblings (e.g. same parent)
            List<UiViewElementNode> nodes = new ArrayList<UiViewElementNode>(infos
                    .size());
            for (CanvasViewInfo info : infos) {
                UiViewElementNode node = info.getUiViewNode();
                if (node != null) {
                    nodes.add(node);
                }
            }
            if (nodes.size() == 0) {
                status.addFatalError("No selected views");
                return false;
            }

            UiElementNode parent = nodes.get(0).getUiParent();
            for (UiViewElementNode node : nodes) {
                if (parent != node.getUiParent()) {
                    status.addFatalError("The selected elements must be adjacent");
                    return false;
                }
            }
            // Ensure that the siblings are contiguous; no gaps.
            // If we've selected all the children of the parent then we don't need
            // to look.
            List<UiElementNode> siblings = parent.getUiChildren();
            if (siblings.size() != nodes.size()) {
                Set<UiViewElementNode> nodeSet = new HashSet<UiViewElementNode>(nodes);
                boolean inRange = false;
                int remaining = nodes.size();
                for (UiElementNode node : siblings) {
                    boolean in = nodeSet.contains(node);
                    if (in) {
                        remaining--;
                        if (remaining == 0) {
                            break;
                        }
                        inRange = true;
                    } else if (inRange) {
                        status.addFatalError("The selected elements must be adjacent");
                        return false;
                    }
                }
            }
        }

        return true;
    }

    /**
     * Updates the given element with a new name if the current id reflects the old
     * element type. If the name was changed, it will return the new name.
     */
    protected String ensureIdMatchesType(Element element, String newType, MultiTextEdit rootEdit) {
        String oldType = element.getTagName();
        if (oldType.indexOf('.') == -1) {
            oldType = ANDROID_WIDGET_PREFIX + oldType;
        }
        String oldTypeBase = oldType.substring(oldType.lastIndexOf('.') + 1);
        String id = getId(element);
        if (id == null || id.length() == 0
                || id.toLowerCase(Locale.US).contains(oldTypeBase.toLowerCase(Locale.US))) {
            String newTypeBase = newType.substring(newType.lastIndexOf('.') + 1);
            return ensureHasId(rootEdit, element, newTypeBase);
        }

        return null;
    }

    /**
     * Returns the {@link IndexedRegion} for the given node
     *
     * @param node the node to look up the region for
     * @return the corresponding region, or null
     */
    public static IndexedRegion getRegion(Node node) {
        if (node instanceof IndexedRegion) {
            return (IndexedRegion) node;
        }

        return null;
    }

    protected String ensureHasId(MultiTextEdit rootEdit, Element element, String prefix) {
        return ensureHasId(rootEdit, element, prefix, true);
    }

    protected String ensureHasId(MultiTextEdit rootEdit, Element element, String prefix,
            boolean apply) {
        String id = mGeneratedIdMap.get(element);
        if (id != null) {
            return NEW_ID_PREFIX + id;
        }

        if (!element.hasAttributeNS(ANDROID_URI, ATTR_ID)
                || (prefix != null && !getId(element).startsWith(prefix))) {
            id = DomUtilities.getFreeWidgetId(element, mGeneratedIds, prefix);
            // Make sure we don't use this one again
            mGeneratedIds.add(id);
            mGeneratedIdMap.put(element, id);
            id = NEW_ID_PREFIX + id;
            if (apply) {
                setAttribute(rootEdit, element,
                        ANDROID_URI, getAndroidNamespacePrefix(), ATTR_ID, id);
            }
            return id;
        }

        return getId(element);
    }

    protected int getFirstAttributeOffset(Element element) {
        IndexedRegion region = getRegion(element);
        if (region != null) {
            int startOffset = region.getStartOffset();
            int endOffset = region.getEndOffset();
            String text = getText(startOffset, endOffset);
            String name = element.getLocalName();
            int nameOffset = text.indexOf(name);
            if (nameOffset != -1) {
                return startOffset + nameOffset + name.length();
            }
        }

        return -1;
    }

    /**
     * Returns the id of the given element
     *
     * @param element the element to look up the id for
     * @return the corresponding id, or an empty string (should not be null
     *         according to the DOM API, but has been observed to be null on
     *         some versions of Eclipse)
     */
    public static String getId(Element element) {
        return element.getAttributeNS(ANDROID_URI, ATTR_ID);
    }

    protected String ensureNewId(String id) {
        if (id != null && id.length() > 0) {
            if (id.startsWith(ID_PREFIX)) {
                id = NEW_ID_PREFIX + id.substring(ID_PREFIX.length());
            } else if (!id.startsWith(NEW_ID_PREFIX)) {
                id = NEW_ID_PREFIX + id;
            }
        } else {
            id = null;
        }

        return id;
    }

    protected String getViewClass(String fqcn) {
        // Don't include android.widget. as a package prefix in layout files
        if (fqcn.startsWith(ANDROID_WIDGET_PREFIX)) {
            fqcn = fqcn.substring(ANDROID_WIDGET_PREFIX.length());
        }

        return fqcn;
    }

    protected void setAttribute(MultiTextEdit rootEdit, Element element,
            String attributeUri,
            String attributePrefix, String attributeName, String attributeValue) {
        int offset = getFirstAttributeOffset(element);
        if (offset != -1) {
            if (element.hasAttributeNS(attributeUri, attributeName)) {
                replaceAttributeDeclaration(rootEdit, offset, element, attributePrefix,
                        attributeUri, attributeName, attributeValue);
            } else {
                addAttributeDeclaration(rootEdit, offset, attributePrefix, attributeName,
                        attributeValue);
            }
        }
    }

    private void addAttributeDeclaration(MultiTextEdit rootEdit, int offset,
            String attributePrefix, String attributeName, String attributeValue) {
        StringBuilder sb = new StringBuilder();
        sb.append(' ');

        if (attributePrefix != null) {
            sb.append(attributePrefix).append(':');
        }
        sb.append(attributeName).append('=').append('"');
        sb.append(attributeValue).append('"');

        InsertEdit setAttribute = new InsertEdit(offset, sb.toString());
        rootEdit.addChild(setAttribute);
    }

    /** Replaces the value declaration of the given attribute */
    private void replaceAttributeDeclaration(MultiTextEdit rootEdit, int offset,
            Element element, String attributePrefix, String attributeUri,
            String attributeName, String attributeValue) {
        // Find attribute value and replace it
        IStructuredModel model = mDelegate.getEditor().getModelForRead();
        try {
            IStructuredDocument doc = model.getStructuredDocument();

            IStructuredDocumentRegion region = doc.getRegionAtCharacterOffset(offset);
            ITextRegionList list = region.getRegions();
            int regionStart = region.getStart();

            int valueStart = -1;
            boolean useNextValue = false;
            String targetName = attributePrefix != null
                ? attributePrefix + ':' + attributeName : attributeName;

            // Look at all attribute values and look for an id reference match
            for (int j = 0; j < region.getNumberOfRegions(); j++) {
                ITextRegion subRegion = list.get(j);
                String type = subRegion.getType();
                if (DOMRegionContext.XML_TAG_ATTRIBUTE_NAME.equals(type)) {
                    // What about prefix?
                    if (targetName.equals(region.getText(subRegion))) {
                        useNextValue = true;
                    }
                } else if (DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(type)) {
                    if (useNextValue) {
                        valueStart = regionStart + subRegion.getStart();
                        break;
                    }
                }
            }

            if (valueStart != -1) {
                String oldValue = element.getAttributeNS(attributeUri, attributeName);
                int start = valueStart + 1; // Skip opening "
                ReplaceEdit setAttribute = new ReplaceEdit(start, oldValue.length(),
                        attributeValue);
                try {
                    rootEdit.addChild(setAttribute);
                } catch (MalformedTreeException mte) {
                    AdtPlugin.log(mte, "Could not replace attribute %1$s with %2$s",
                            attributeName, attributeValue);
                    throw mte;
                }
            }
        } finally {
            model.releaseFromRead();
        }
    }

    /** Strips out the given attribute, if defined */
    protected void removeAttribute(MultiTextEdit rootEdit, Element element, String uri,
            String attributeName) {
        if (element.hasAttributeNS(uri, attributeName)) {
            Attr attribute = element.getAttributeNodeNS(uri, attributeName);
            removeAttribute(rootEdit, attribute);
        }
    }

    /** Strips out the given attribute, if defined */
    protected void removeAttribute(MultiTextEdit rootEdit, Attr attribute) {
        IndexedRegion region = getRegion(attribute);
        if (region != null) {
            int startOffset = region.getStartOffset();
            int endOffset = region.getEndOffset();
            DeleteEdit deletion = new DeleteEdit(startOffset, endOffset - startOffset);
            rootEdit.addChild(deletion);
        }
    }


    /**
     * Removes the given element's opening and closing tags (including all of its
     * attributes) but leaves any children alone
     *
     * @param rootEdit the multi edit to add the removal operation to
     * @param element the element to delete the open and closing tags for
     * @param skip a list of elements that should not be modified (for example because they
     *    are targeted for deletion)
     *
     * TODO: Rename this to "unwrap" ? And allow for handling nested deletions.
     */
    protected void removeElementTags(MultiTextEdit rootEdit, Element element, List<Element> skip,
            boolean changeIndentation) {
        IndexedRegion elementRegion = getRegion(element);
        if (elementRegion == null) {
            return;
        }

        // Look for the opening tag
        IStructuredModel model = mDelegate.getEditor().getModelForRead();
        try {
            int startLineInclusive = -1;
            int endLineInclusive = -1;
            IStructuredDocument doc = model.getStructuredDocument();
            if (doc != null) {
                int start = elementRegion.getStartOffset();
                IStructuredDocumentRegion region = doc.getRegionAtCharacterOffset(start);
                ITextRegionList list = region.getRegions();
                int regionStart = region.getStart();
                int startOffset = regionStart;
                for (int j = 0; j < region.getNumberOfRegions(); j++) {
                    ITextRegion subRegion = list.get(j);
                    String type = subRegion.getType();
                    if (DOMRegionContext.XML_TAG_OPEN.equals(type)) {
                        startOffset = regionStart + subRegion.getStart();
                    } else if (DOMRegionContext.XML_TAG_CLOSE.equals(type)) {
                        int endOffset = regionStart + subRegion.getStart() + subRegion.getLength();

                        DeleteEdit deletion = createDeletion(doc, startOffset, endOffset);
                        rootEdit.addChild(deletion);
                        startLineInclusive = doc.getLineOfOffset(endOffset) + 1;
                        break;
                    }
                }

                // Find the close tag
                // Look at all attribute values and look for an id reference match
                region = doc.getRegionAtCharacterOffset(elementRegion.getEndOffset()
                        - element.getTagName().length() - 1);
                list = region.getRegions();
                regionStart = region.getStartOffset();
                startOffset = -1;
                for (int j = 0; j < region.getNumberOfRegions(); j++) {
                    ITextRegion subRegion = list.get(j);
                    String type = subRegion.getType();
                    if (DOMRegionContext.XML_END_TAG_OPEN.equals(type)) {
                        startOffset = regionStart + subRegion.getStart();
                    } else if (DOMRegionContext.XML_TAG_CLOSE.equals(type)) {
                        int endOffset = regionStart + subRegion.getStart() + subRegion.getLength();
                        if (startOffset != -1) {
                            DeleteEdit deletion = createDeletion(doc, startOffset, endOffset);
                            rootEdit.addChild(deletion);
                            endLineInclusive = doc.getLineOfOffset(startOffset) - 1;
                        }
                        break;
                    }
                }
            }

            // Dedent the contents
            if (changeIndentation && startLineInclusive != -1 && endLineInclusive != -1) {
                String indent = AndroidXmlEditor.getIndentAtOffset(doc, getRegion(element)
                        .getStartOffset());
                setIndentation(rootEdit, indent, doc, startLineInclusive, endLineInclusive,
                        element, skip);
            }
        } finally {
            model.releaseFromRead();
        }
    }

    protected void removeIndentation(MultiTextEdit rootEdit, String removeIndent,
            IStructuredDocument doc, int startLineInclusive, int endLineInclusive,
            Element element, List<Element> skip) {
        if (startLineInclusive > endLineInclusive) {
            return;
        }
        int indentLength = removeIndent.length();
        if (indentLength == 0) {
            return;
        }

        try {
            for (int line = startLineInclusive; line <= endLineInclusive; line++) {
                IRegion info = doc.getLineInformation(line);
                int lineStart = info.getOffset();
                int lineLength = info.getLength();
                int lineEnd = lineStart + lineLength;
                if (overlaps(lineStart, lineEnd, element, skip)) {
                    continue;
                }
                String lineText = getText(lineStart,
                        lineStart + Math.min(lineLength, indentLength));
                if (lineText.startsWith(removeIndent)) {
                    rootEdit.addChild(new DeleteEdit(lineStart, indentLength));
                }
            }
        } catch (BadLocationException e) {
            AdtPlugin.log(e, null);
        }
    }

    protected void setIndentation(MultiTextEdit rootEdit, String indent,
            IStructuredDocument doc, int startLineInclusive, int endLineInclusive,
            Element element, List<Element> skip) {
        if (startLineInclusive > endLineInclusive) {
            return;
        }
        int indentLength = indent.length();
        if (indentLength == 0) {
            return;
        }

        try {
            for (int line = startLineInclusive; line <= endLineInclusive; line++) {
                IRegion info = doc.getLineInformation(line);
                int lineStart = info.getOffset();
                int lineLength = info.getLength();
                int lineEnd = lineStart + lineLength;
                if (overlaps(lineStart, lineEnd, element, skip)) {
                    continue;
                }
                String lineText = getText(lineStart, lineStart + lineLength);
                int indentEnd = getFirstNonSpace(lineText);
                rootEdit.addChild(new ReplaceEdit(lineStart, indentEnd, indent));
            }
        } catch (BadLocationException e) {
            AdtPlugin.log(e, null);
        }
    }

    private int getFirstNonSpace(String s) {
        for (int i = 0; i < s.length(); i++) {
            if (!Character.isWhitespace(s.charAt(i))) {
                return i;
            }
        }

        return s.length();
    }

    /** Returns true if the given line overlaps any of the given elements */
    private static boolean overlaps(int startOffset, int endOffset,
            Element element, List<Element> overlaps) {
        for (Element e : overlaps) {
            if (e == element) {
                continue;
            }

            IndexedRegion region = getRegion(e);
            if (region.getEndOffset() >= startOffset && region.getStartOffset() <= endOffset) {
                return true;
            }
        }
        return false;
    }

    protected DeleteEdit createDeletion(IStructuredDocument doc, int startOffset, int endOffset) {
        // Expand to delete the whole line?
        try {
            IRegion info = doc.getLineInformationOfOffset(startOffset);
            int lineBegin = info.getOffset();
            // Is the text on the line leading up to the deletion region,
            // and the text following it, all whitespace?
            boolean deleteLine = true;
            if (lineBegin < startOffset) {
                String prefix = getText(lineBegin, startOffset);
                if (prefix.trim().length() > 0) {
                    deleteLine = false;
                }
            }
            info = doc.getLineInformationOfOffset(endOffset);
            int lineEnd = info.getOffset() + info.getLength();
            if (lineEnd > endOffset) {
                String suffix = getText(endOffset, lineEnd);
                if (suffix.trim().length() > 0) {
                    deleteLine = false;
                }
            }
            if (deleteLine) {
                startOffset = lineBegin;
                endOffset = Math.min(doc.getLength(), lineEnd + 1);
            }
        } catch (BadLocationException e) {
            AdtPlugin.log(e, null);
        }


        return new DeleteEdit(startOffset, endOffset - startOffset);
    }

    /**
     * Rewrite the edits in the given {@link MultiTextEdit} such that same edits are
     * applied, but the resulting range is also formatted
     */
    protected MultiTextEdit reformat(MultiTextEdit edit, XmlFormatStyle style) {
        String xml = mDelegate.getEditor().getStructuredDocument().get();
        return reformat(xml, edit, style);
    }

    /**
     * Rewrite the edits in the given {@link MultiTextEdit} such that same edits are
     * applied, but the resulting range is also formatted
     *
     * @param oldContents the original contents that should be edited by a
     *            {@link MultiTextEdit}
     * @param edit the {@link MultiTextEdit} to be applied to some string
     * @param style the formatting style to use
     * @return a new {@link MultiTextEdit} which performs the same edits as the input edit
     *         but also reformats the text
     */
    public static MultiTextEdit reformat(String oldContents, MultiTextEdit edit,
            XmlFormatStyle style) {
        IDocument document = new org.eclipse.jface.text.Document();
        document.set(oldContents);

        try {
            edit.apply(document);
        } catch (MalformedTreeException e) {
            AdtPlugin.log(e, null);
            return null; // Abort formatting
        } catch (BadLocationException e) {
            AdtPlugin.log(e, null);
            return null; // Abort formatting
        }

        String actual = document.get();

        // TODO: Try to format only the affected portion of the document.
        // To do that we need to find out what the affected offsets are; we know
        // the MultiTextEdit's affected range, but that is referring to offsets
        // in the old document. Use that to compute offsets in the new document.
        //int distanceFromEnd = actual.length() - edit.getExclusiveEnd();
        //IStructuredModel model = DomUtilities.createStructuredModel(actual);
        //int start = edit.getOffset();
        //int end = actual.length() - distanceFromEnd;
        //int length = end - start;
        //TextEdit format = AndroidXmlFormattingStrategy.format(model, start, length);
        EclipseXmlFormatPreferences formatPrefs = EclipseXmlFormatPreferences.create();
        String formatted = EclipseXmlPrettyPrinter.prettyPrint(actual, formatPrefs, style,
                null /*lineSeparator*/);


        // Figure out how much of the before and after strings are identical and narrow
        // the replacement scope
        boolean foundDifference = false;
        int firstDifference = 0;
        int lastDifference = formatted.length();
        int start = 0;
        int end = oldContents.length();

        for (int i = 0, j = start; i < formatted.length() && j < end; i++, j++) {
            if (formatted.charAt(i) != oldContents.charAt(j)) {
                firstDifference = i;
                foundDifference = true;
                break;
            }
        }

        if (!foundDifference) {
            // No differences - the document is already formatted, nothing to do
            return null;
        }

        lastDifference = firstDifference + 1;
        for (int i = formatted.length() - 1, j = end - 1;
                i > firstDifference && j > start;
                i--, j--) {
            if (formatted.charAt(i) != oldContents.charAt(j)) {
                lastDifference = i + 1;
                break;
            }
        }

        start += firstDifference;
        end -= (formatted.length() - lastDifference);
        end = Math.max(start, end);
        formatted = formatted.substring(firstDifference, lastDifference);

        ReplaceEdit format = new ReplaceEdit(start, end - start,
                formatted);

        MultiTextEdit newEdit = new MultiTextEdit();
        newEdit.addChild(format);

        return newEdit;
    }

    protected ViewElementDescriptor getElementDescriptor(String fqcn) {
        AndroidTargetData data = mDelegate.getEditor().getTargetData();
        if (data != null) {
            return data.getLayoutDescriptors().findDescriptorByClass(fqcn);
        }

        return null;
    }

    /** Create a wizard for this refactoring */
    abstract VisualRefactoringWizard createWizard();

    public abstract static class VisualRefactoringDescriptor extends RefactoringDescriptor {
        private final Map<String, String> mArguments;

        public VisualRefactoringDescriptor(
                String id, String project, String description, String comment,
                Map<String, String> arguments) {
            super(id, project, description, comment, STRUCTURAL_CHANGE | MULTI_CHANGE);
            mArguments = arguments;
        }

        public Map<String, String> getArguments() {
            return mArguments;
        }

        protected abstract Refactoring createRefactoring(Map<String, String> args);

        @Override
        public Refactoring createRefactoring(RefactoringStatus status) throws CoreException {
            try {
                return createRefactoring(mArguments);
            } catch (NullPointerException e) {
                status.addFatalError("Failed to recreate refactoring from descriptor");
                return null;
            }
        }
    }
}
