/*
 * 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.common.layout;

import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_ID;
import static com.android.SdkConstants.ATTR_LAYOUT_ABOVE;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_BASELINE;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_BOTTOM;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_LEFT;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_PARENT_BOTTOM;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_PARENT_LEFT;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_PARENT_RIGHT;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_PARENT_TOP;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_RIGHT;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_TOP;
import static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_WITH_PARENT_MISSING;
import static com.android.SdkConstants.ATTR_LAYOUT_BELOW;
import static com.android.SdkConstants.ATTR_LAYOUT_CENTER_HORIZONTAL;
import static com.android.SdkConstants.ATTR_LAYOUT_CENTER_IN_PARENT;
import static com.android.SdkConstants.ATTR_LAYOUT_CENTER_VERTICAL;
import static com.android.SdkConstants.ATTR_LAYOUT_COLUMN;
import static com.android.SdkConstants.ATTR_LAYOUT_COLUMN_SPAN;
import static com.android.SdkConstants.ATTR_LAYOUT_GRAVITY;
import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT;
import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN;
import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN_BOTTOM;
import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN_LEFT;
import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN_RIGHT;
import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN_TOP;
import static com.android.SdkConstants.ATTR_LAYOUT_ROW;
import static com.android.SdkConstants.ATTR_LAYOUT_ROW_SPAN;
import static com.android.SdkConstants.ATTR_LAYOUT_TO_LEFT_OF;
import static com.android.SdkConstants.ATTR_LAYOUT_TO_RIGHT_OF;
import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH;
import static com.android.SdkConstants.ATTR_LAYOUT_X;
import static com.android.SdkConstants.ATTR_LAYOUT_Y;
import static com.android.SdkConstants.VALUE_FILL_PARENT;
import static com.android.SdkConstants.VALUE_MATCH_PARENT;
import static com.android.SdkConstants.VALUE_WRAP_CONTENT;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.api.DrawingStyle;
import com.android.ide.common.api.DropFeedback;
import com.android.ide.common.api.IAttributeInfo;
import com.android.ide.common.api.IClientRulesEngine;
import com.android.ide.common.api.IDragElement;
import com.android.ide.common.api.IDragElement.IDragAttribute;
import com.android.ide.common.api.IFeedbackPainter;
import com.android.ide.common.api.IGraphics;
import com.android.ide.common.api.IMenuCallback;
import com.android.ide.common.api.INode;
import com.android.ide.common.api.INodeHandler;
import com.android.ide.common.api.IViewRule;
import com.android.ide.common.api.MarginType;
import com.android.ide.common.api.Point;
import com.android.ide.common.api.Rect;
import com.android.ide.common.api.RuleAction;
import com.android.ide.common.api.RuleAction.ChoiceProvider;
import com.android.ide.common.api.Segment;
import com.android.ide.common.api.SegmentType;
import com.android.utils.Pair;

import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * A {@link IViewRule} for all layouts.
 */
public class BaseLayoutRule extends BaseViewRule {
    private static final String ACTION_FILL_WIDTH = "_fillW";  //$NON-NLS-1$
    private static final String ACTION_FILL_HEIGHT = "_fillH"; //$NON-NLS-1$
    private static final String ACTION_MARGIN = "_margin";     //$NON-NLS-1$
    private static final URL ICON_MARGINS =
        BaseLayoutRule.class.getResource("margins.png"); //$NON-NLS-1$
    private static final URL ICON_GRAVITY =
        BaseLayoutRule.class.getResource("gravity.png"); //$NON-NLS-1$
    private static final URL ICON_FILL_WIDTH =
        BaseLayoutRule.class.getResource("fillwidth.png"); //$NON-NLS-1$
    private static final URL ICON_FILL_HEIGHT =
        BaseLayoutRule.class.getResource("fillheight.png"); //$NON-NLS-1$

    // ==== Layout Actions support ====

    // The Margin layout parameters are available for LinearLayout, FrameLayout, RelativeLayout,
    // and their subclasses.
    protected final RuleAction createMarginAction(final INode parentNode,
            final List<? extends INode> children) {

        final List<? extends INode> targets = children == null || children.size() == 0 ?
                Collections.singletonList(parentNode)
                : children;
        final INode first = targets.get(0);

        IMenuCallback actionCallback = new IMenuCallback() {
            @Override
            public void action(@NonNull RuleAction action,
                    @NonNull List<? extends INode> selectedNodes,
                    final @Nullable String valueId,
                    final @Nullable Boolean newValue) {
                parentNode.editXml("Change Margins", new INodeHandler() {
                    @Override
                    public void handle(@NonNull INode n) {
                        String uri = ANDROID_URI;
                        String all = first.getStringAttr(uri, ATTR_LAYOUT_MARGIN);
                        String left = first.getStringAttr(uri, ATTR_LAYOUT_MARGIN_LEFT);
                        String right = first.getStringAttr(uri, ATTR_LAYOUT_MARGIN_RIGHT);
                        String top = first.getStringAttr(uri, ATTR_LAYOUT_MARGIN_TOP);
                        String bottom = first.getStringAttr(uri, ATTR_LAYOUT_MARGIN_BOTTOM);
                        String[] margins = mRulesEngine.displayMarginInput(all, left,
                                right, top, bottom);
                        if (margins != null) {
                            assert margins.length == 5;
                            for (INode child : targets) {
                                child.setAttribute(uri, ATTR_LAYOUT_MARGIN, margins[0]);
                                child.setAttribute(uri, ATTR_LAYOUT_MARGIN_LEFT, margins[1]);
                                child.setAttribute(uri, ATTR_LAYOUT_MARGIN_RIGHT, margins[2]);
                                child.setAttribute(uri, ATTR_LAYOUT_MARGIN_TOP, margins[3]);
                                child.setAttribute(uri, ATTR_LAYOUT_MARGIN_BOTTOM, margins[4]);
                            }
                        }
                    }
                });
            }
        };

        return RuleAction.createAction(ACTION_MARGIN, "Change Margins...", actionCallback,
                ICON_MARGINS, 40, false);
    }

    // Both LinearLayout and RelativeLayout have a gravity (but RelativeLayout applies it
    // to the parent whereas for LinearLayout it's on the children)
    protected final RuleAction createGravityAction(final List<? extends INode> targets, final
            String attributeName) {
        if (targets != null && targets.size() > 0) {
            final INode first = targets.get(0);
            ChoiceProvider provider = new ChoiceProvider() {
                @Override
                public void addChoices(@NonNull List<String> titles, @NonNull List<URL> iconUrls,
                        @NonNull List<String> ids) {
                    IAttributeInfo info = first.getAttributeInfo(ANDROID_URI, attributeName);
                    if (info != null) {
                        // Generate list of possible gravity value constants
                        assert info.getFormats().contains(IAttributeInfo.Format.FLAG);
                        for (String name : info.getFlagValues()) {
                            titles.add(getAttributeDisplayName(name));
                            ids.add(name);
                        }
                    }
                }
            };

            return RuleAction.createChoices("_gravity", "Change Gravity", //$NON-NLS-1$
                    new PropertyCallback(targets, "Change Gravity", ANDROID_URI,
                            attributeName),
                    provider,
                    first.getStringAttr(ANDROID_URI, attributeName), ICON_GRAVITY,
                    43, false);
        }

        return null;
    }

    @Override
    public void addLayoutActions(
            @NonNull List<RuleAction> actions,
            final @NonNull INode parentNode,
            final @NonNull List<? extends INode> children) {
        super.addLayoutActions(actions, parentNode, children);

        final List<? extends INode> targets = children == null || children.size() == 0 ?
                Collections.singletonList(parentNode)
                : children;
        final INode first = targets.get(0);

        // Shared action callback
        IMenuCallback actionCallback = new IMenuCallback() {
            @Override
            public void action(
                    @NonNull RuleAction action,
                    @NonNull List<? extends INode> selectedNodes,
                    final @Nullable String valueId,
                    final @Nullable Boolean newValue) {
                final String actionId = action.getId();
                final String undoLabel;
                if (actionId.equals(ACTION_FILL_WIDTH)) {
                    undoLabel = "Change Width Fill";
                } else if (actionId.equals(ACTION_FILL_HEIGHT)) {
                    undoLabel = "Change Height Fill";
                } else {
                    return;
                }
                parentNode.editXml(undoLabel, new INodeHandler() {
                    @Override
                    public void handle(@NonNull INode n) {
                        String attribute = actionId.equals(ACTION_FILL_WIDTH)
                                ? ATTR_LAYOUT_WIDTH : ATTR_LAYOUT_HEIGHT;
                        String value;
                        if (newValue) {
                            if (supportsMatchParent()) {
                                value = VALUE_MATCH_PARENT;
                            } else {
                                value = VALUE_FILL_PARENT;
                            }
                        } else {
                            value = VALUE_WRAP_CONTENT;
                        }
                        for (INode child : targets) {
                            child.setAttribute(ANDROID_URI, attribute, value);
                        }
                    }
                });
            }
        };

        actions.add(RuleAction.createToggle(ACTION_FILL_WIDTH, "Toggle Fill Width",
                isFilled(first, ATTR_LAYOUT_WIDTH), actionCallback, ICON_FILL_WIDTH, 10, false));
        actions.add(RuleAction.createToggle(ACTION_FILL_HEIGHT, "Toggle Fill Height",
                isFilled(first, ATTR_LAYOUT_HEIGHT), actionCallback, ICON_FILL_HEIGHT, 20, false));
    }

    // ==== Paste support ====

    /**
     * The default behavior for pasting in a layout is to simulate a drop in the
     * top-left corner of the view.
     * <p/>
     * Note that we explicitly do not call super() here -- the BaseViewRule.onPaste handler
     * will call onPasteBeforeChild() instead.
     * <p/>
     * Derived layouts should override this behavior if not appropriate.
     */
    @Override
    public void onPaste(@NonNull INode targetNode, @Nullable Object targetView,
            @NonNull IDragElement[] elements) {
        DropFeedback feedback = onDropEnter(targetNode, targetView, elements);
        if (feedback != null) {
            Point p = targetNode.getBounds().getTopLeft();
            feedback = onDropMove(targetNode, elements, feedback, p);
            if (feedback != null) {
                onDropLeave(targetNode, elements, feedback);
                onDropped(targetNode, elements, feedback, p);
            }
        }
    }

    /**
     * The default behavior for pasting in a layout with a specific child target
     * is to simulate a drop right above the top left of the given child target.
     * <p/>
     * This method is invoked by BaseView when onPaste() is called --
     * views don't generally accept children and instead use the target node as
     * a hint to paste "before" it.
     *
     * @param parentNode the parent node we're pasting into
     * @param parentView the view object for the parent layout, or null
     * @param targetNode the first selected node
     * @param elements the elements being pasted
     */
    public void onPasteBeforeChild(INode parentNode, Object parentView, INode targetNode,
            IDragElement[] elements) {
        DropFeedback feedback = onDropEnter(parentNode, parentView, elements);
        if (feedback != null) {
            Point parentP = parentNode.getBounds().getTopLeft();
            Point targetP = targetNode.getBounds().getTopLeft();
            if (parentP.y < targetP.y) {
                targetP.y -= 1;
            }

            feedback = onDropMove(parentNode, elements, feedback, targetP);
            if (feedback != null) {
                onDropLeave(parentNode, elements, feedback);
                onDropped(parentNode, elements, feedback, targetP);
            }
        }
    }

    // ==== Utility methods used by derived layouts ====

    /**
     * Draws the bounds of the given elements and all its children elements in the canvas
     * with the specified offset.
     *
     * @param gc the graphics context
     * @param element the element to be drawn
     * @param offsetX a horizontal delta to add to the current bounds of the element when
     *            drawing it
     * @param offsetY a vertical delta to add to the current bounds of the element when
     *            drawing it
     */
    public void drawElement(IGraphics gc, IDragElement element, int offsetX, int offsetY) {
        Rect b = element.getBounds();
        if (b.isValid()) {
            gc.drawRect(b.x + offsetX, b.y + offsetY, b.x + offsetX + b.w, b.y + offsetY + b.h);
        }

        for (IDragElement inner : element.getInnerElements()) {
            drawElement(gc, inner, offsetX, offsetY);
        }
    }

    /**
     * Collect all the "android:id" IDs from the dropped elements. When moving
     * objects within the same canvas, that's all there is to do. However if the
     * objects are moved to a different canvas or are copied then set
     * createNewIds to true to find the existing IDs under targetNode and create
     * a map with new non-conflicting unique IDs as needed. Returns a map String
     * old-id => tuple (String new-id, String fqcn) where fqcn is the FQCN of
     * the element.
     */
    protected static Map<String, Pair<String, String>> getDropIdMap(INode targetNode,
            IDragElement[] elements, boolean createNewIds) {
        Map<String, Pair<String, String>> idMap = new HashMap<String, Pair<String, String>>();

        if (createNewIds) {
            collectIds(idMap, elements);
            // Need to remap ids if necessary
            idMap = remapIds(targetNode, idMap);
        }

        return idMap;
    }

    /**
     * Fills idMap with a map String id => tuple (String id, String fqcn) where
     * fqcn is the FQCN of the element (in case we want to generate new IDs
     * based on the element type.)
     *
     * @see #getDropIdMap
     */
    protected static Map<String, Pair<String, String>> collectIds(
            Map<String, Pair<String, String>> idMap,
            IDragElement[] elements) {
        for (IDragElement element : elements) {
            IDragAttribute attr = element.getAttribute(ANDROID_URI, ATTR_ID);
            if (attr != null) {
                String id = attr.getValue();
                if (id != null && id.length() > 0) {
                    idMap.put(id, Pair.of(id, element.getFqcn()));
                }
            }

            collectIds(idMap, element.getInnerElements());
        }

        return idMap;
    }

    /**
     * Used by #getDropIdMap to find new IDs in case of conflict.
     */
    protected static Map<String, Pair<String, String>> remapIds(INode node,
            Map<String, Pair<String, String>> idMap) {
        // Visit the document to get a list of existing ids
        Set<String> existingIdSet = new HashSet<String>();
        collectExistingIds(node.getRoot(), existingIdSet);

        Map<String, Pair<String, String>> new_map = new HashMap<String, Pair<String, String>>();
        for (Map.Entry<String, Pair<String, String>> entry : idMap.entrySet()) {
            String key = entry.getKey();
            Pair<String, String> value = entry.getValue();

            String id = normalizeId(key);

            if (!existingIdSet.contains(id)) {
                // Not a conflict. Use as-is.
                new_map.put(key, value);
                if (!key.equals(id)) {
                    new_map.put(id, value);
                }
            } else {
                // There is a conflict. Get a new id.
                String new_id = findNewId(value.getSecond(), existingIdSet);
                value = Pair.of(new_id, value.getSecond());
                new_map.put(id, value);
                new_map.put(id.replaceFirst("@\\+", "@"), value); //$NON-NLS-1$ //$NON-NLS-2$
            }
        }

        return new_map;
    }

    /**
     * Used by #remapIds to find a new ID for a conflicting element.
     */
    protected static String findNewId(String fqcn, Set<String> existingIdSet) {
        // Get the last component of the FQCN (e.g. "android.view.Button" =>
        // "Button")
        String name = fqcn.substring(fqcn.lastIndexOf('.') + 1);

        for (int i = 1; i < 1000000; i++) {
            String id = String.format("@+id/%s%02d", name, i); //$NON-NLS-1$
            if (!existingIdSet.contains(id)) {
                existingIdSet.add(id);
                return id;
            }
        }

        // We'll never reach here.
        return null;
    }

    /**
     * Used by #getDropIdMap to find existing IDs recursively.
     */
    protected static void collectExistingIds(INode root, Set<String> existingIdSet) {
        if (root == null) {
            return;
        }

        String id = root.getStringAttr(ANDROID_URI, ATTR_ID);
        if (id != null) {
            id = normalizeId(id);

            if (!existingIdSet.contains(id)) {
                existingIdSet.add(id);
            }
        }

        for (INode child : root.getChildren()) {
            collectExistingIds(child, existingIdSet);
        }
    }

    /**
     * Transforms @id/name into @+id/name to treat both forms the same way.
     */
    protected static String normalizeId(String id) {
        if (id.indexOf("@+") == -1) { //$NON-NLS-1$
            id = id.replaceFirst("@", "@+"); //$NON-NLS-1$ //$NON-NLS-2$
        }
        return id;
    }

    /**
     * For use by {@link BaseLayoutRule#addAttributes} A filter should return a
     * valid replacement string.
     */
    protected static interface AttributeFilter {
        String replace(String attributeUri, String attributeName, String attributeValue);
    }

    private static final String[] EXCLUDED_ATTRIBUTES = new String[] {
        // Common
        ATTR_LAYOUT_GRAVITY,

        // from AbsoluteLayout
        ATTR_LAYOUT_X,
        ATTR_LAYOUT_Y,

        // from RelativeLayout
        ATTR_LAYOUT_ABOVE,
        ATTR_LAYOUT_BELOW,
        ATTR_LAYOUT_TO_LEFT_OF,
        ATTR_LAYOUT_TO_RIGHT_OF,
        ATTR_LAYOUT_ALIGN_BASELINE,
        ATTR_LAYOUT_ALIGN_TOP,
        ATTR_LAYOUT_ALIGN_BOTTOM,
        ATTR_LAYOUT_ALIGN_LEFT,
        ATTR_LAYOUT_ALIGN_RIGHT,
        ATTR_LAYOUT_ALIGN_PARENT_TOP,
        ATTR_LAYOUT_ALIGN_PARENT_BOTTOM,
        ATTR_LAYOUT_ALIGN_PARENT_LEFT,
        ATTR_LAYOUT_ALIGN_PARENT_RIGHT,
        ATTR_LAYOUT_ALIGN_WITH_PARENT_MISSING,
        ATTR_LAYOUT_CENTER_HORIZONTAL,
        ATTR_LAYOUT_CENTER_IN_PARENT,
        ATTR_LAYOUT_CENTER_VERTICAL,

        // From GridLayout
        ATTR_LAYOUT_ROW,
        ATTR_LAYOUT_ROW_SPAN,
        ATTR_LAYOUT_COLUMN,
        ATTR_LAYOUT_COLUMN_SPAN
    };

    /**
     * Default attribute filter used by the various layouts to filter out some properties
     * we don't want to offer.
     */
    public static final AttributeFilter DEFAULT_ATTR_FILTER = new AttributeFilter() {
        Set<String> mExcludes;

        @Override
        public String replace(String uri, String name, String value) {
            if (!ANDROID_URI.equals(uri)) {
                return value;
            }

            if (mExcludes == null) {
                mExcludes = new HashSet<String>(EXCLUDED_ATTRIBUTES.length);
                mExcludes.addAll(Arrays.asList(EXCLUDED_ATTRIBUTES));
            }

            return mExcludes.contains(name) ? null : value;
        }
    };

    /**
     * Copies all the attributes from oldElement to newNode. Uses the idMap to
     * transform the value of all attributes of Format.REFERENCE. If filter is
     * non-null, it's a filter that can rewrite the attribute string.
     */
    protected static void addAttributes(INode newNode, IDragElement oldElement,
            Map<String, Pair<String, String>> idMap, AttributeFilter filter) {

        for (IDragAttribute attr : oldElement.getAttributes()) {
            String uri = attr.getUri();
            String name = attr.getName();
            String value = attr.getValue();

            IAttributeInfo attrInfo = newNode.getAttributeInfo(uri, name);
            if (attrInfo != null) {
                if (attrInfo.getFormats().contains(IAttributeInfo.Format.REFERENCE)) {
                    if (idMap.containsKey(value)) {
                        value = idMap.get(value).getFirst();
                    }
                }
            }

            if (filter != null) {
                value = filter.replace(uri, name, value);
            }
            if (value != null && value.length() > 0) {
                newNode.setAttribute(uri, name, value);
            }
        }
    }

    /**
     * Adds all the children elements of oldElement to newNode, recursively.
     * Attributes are adjusted by calling addAttributes with idMap as necessary,
     * with no closure filter.
     */
    protected static void addInnerElements(INode newNode, IDragElement oldElement,
            Map<String, Pair<String, String>> idMap) {

        for (IDragElement element : oldElement.getInnerElements()) {
            String fqcn = element.getFqcn();
            INode childNode = newNode.appendChild(fqcn);

            addAttributes(childNode, element, idMap, null /* filter */);
            addInnerElements(childNode, element, idMap);
        }
    }

    /**
     * Insert the given elements into the given node at the given position
     *
     * @param targetNode the node to insert into
     * @param elements the elements to insert
     * @param createNewIds if true, generate new ids when there is a conflict
     * @param initialInsertPos index among targetnode's children which to insert the
     *            children
     */
    public static void insertAt(final INode targetNode, final IDragElement[] elements,
            final boolean createNewIds, final int initialInsertPos) {

        // Collect IDs from dropped elements and remap them to new IDs
        // if this is a copy or from a different canvas.
        final Map<String, Pair<String, String>> idMap = getDropIdMap(targetNode, elements,
                createNewIds);

        targetNode.editXml("Insert Elements", new INodeHandler() {

            @Override
            public void handle(@NonNull INode node) {
                // Now write the new elements.
                int insertPos = initialInsertPos;
                for (IDragElement element : elements) {
                    String fqcn = element.getFqcn();

                    INode newChild = targetNode.insertChildAt(fqcn, insertPos);

                    // insertPos==-1 means to insert at the end. Otherwise
                    // increment the insertion position.
                    if (insertPos >= 0) {
                        insertPos++;
                    }

                    // Copy all the attributes, modifying them as needed.
                    addAttributes(newChild, element, idMap, DEFAULT_ATTR_FILTER);
                    addInnerElements(newChild, element, idMap);
                }
            }
        });
    }

    // ---- Resizing ----

    /** Creates a new {@link ResizeState} object to track resize state */
    protected ResizeState createResizeState(INode layout, Object layoutView, INode node) {
        return new ResizeState(this, layout, layoutView, node);
    }

    @Override
    public DropFeedback onResizeBegin(@NonNull INode child, @NonNull INode parent,
            @Nullable SegmentType horizontalEdge, @Nullable SegmentType verticalEdge,
            @Nullable Object childView, @Nullable Object parentView) {
        ResizeState state = createResizeState(parent, parentView, child);
        state.horizontalEdgeType = horizontalEdge;
        state.verticalEdgeType = verticalEdge;

        // Compute preferred (wrap_content) size such that we can offer guidelines to
        // snap to the preferred size
        Map<INode, Rect> sizes = mRulesEngine.measureChildren(parent,
                new IClientRulesEngine.AttributeFilter() {
                    @Override
                    public String getAttribute(@NonNull INode node, @Nullable String namespace,
                            @NonNull String localName) {
                        // Change attributes to wrap_content
                        if (ATTR_LAYOUT_WIDTH.equals(localName)
                                && SdkConstants.NS_RESOURCES.equals(namespace)) {
                            return VALUE_WRAP_CONTENT;
                        }
                        if (ATTR_LAYOUT_HEIGHT.equals(localName)
                                && SdkConstants.NS_RESOURCES.equals(namespace)) {
                            return VALUE_WRAP_CONTENT;
                        }

                        return null;
                    }
                });
        if (sizes != null) {
            state.wrapBounds = sizes.get(child);
        }

        return new DropFeedback(state, new IFeedbackPainter() {
            @Override
            public void paint(@NonNull IGraphics gc, @NonNull INode node,
                    @NonNull DropFeedback feedback) {
                ResizeState resizeState = (ResizeState) feedback.userData;
                if (resizeState != null && resizeState.bounds != null) {
                    paintResizeFeedback(gc, node, resizeState);
                }
            }
        });
    }

    protected void paintResizeFeedback(IGraphics gc, INode node, ResizeState resizeState) {
        gc.useStyle(DrawingStyle.RESIZE_PREVIEW);
        Rect b = resizeState.bounds;
        gc.drawRect(b);

        if (resizeState.horizontalFillSegment != null) {
            gc.useStyle(DrawingStyle.GUIDELINE);
            Segment s = resizeState.horizontalFillSegment;
            gc.drawLine(s.from, s.at, s.to, s.at);
        }
        if (resizeState.verticalFillSegment != null) {
            gc.useStyle(DrawingStyle.GUIDELINE);
            Segment s = resizeState.verticalFillSegment;
            gc.drawLine(s.at, s.from, s.at, s.to);
        }

        if (resizeState.wrapBounds != null) {
            gc.useStyle(DrawingStyle.GUIDELINE);
            int wrapWidth = resizeState.wrapBounds.w;
            int wrapHeight = resizeState.wrapBounds.h;

            // Show the "wrap_content" guideline.
            // If we are showing both the wrap_width and wrap_height lines
            // then we show at most the rectangle formed by the two lines;
            // otherwise we show the entire width of the line
            if (resizeState.horizontalEdgeType != null) {
                int y = -1;
                switch (resizeState.horizontalEdgeType) {
                    case TOP:
                        y = b.y + b.h - wrapHeight;
                        break;
                    case BOTTOM:
                        y = b.y + wrapHeight;
                        break;
                    default: assert false : resizeState.horizontalEdgeType;
                }
                if (resizeState.verticalEdgeType != null) {
                    switch (resizeState.verticalEdgeType) {
                        case LEFT:
                            gc.drawLine(b.x + b.w - wrapWidth, y, b.x + b.w, y);
                            break;
                        case RIGHT:
                            gc.drawLine(b.x, y, b.x + wrapWidth, y);
                            break;
                        default: assert false : resizeState.verticalEdgeType;
                    }
                } else {
                    gc.drawLine(b.x, y, b.x + b.w, y);
                }
            }
            if (resizeState.verticalEdgeType != null) {
                int x = -1;
                switch (resizeState.verticalEdgeType) {
                    case LEFT:
                        x = b.x + b.w - wrapWidth;
                        break;
                    case RIGHT:
                        x = b.x + wrapWidth;
                        break;
                    default: assert false : resizeState.verticalEdgeType;
                }
                if (resizeState.horizontalEdgeType != null) {
                    switch (resizeState.horizontalEdgeType) {
                        case TOP:
                            gc.drawLine(x, b.y + b.h - wrapHeight, x, b.y + b.h);
                            break;
                        case BOTTOM:
                            gc.drawLine(x, b.y, x, b.y + wrapHeight);
                            break;
                        default: assert false : resizeState.horizontalEdgeType;
                    }
                } else {
                    gc.drawLine(x, b.y, x, b.y + b.h);
                }
            }
        }
    }

    /**
     * Returns the maximum number of pixels will be considered a "match" when snapping
     * resize or move positions to edges or other constraints
     *
     * @return the maximum number of pixels to consider for snapping
     */
    public static final int getMaxMatchDistance() {
        // TODO - make constant once we're happy with the feel
        return 20;
    }

    @Override
    public void onResizeUpdate(@Nullable DropFeedback feedback, @NonNull INode child,
            @NonNull INode parent, @NonNull Rect newBounds, int modifierMask) {
        ResizeState state = (ResizeState) feedback.userData;
        state.bounds = newBounds;
        state.modifierMask = modifierMask;

        // Match on wrap bounds
        state.wrapWidth = state.wrapHeight = false;
        if (state.wrapBounds != null) {
            Rect b = state.wrapBounds;
            int maxMatchDistance = getMaxMatchDistance();
            if (state.horizontalEdgeType != null) {
                if (Math.abs(newBounds.h - b.h) < maxMatchDistance) {
                    state.wrapHeight = true;
                    if (state.horizontalEdgeType == SegmentType.TOP) {
                        newBounds.y += newBounds.h - b.h;
                    }
                    newBounds.h = b.h;
                }
            }
            if (state.verticalEdgeType != null) {
                if (Math.abs(newBounds.w - b.w) < maxMatchDistance) {
                    state.wrapWidth = true;
                    if (state.verticalEdgeType == SegmentType.LEFT) {
                        newBounds.x += newBounds.w - b.w;
                    }
                    newBounds.w = b.w;
                }
            }
        }

        // Match on fill bounds
        state.horizontalFillSegment = null;
        state.fillHeight = false;
        if (state.horizontalEdgeType == SegmentType.BOTTOM && !state.wrapHeight) {
            Rect parentBounds = parent.getBounds();
            state.horizontalFillSegment = new Segment(parentBounds.y2(), newBounds.x,
                newBounds.x2(),
                null /*node*/, null /*id*/, SegmentType.BOTTOM, MarginType.NO_MARGIN);
            if (Math.abs(newBounds.y2() - parentBounds.y2()) < getMaxMatchDistance()) {
                state.fillHeight = true;
                newBounds.h = parentBounds.y2() - newBounds.y;
            }
        }
        state.verticalFillSegment = null;
        state.fillWidth = false;
        if (state.verticalEdgeType == SegmentType.RIGHT && !state.wrapWidth) {
            Rect parentBounds = parent.getBounds();
            state.verticalFillSegment = new Segment(parentBounds.x2(), newBounds.y,
                newBounds.y2(),
                null /*node*/, null /*id*/, SegmentType.RIGHT, MarginType.NO_MARGIN);
            if (Math.abs(newBounds.x2() - parentBounds.x2()) < getMaxMatchDistance()) {
                state.fillWidth = true;
                newBounds.w = parentBounds.x2() - newBounds.x;
            }
        }

        feedback.tooltip = getResizeUpdateMessage(state, child, parent,
                newBounds, state.horizontalEdgeType, state.verticalEdgeType);
    }

    @Override
    public void onResizeEnd(@Nullable DropFeedback feedback, @NonNull INode child,
            final @NonNull INode parent, final @NonNull Rect newBounds) {
        final Rect oldBounds = child.getBounds();
        if (oldBounds.w != newBounds.w || oldBounds.h != newBounds.h) {
            final ResizeState state = (ResizeState) feedback.userData;
            child.editXml("Resize", new INodeHandler() {
                @Override
                public void handle(@NonNull INode n) {
                    setNewSizeBounds(state, n, parent, oldBounds, newBounds,
                            state.horizontalEdgeType, state.verticalEdgeType);
                }
            });
        }
    }

    /**
     * Returns the message to display to the user during the resize operation
     *
     * @param resizeState the current resize state
     * @param child the child node being resized
     * @param parent the parent of the resized node
     * @param newBounds the new bounds to resize the child to, in pixels
     * @param horizontalEdge the horizontal edge being resized
     * @param verticalEdge the vertical edge being resized
     * @return the message to display for the current resize bounds
     */
    protected String getResizeUpdateMessage(ResizeState resizeState, INode child, INode parent,
            Rect newBounds, SegmentType horizontalEdge, SegmentType verticalEdge) {
        String width = resizeState.getWidthAttribute();
        String height = resizeState.getHeightAttribute();

        if (horizontalEdge == null) {
            return width;
        } else if (verticalEdge == null) {
            return height;
        } else {
            // U+00D7: Unicode for multiplication sign
            return String.format("%s \u00D7 %s", width, height);
        }
    }

    /**
     * Performs the edit on the node to complete a resizing operation. The actual edit
     * part is pulled out such that subclasses can change/add to the edits and be part of
     * the same undo event
     *
     * @param resizeState the current resize state
     * @param node the child node being resized
     * @param layout the parent of the resized node
     * @param newBounds the new bounds to resize the child to, in pixels
     * @param horizontalEdge the horizontal edge being resized
     * @param verticalEdge the vertical edge being resized
     */
    protected void setNewSizeBounds(ResizeState resizeState, INode node, INode layout,
            Rect oldBounds, Rect newBounds, SegmentType horizontalEdge, SegmentType verticalEdge) {
        if (verticalEdge != null
            && (newBounds.w != oldBounds.w || resizeState.wrapWidth || resizeState.fillWidth)) {
            node.setAttribute(ANDROID_URI, ATTR_LAYOUT_WIDTH, resizeState.getWidthAttribute());
        }
        if (horizontalEdge != null
            && (newBounds.h != oldBounds.h || resizeState.wrapHeight || resizeState.fillHeight)) {
            node.setAttribute(ANDROID_URI, ATTR_LAYOUT_HEIGHT, resizeState.getHeightAttribute());
        }
    }
}
