/*
 * 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_URI;
import static com.android.SdkConstants.ANDROID_WIDGET_PREFIX;
import static com.android.SdkConstants.ATTR_BASELINE_ALIGNED;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_BASELINE;
import static com.android.SdkConstants.ATTR_LAYOUT_BELOW;
import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT;
import static com.android.SdkConstants.ATTR_LAYOUT_RESOURCE_PREFIX;
import static com.android.SdkConstants.ATTR_LAYOUT_TO_RIGHT_OF;
import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH;
import static com.android.SdkConstants.ATTR_ORIENTATION;
import static com.android.SdkConstants.EXT_XML;
import static com.android.SdkConstants.FQCN_GESTURE_OVERLAY_VIEW;
import static com.android.SdkConstants.FQCN_GRID_LAYOUT;
import static com.android.SdkConstants.FQCN_LINEAR_LAYOUT;
import static com.android.SdkConstants.FQCN_RELATIVE_LAYOUT;
import static com.android.SdkConstants.FQCN_TABLE_LAYOUT;
import static com.android.SdkConstants.GESTURE_OVERLAY_VIEW;
import static com.android.SdkConstants.LINEAR_LAYOUT;
import static com.android.SdkConstants.TABLE_ROW;
import static com.android.SdkConstants.VALUE_FALSE;
import static com.android.SdkConstants.VALUE_VERTICAL;
import static com.android.SdkConstants.VALUE_WRAP_CONTENT;

import com.android.SdkConstants;
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.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
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.LayoutCanvas;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ViewHierarchy;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.TextFileChange;
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.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.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Converts the selected layout into a layout of a different type.
 */
@SuppressWarnings("restriction") // XML model
public class ChangeLayoutRefactoring extends VisualRefactoring {
    private static final String KEY_TYPE = "type";       //$NON-NLS-1$
    private static final String KEY_FLATTEN = "flatten"; //$NON-NLS-1$

    private String mTypeFqcn;
    private String mInitializedAttributes;
    private boolean mFlatten;

    /**
     * This constructor is solely used by {@link Descriptor},
     * to replay a previous refactoring.
     * @param arguments argument map created by #createArgumentMap.
     */
    ChangeLayoutRefactoring(Map<String, String> arguments) {
        super(arguments);
        mTypeFqcn = arguments.get(KEY_TYPE);
        mFlatten = Boolean.parseBoolean(arguments.get(KEY_FLATTEN));
    }

    @VisibleForTesting
    ChangeLayoutRefactoring(List<Element> selectedElements, LayoutEditorDelegate delegate) {
        super(selectedElements, delegate);
    }

    public ChangeLayoutRefactoring(
            IFile file,
            LayoutEditorDelegate delegate,
            ITextSelection selection,
            ITreeSelection treeSelection) {
        super(file, delegate, selection, treeSelection);
    }

    @Override
    public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException,
            OperationCanceledException {
        RefactoringStatus status = new RefactoringStatus();

        try {
            pm.beginTask("Checking preconditions...", 2);

            if (mSelectionStart == -1 || mSelectionEnd == -1) {
                status.addFatalError("No selection to convert");
                return status;
            }

            if (mElements.size() != 1) {
                status.addFatalError("Select precisely one layout to convert");
                return status;
            }

            pm.worked(1);
            return status;

        } finally {
            pm.done();
        }
    }

    @Override
    protected VisualRefactoringDescriptor createDescriptor() {
        String comment = getName();
        return new Descriptor(
                mProject.getName(), //project
                comment, //description
                comment, //comment
                createArgumentMap());
    }

    @Override
    protected Map<String, String> createArgumentMap() {
        Map<String, String> args = super.createArgumentMap();
        args.put(KEY_TYPE, mTypeFqcn);
        args.put(KEY_FLATTEN, Boolean.toString(mFlatten));

        return args;
    }

    @Override
    public String getName() {
        return "Change Layout";
    }

    void setType(String typeFqcn) {
        mTypeFqcn = typeFqcn;
    }

    void setInitializedAttributes(String initializedAttributes) {
        mInitializedAttributes = initializedAttributes;
    }

    void setFlatten(boolean flatten) {
        mFlatten = flatten;
    }

    @Override
    protected List<Element> initElements() {
        List<Element> elements = super.initElements();

        // Don't convert a root GestureOverlayView; convert its child. This looks for
        // gesture overlays, and if found, it generates a new child list where the gesture
        // overlay children are replaced by their first element children
        for (Element element : elements) {
            String tagName = element.getTagName();
            if (tagName.equals(GESTURE_OVERLAY_VIEW)
                    || tagName.equals(FQCN_GESTURE_OVERLAY_VIEW)) {
                List<Element> replacement = new ArrayList<Element>(elements.size());
                for (Element e : elements) {
                    tagName = e.getTagName();
                    if (tagName.equals(GESTURE_OVERLAY_VIEW)
                            || tagName.equals(FQCN_GESTURE_OVERLAY_VIEW)) {
                        NodeList children = e.getChildNodes();
                        Element first = null;
                        for (int i = 0, n = children.getLength(); i < n; i++) {
                            Node node = children.item(i);
                            if (node.getNodeType() == Node.ELEMENT_NODE) {
                                first = (Element) node;
                                break;
                            }
                        }
                        if (first != null) {
                            e = first;
                        }
                    }
                    replacement.add(e);
                }
                return replacement;
            }
        }

        return elements;
    }

    @Override
    protected @NonNull List<Change> computeChanges(IProgressMonitor monitor) {
        String name = getViewClass(mTypeFqcn);

        IFile file = mDelegate.getEditor().getInputFile();
        List<Change> changes = new ArrayList<Change>();
        if (file == null) {
            return changes;
        }
        TextFileChange change = new TextFileChange(file.getName(), file);
        MultiTextEdit rootEdit = new MultiTextEdit();
        change.setTextType(EXT_XML);
        changes.add(change);

        String text = getText(mSelectionStart, mSelectionEnd);
        Element layout = getPrimaryElement();
        String oldName = layout.getNodeName();
        int open = text.indexOf(oldName);
        int close = text.lastIndexOf(oldName);

        if (open != -1 && close != -1) {
            int oldLength = oldName.length();
            rootEdit.addChild(new ReplaceEdit(mSelectionStart + open, oldLength, name));
            if (close != open) { // Gracefully handle <FooLayout/>
                rootEdit.addChild(new ReplaceEdit(mSelectionStart + close, oldLength, name));
            }
        }

        String oldId = getId(layout);
        String newId = ensureIdMatchesType(layout, mTypeFqcn, rootEdit);
        // Update any layout references to the old id with the new id
        if (oldId != null && newId != null) {
            IStructuredModel model = mDelegate.getEditor().getModelForRead();
            try {
                IStructuredDocument doc = model.getStructuredDocument();
                if (doc != null) {
                    List<TextEdit> replaceIds = replaceIds(getAndroidNamespacePrefix(), doc,
                            mSelectionStart,
                            mSelectionEnd, oldId, newId);
                    for (TextEdit edit : replaceIds) {
                        rootEdit.addChild(edit);
                    }
                }
            } finally {
                model.releaseFromRead();
            }
        }

        String oldType = getOldType();
        String newType = mTypeFqcn;

        if (newType.equals(FQCN_RELATIVE_LAYOUT)) {
            if (oldType.equals(FQCN_LINEAR_LAYOUT) && !mFlatten) {
                // Hand-coded conversion specifically tailored for linear to relative, provided
                // there is no hierarchy flattening
                // TODO: use the RelativeLayoutConversionHelper for this; it does a better job
                // analyzing gravities etc.
                convertLinearToRelative(rootEdit);
                removeUndefinedAttrs(rootEdit, layout);
                addMissingWrapContentAttributes(rootEdit, layout, oldType, newType, null);
            } else {
                // Generic conversion to relative - can also flatten the hierarchy
                convertAnyToRelative(rootEdit, oldType, newType);
                // This already handles removing undefined layout attributes -- right?
                //removeUndefinedLayoutAttrs(rootEdit, layout);
            }
        } else if (newType.equals(FQCN_GRID_LAYOUT)) {
            convertAnyToGridLayout(rootEdit);
            // Layout attributes on children have already been removed as part of conversion
            // during the flattening
            removeUndefinedAttrs(rootEdit, layout, false /*removeLayoutAttrs*/);
        } else if (oldType.equals(FQCN_RELATIVE_LAYOUT) && newType.equals(FQCN_LINEAR_LAYOUT)) {
            convertRelativeToLinear(rootEdit);
            removeUndefinedAttrs(rootEdit, layout);
            addMissingWrapContentAttributes(rootEdit, layout, oldType, newType, null);
        } else if (oldType.equals(FQCN_LINEAR_LAYOUT) && newType.equals(FQCN_TABLE_LAYOUT)) {
            convertLinearToTable(rootEdit);
            removeUndefinedAttrs(rootEdit, layout);
            addMissingWrapContentAttributes(rootEdit, layout, oldType, newType, null);
        } else {
            convertGeneric(rootEdit, oldType, newType, layout);
        }

        if (mInitializedAttributes != null && mInitializedAttributes.length() > 0) {
            String namespace = getAndroidNamespacePrefix();
            for (String s : mInitializedAttributes.split(",")) { //$NON-NLS-1$
                String[] nameValue = s.split("="); //$NON-NLS-1$
                String attribute = nameValue[0];
                String value = nameValue[1];
                String prefix = null;
                String namespaceUri = null;
                if (attribute.startsWith(SdkConstants.ANDROID_NS_NAME_PREFIX)) {
                    prefix = namespace;
                    namespaceUri = ANDROID_URI;
                    attribute = attribute.substring(SdkConstants.ANDROID_NS_NAME_PREFIX.length());
                }
                setAttribute(rootEdit, layout, namespaceUri,
                        prefix, attribute, value);
            }
        }

        if (AdtPrefs.getPrefs().getFormatGuiXml()) {
            MultiTextEdit formatted = reformat(rootEdit, XmlFormatStyle.LAYOUT);
            if (formatted != null) {
                rootEdit = formatted;
            }
        }
        change.setEdit(rootEdit);

        return changes;
    }

    /** Checks whether we need to add any missing attributes on the elements */
    private void addMissingWrapContentAttributes(MultiTextEdit rootEdit, Element layout,
            String oldType, String newType, Set<Element> skip) {
        if (oldType.equals(FQCN_GRID_LAYOUT) && !newType.equals(FQCN_GRID_LAYOUT)) {
            String namespace = getAndroidNamespacePrefix();

            for (Element child : DomUtilities.getChildren(layout)) {
                if (skip != null && skip.contains(child)) {
                    continue;
                }

                if (!child.hasAttributeNS(ANDROID_URI, ATTR_LAYOUT_WIDTH)) {
                    setAttribute(rootEdit, child, ANDROID_URI,
                            namespace, ATTR_LAYOUT_WIDTH, VALUE_WRAP_CONTENT);
                }
                if (!child.hasAttributeNS(ANDROID_URI, ATTR_LAYOUT_HEIGHT)) {
                    setAttribute(rootEdit, child, ANDROID_URI,
                            namespace, ATTR_LAYOUT_HEIGHT, VALUE_WRAP_CONTENT);
                }
            }
        }
    }

    /** Hand coded conversion from a LinearLayout to a TableLayout */
    private void convertLinearToTable(MultiTextEdit rootEdit) {
        // This is pretty easy; just switch the root tag (already done by the initial generic
        // conversion) and then convert all the children into <TableRow> elements.
        // Finally, get rid of the orientation attribute, if any.
        Element layout = getPrimaryElement();
        removeOrientationAttribute(rootEdit, layout);

        NodeList children = layout.getChildNodes();
        for (int i = 0, n = children.getLength(); i < n; i++) {
            Node node = children.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element child = (Element) node;
                if (node instanceof IndexedRegion) {
                    IndexedRegion region = (IndexedRegion) node;
                    int start = region.getStartOffset();
                    int end = region.getEndOffset();
                    String text = getText(start, end);
                    String oldName = child.getNodeName();
                    if (oldName.equals(LINEAR_LAYOUT)) {
                        removeOrientationAttribute(rootEdit, child);
                        int open = text.indexOf(oldName);
                        int close = text.lastIndexOf(oldName);

                        if (open != -1 && close != -1) {
                            int oldLength = oldName.length();
                            rootEdit.addChild(new ReplaceEdit(mSelectionStart + open, oldLength,
                                    TABLE_ROW));
                            if (close != open) { // Gracefully handle <FooLayout/>
                                rootEdit.addChild(new ReplaceEdit(mSelectionStart + close,
                                        oldLength, TABLE_ROW));
                            }
                        }
                    } // else: WRAP in TableLayout!
                }
            }
        }
    }

     /** Hand coded conversion from a LinearLayout to a RelativeLayout */
    private void convertLinearToRelative(MultiTextEdit rootEdit) {
        // This can be done accurately.
        Element layout = getPrimaryElement();
        // Horizontal is the default, so if no value is specified it is horizontal.
        boolean isVertical = VALUE_VERTICAL.equals(layout.getAttributeNS(ANDROID_URI,
                ATTR_ORIENTATION));

        String attributePrefix = getAndroidNamespacePrefix();

        // TODO: Consider gravity of each element
        // TODO: Consider weight of each element
        // Right now it simply makes a single attachment to keep the order.

        if (isVertical) {
            // Align each child to the bottom and left of its parent
            NodeList children = layout.getChildNodes();
            String prevId = null;
            for (int i = 0, n = children.getLength(); i < n; i++) {
                Node node = children.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element child = (Element) node;
                    String id = ensureHasId(rootEdit, child, null);
                    if (prevId != null) {
                        setAttribute(rootEdit, child, ANDROID_URI, attributePrefix,
                                ATTR_LAYOUT_BELOW, prevId);
                    }
                    prevId = id;
                }
            }
        } else {
            // Align each child to the left
            NodeList children = layout.getChildNodes();
            boolean isBaselineAligned =
                !VALUE_FALSE.equals(layout.getAttributeNS(ANDROID_URI, ATTR_BASELINE_ALIGNED));

            String prevId = null;
            for (int i = 0, n = children.getLength(); i < n; i++) {
                Node node = children.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element child = (Element) node;
                    String id = ensureHasId(rootEdit, child, null);
                    if (prevId != null) {
                        setAttribute(rootEdit, child, ANDROID_URI, attributePrefix,
                                ATTR_LAYOUT_TO_RIGHT_OF, prevId);
                        if (isBaselineAligned) {
                            setAttribute(rootEdit, child, ANDROID_URI, attributePrefix,
                                    ATTR_LAYOUT_ALIGN_BASELINE, prevId);
                        }
                    }
                    prevId = id;
                }
            }
        }
    }

    /** Strips out the android:orientation attribute from the given linear layout element */
    private void removeOrientationAttribute(MultiTextEdit rootEdit, Element layout) {
        assert layout.getTagName().equals(LINEAR_LAYOUT);
        removeAttribute(rootEdit, layout, ANDROID_URI, ATTR_ORIENTATION);
    }

    /**
     * Hand coded conversion from a RelativeLayout to a LinearLayout
     *
     * @param rootEdit the root multi text edit to add edits to
     */
    private void convertRelativeToLinear(MultiTextEdit rootEdit) {
        // This is going to be lossy...
        // TODO: Attempt to "order" the items based on their visual positions
        // and insert them in that order in the LinearLayout.
        // TODO: Possibly use nesting if necessary, by spatial subdivision,
        // to accomplish roughly the same layout as the relative layout specifies.
    }

    /**
     * Hand coded -generic- conversion from one layout to another. This is not going to be
     * an accurate layout transformation; instead it simply migrates the layout attributes
     * that are supported, and adds defaults for any new required layout attributes. In
     * addition, it attempts to order the children visually based on where they fit in a
     * rendering. (Unsupported layout attributes will be removed by the caller at the
     * end.)
     * <ul>
     * <li>Try to handle nesting. Converting a *hierarchy* of layouts into a flatter
     * layout for powerful layouts that support it, like RelativeLayout.
     * <li>Try to do automatic "inference" about the layout. I can render it and look at
     * the ViewInfo positions and sizes. I can render it multiple times, at different
     * sizes, to infer "stretchiness" and "weight" properties of the children.
     * <li>Try to do indirect transformations. E.g. if I can go from A to B, and B to C,
     * then an attempt to go from A to C should perform conversions A to B and then B to
     * C.
     * </ul>
     *
     * @param rootEdit the root multi text edit to add edits to
     * @param oldType the fully qualified class name of the layout type we are converting
     *            from
     * @param newType the fully qualified class name of the layout type we are converting
     *            to
     * @param layout the layout to be converted
     */
    private void convertGeneric(MultiTextEdit rootEdit, String oldType, String newType,
            Element layout) {
        // TODO: Add hooks for 3rd party conversions getting registered through the
        // IViewRule interface.

        // For now we simply go with the default behavior, which is to just strip the
        // layout attributes that aren't supported.
        removeUndefinedAttrs(rootEdit, layout);
        addMissingWrapContentAttributes(rootEdit, layout, oldType, newType, null);
    }

    /**
     * Removes all the unavailable attributes after a conversion, both on the
     * layout element itself as well as the layout attributes of any of the
     * children
     */
    private void removeUndefinedAttrs(MultiTextEdit rootEdit, Element layout) {
        removeUndefinedAttrs(rootEdit, layout, true /*removeLayoutAttrs*/);
    }

    private void removeUndefinedAttrs(MultiTextEdit rootEdit, Element layout,
            boolean removeLayoutAttrs) {
        ViewElementDescriptor descriptor = getElementDescriptor(mTypeFqcn);
        if (descriptor == null) {
            return;
        }

        if (removeLayoutAttrs) {
            Set<String> defined = new HashSet<String>();
            AttributeDescriptor[] layoutAttributes = descriptor.getLayoutAttributes();
            for (AttributeDescriptor attribute : layoutAttributes) {
                defined.add(attribute.getXmlLocalName());
            }

            NodeList children = layout.getChildNodes();
            for (int i = 0, n = children.getLength(); i < n; i++) {
                Node node = children.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element child = (Element) node;

                    List<Attr> attributes = findLayoutAttributes(child);
                    for (Attr attribute : attributes) {
                        String name = attribute.getLocalName();
                        if (!defined.contains(name)) {
                            // Remove it
                            try {
                                removeAttribute(rootEdit, child, attribute.getNamespaceURI(), name);
                            } catch (MalformedTreeException mte) {
                                // Sometimes refactoring has modified attribute; not removing
                                // it is non-fatal so just warn instead of letting refactoring
                                // operation abort
                                AdtPlugin.log(IStatus.WARNING,
                                        "Could not remove unsupported attribute %1$s; " + //$NON-NLS-1$
                                        "already modified during refactoring?", //$NON-NLS-1$
                                        attribute.getLocalName());
                            }
                        }
                    }
                }
            }
        }

        // Also remove the unavailable attributes (not layout attributes) on the
        // converted element
        Set<String> defined = new HashSet<String>();
        AttributeDescriptor[] attributes = descriptor.getAttributes();
        for (AttributeDescriptor attribute : attributes) {
            defined.add(attribute.getXmlLocalName());
        }

        // Remove undefined attributes on the layout element itself
        NamedNodeMap attributeMap = layout.getAttributes();
        for (int i = 0, n = attributeMap.getLength(); i < n; i++) {
            Node attributeNode = attributeMap.item(i);

            String name = attributeNode.getLocalName();
            if (!name.startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)
                    && ANDROID_URI.equals(attributeNode.getNamespaceURI())) {
                if (!defined.contains(name)) {
                    // Remove it
                    removeAttribute(rootEdit, layout, ANDROID_URI, name);
                }
            }
        }
    }

    /** Hand coded conversion from any layout to a RelativeLayout */
    private void convertAnyToRelative(MultiTextEdit rootEdit, String oldType, String newType) {
        // To perform a conversion from any other layout type, including nested conversion,
        Element layout = getPrimaryElement();
        CanvasViewInfo rootView = mRootView;
        if (rootView == null) {
            LayoutCanvas canvas = mDelegate.getGraphicalEditor().getCanvasControl();
            ViewHierarchy viewHierarchy = canvas.getViewHierarchy();
            rootView = viewHierarchy.getRoot();
        }

        RelativeLayoutConversionHelper helper =
            new RelativeLayoutConversionHelper(this, layout, mFlatten, rootEdit, rootView);
        helper.convertToRelative();
        List<Element> deletedElements = helper.getDeletedElements();
        Set<Element> deleted = null;
        if (deletedElements != null && deletedElements.size() > 0) {
            deleted = new HashSet<Element>(deletedElements);
        }
        addMissingWrapContentAttributes(rootEdit, layout, oldType, newType, deleted);
    }

    /** Hand coded conversion from any layout to a GridLayout */
    private void convertAnyToGridLayout(MultiTextEdit rootEdit) {
        // To perform a conversion from any other layout type, including nested conversion,
        Element layout = getPrimaryElement();
        CanvasViewInfo rootView = mRootView;
        if (rootView == null) {
            LayoutCanvas canvas = mDelegate.getGraphicalEditor().getCanvasControl();
            ViewHierarchy viewHierarchy = canvas.getViewHierarchy();
            rootView = viewHierarchy.getRoot();
        }

        GridLayoutConverter converter = new GridLayoutConverter(this, layout, mFlatten,
                rootEdit, rootView);
        converter.convertToGridLayout();
    }

    public static class Descriptor extends VisualRefactoringDescriptor {
        public Descriptor(String project, String description, String comment,
                Map<String, String> arguments) {
            super("com.android.ide.eclipse.adt.refactoring.convert", //$NON-NLS-1$
                    project, description, comment, arguments);
        }

        @Override
        protected Refactoring createRefactoring(Map<String, String> args) {
            return new ChangeLayoutRefactoring(args);
        }
    }

    String getOldType() {
        Element primary = getPrimaryElement();
        if (primary != null) {
            String oldType = primary.getTagName();
            if (oldType.indexOf('.') == -1) {
                oldType = ANDROID_WIDGET_PREFIX + oldType;
            }
            return oldType;
        }

        return null;
    }

    @VisibleForTesting
    protected CanvasViewInfo mRootView;

    @VisibleForTesting
    public void setRootView(CanvasViewInfo rootView) {
        mRootView = rootView;
    }

    @Override
    VisualRefactoringWizard createWizard() {
        return new ChangeLayoutWizard(this, mDelegate);
    }
}
