/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * 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.tools.lint.checks;

import static com.android.SdkConstants.ANDROID_STRING_PREFIX;
import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_BACKGROUND;
import static com.android.SdkConstants.ATTR_ID;
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_TO_LEFT_OF;
import static com.android.SdkConstants.ATTR_LAYOUT_TO_RIGHT_OF;
import static com.android.SdkConstants.ATTR_NAME;
import static com.android.SdkConstants.ATTR_ORIENTATION;
import static com.android.SdkConstants.ATTR_STYLE;
import static com.android.SdkConstants.ATTR_TEXT;
import static com.android.SdkConstants.BUTTON;
import static com.android.SdkConstants.LINEAR_LAYOUT;
import static com.android.SdkConstants.RELATIVE_LAYOUT;
import static com.android.SdkConstants.STRING_PREFIX;
import static com.android.SdkConstants.TABLE_ROW;
import static com.android.SdkConstants.TAG_STRING;
import static com.android.SdkConstants.VALUE_SELECTABLE_ITEM_BACKGROUND;
import static com.android.SdkConstants.VALUE_TRUE;
import static com.android.SdkConstants.VALUE_VERTICAL;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.resources.ResourceFolderType;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.Implementation;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.LintUtils;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.ResourceXmlDetector;
import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
import com.android.tools.lint.detector.api.Speed;
import com.android.tools.lint.detector.api.XmlContext;

import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Check which looks at the order of buttons in dialogs and makes sure that
 * "the dismissive action of a dialog is always on the left whereas the affirmative actions
 * are on the right."
 * <p>
 * This only looks for the affirmative and dismissive actions named "OK" and "Cancel";
 * "Cancel" usually works, but the affirmative action often has many other names -- "Done",
 * "Send", "Go", etc.
 * <p>
 * TODO: Perhaps we should look for Yes/No dialogs and suggested they be rephrased as
 * Cancel/OK dialogs? Similarly, consider "Abort" a synonym for "Cancel" ?
 */
public class ButtonDetector extends ResourceXmlDetector {
    /** Name of cancel value ("Cancel") */
    private static final String CANCEL_LABEL = "Cancel";
    /** Name of OK value ("Cancel") */
    private static final String OK_LABEL = "OK";
    /** Name of Back value ("Back") */
    private static final String BACK_LABEL = "Back";
    /** Yes */
    private static final String YES_LABEL = "Yes";
    /** No */
    private static final String NO_LABEL = "No";

    /** Layout text attribute reference to {@code @android:string/ok} */
    private static final String ANDROID_OK_RESOURCE =
            ANDROID_STRING_PREFIX + "ok"; //$NON-NLS-1$
    /** Layout text attribute reference to {@code @android:string/cancel} */
    private static final String ANDROID_CANCEL_RESOURCE =
            ANDROID_STRING_PREFIX + "cancel"; //$NON-NLS-1$
    /** Layout text attribute reference to {@code @android:string/yes} */
    private static final String ANDROID_YES_RESOURCE =
            ANDROID_STRING_PREFIX + "yes"; //$NON-NLS-1$
    /** Layout text attribute reference to {@code @android:string/no} */
    private static final String ANDROID_NO_RESOURCE =
            ANDROID_STRING_PREFIX + "no"; //$NON-NLS-1$

    private static final Implementation IMPLEMENTATION = new Implementation(
            ButtonDetector.class,
            Scope.RESOURCE_FILE_SCOPE);

    /** The main issue discovered by this detector */
    public static final Issue ORDER = Issue.create(
            "ButtonOrder", //$NON-NLS-1$
            "Button order",

            "According to the Android Design Guide,\n" +
            "\n" +
            "\"Action buttons are typically Cancel and/or OK, with OK indicating the preferred " +
            "or most likely action. However, if the options consist of specific actions such " +
            "as Close or Wait rather than a confirmation or cancellation of the action " +
            "described in the content, then all the buttons should be active verbs. As a rule, " +
            "the dismissive action of a dialog is always on the left whereas the affirmative " +
            "actions are on the right.\"\n" +
            "\n" +
            "This check looks for button bars and buttons which look like cancel buttons, " +
            "and makes sure that these are on the left.",

            Category.USABILITY,
            8,
            Severity.WARNING,
            IMPLEMENTATION)
            .addMoreInfo(
                    "http://developer.android.com/design/building-blocks/dialogs.html"); //$NON-NLS-1$

    /** The main issue discovered by this detector */
    public static final Issue STYLE = Issue.create(
            "ButtonStyle", //$NON-NLS-1$
            "Button should be borderless",

            "Button bars typically use a borderless style for the buttons. Set the " +
            "`style=\"?android:attr/buttonBarButtonStyle\"` attribute " +
            "on each of the buttons, and set `style=\"?android:attr/buttonBarStyle\"` on " +
            "the parent layout",

            Category.USABILITY,
            5,
            Severity.WARNING,
            IMPLEMENTATION)
            .addMoreInfo(
                    "http://developer.android.com/design/building-blocks/buttons.html"); //$NON-NLS-1$

    /** The main issue discovered by this detector */
    public static final Issue BACK_BUTTON = Issue.create(
            "BackButton", //$NON-NLS-1$
            "Back button",
            // TODO: Look for ">" as label suffixes as well

            "According to the Android Design Guide,\n" +
            "\n" +
            "\"Other platforms use an explicit back button with label to allow the user " +
            "to navigate up the application's hierarchy. Instead, Android uses the main " +
            "action bar's app icon for hierarchical navigation and the navigation bar's " +
            "back button for temporal navigation.\"" +
            "\n" +
            "This check is not very sophisticated (it just looks for buttons with the " +
            "label \"Back\"), so it is disabled by default to not trigger on common " +
            "scenarios like pairs of Back/Next buttons to paginate through screens.",

            Category.USABILITY,
            6,
            Severity.WARNING,
            IMPLEMENTATION)
            .setEnabledByDefault(false)
            .addMoreInfo(
                 "http://developer.android.com/design/patterns/pure-android.html"); //$NON-NLS-1$

    /** The main issue discovered by this detector */
    public static final Issue CASE = Issue.create(
            "ButtonCase", //$NON-NLS-1$
            "Cancel/OK dialog button capitalization",

            "The standard capitalization for OK/Cancel dialogs is \"OK\" and \"Cancel\". " +
            "To ensure that your dialogs use the standard strings, you can use " +
            "the resource strings @android:string/ok and @android:string/cancel.",

            Category.USABILITY,
            2,
            Severity.WARNING,
            IMPLEMENTATION);

    /** Set of resource names whose value was either OK or Cancel */
    private Set<String> mApplicableResources;

    /**
     * Map of resource names we'd like resolved into strings in phase 2. The
     * values should be filled in with the actual string contents.
     */
    private Map<String, String> mKeyToLabel;

    /**
     * Set of elements we've already warned about. If we've already complained
     * about a cancel button, don't also report the OK button (since it's listed
     * for the warnings on OK buttons).
     */
    private Set<Element> mIgnore;

    /** Constructs a new {@link ButtonDetector} */
    public ButtonDetector() {
    }

    @NonNull
    @Override
    public Speed getSpeed() {
        return Speed.FAST;
    }

    @Override
    public Collection<String> getApplicableElements() {
        return Arrays.asList(BUTTON, TAG_STRING);
    }

    @Override
    public boolean appliesTo(@NonNull ResourceFolderType folderType) {
        return folderType == ResourceFolderType.LAYOUT || folderType == ResourceFolderType.VALUES;
    }

    @Override
    public void afterCheckProject(@NonNull Context context) {
        int phase = context.getPhase();
        if (phase == 1 && mApplicableResources != null) {
            // We found resources for the string "Cancel"; perform a second pass
            // where we check layout text attributes against these strings.
            context.getDriver().requestRepeat(this, Scope.RESOURCE_FILE_SCOPE);
        }
    }

    private static String stripLabel(String text) {
        text = text.trim();
        if (text.length() > 2
                && (text.charAt(0) == '"' || text.charAt(0) == '\'')
                && (text.charAt(0) == text.charAt(text.length() - 1))) {
            text = text.substring(1, text.length() - 1);
        }

        return text;
    }

    @Override
    public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
        // This detector works in two passes.
        // In pass 1, it looks in layout files for hardcoded strings of "Cancel", or
        // references to @string/cancel or @android:string/cancel.
        // It also looks in values/ files for strings whose value is "Cancel",
        // and if found, stores the corresponding keys in a map. (This is necessary
        // since value files are processed after layout files).
        // Then, if at the end of phase 1 any "Cancel" string resources were
        // found in the value files, then it requests a *second* phase,
        // where it looks only for <Button>'s whose text matches one of the
        // cancel string resources.
        int phase = context.getPhase();
        String tagName = element.getTagName();
        if (phase == 1 && tagName.equals(TAG_STRING)) {
            NodeList childNodes = element.getChildNodes();
            for (int i = 0, n = childNodes.getLength(); i < n; i++) {
                Node child = childNodes.item(i);
                if (child.getNodeType() == Node.TEXT_NODE) {
                    String text = child.getNodeValue();
                    for (int j = 0, len = text.length(); j < len; j++) {
                        char c = text.charAt(j);
                        if (!Character.isWhitespace(c)) {
                            if (c == '"' || c == '\'') {
                                continue;
                            }
                            if (LintUtils.startsWith(text, CANCEL_LABEL, j)) {
                                String label = stripLabel(text);
                                if (label.equalsIgnoreCase(CANCEL_LABEL)) {
                                    String name = element.getAttribute(ATTR_NAME);
                                    foundResource(context, name, element);

                                    if (!label.equals(CANCEL_LABEL)
                                            && LintUtils.isEnglishResource(context, true)
                                            && context.isEnabled(CASE)) {
                                        assert label.trim().equalsIgnoreCase(CANCEL_LABEL) : label;
                                        context.report(CASE, child, context.getLocation(child),
                                            String.format(
                                            "The standard Android way to capitalize %1$s " +
                                            "is \"Cancel\" (tip: use `@android:string/cancel` instead)",
                                            label));
                                    }
                                }
                            } else if (LintUtils.startsWith(text, OK_LABEL, j)) {
                                String label = stripLabel(text);
                                if (label.equalsIgnoreCase(OK_LABEL)) {
                                    String name = element.getAttribute(ATTR_NAME);
                                    foundResource(context, name, element);

                                    if (!label.equals(OK_LABEL)
                                            && LintUtils.isEnglishResource(context, true)
                                            && context.isEnabled(CASE)) {
                                        assert label.trim().equalsIgnoreCase(OK_LABEL) : label;
                                        context.report(CASE, child, context.getLocation(child),
                                            String.format(
                                            "The standard Android way to capitalize %1$s " +
                                            "is \"OK\" (tip: use `@android:string/ok` instead)",
                                            label));
                                    }
                                }
                            } else if (LintUtils.startsWith(text, BACK_LABEL, j) &&
                                    stripLabel(text).equalsIgnoreCase(BACK_LABEL)) {
                                String name = element.getAttribute(ATTR_NAME);
                                foundResource(context, name, element);
                            }
                            break;
                        }
                    }
                }
            }
        } else if (tagName.equals(BUTTON)) {
            if (phase == 1) {
                if (isInButtonBar(element)
                        && !element.hasAttribute(ATTR_STYLE)
                        && !VALUE_SELECTABLE_ITEM_BACKGROUND.equals(
                                element.getAttributeNS(ANDROID_URI, ATTR_BACKGROUND))
                        && (context.getProject().getMinSdk() >= 11
                            || context.getFolderVersion() >= 11)
                        && context.isEnabled(STYLE)
                        && !parentDefinesSelectableItem(element)) {
                    context.report(STYLE, element, context.getLocation(element),
                            "Buttons in button bars should be borderless; use " +
                            "`style=\"?android:attr/buttonBarButtonStyle\"` (and " +
                            "`?android:attr/buttonBarStyle` on the parent)");
                }
            }

            String text = element.getAttributeNS(ANDROID_URI, ATTR_TEXT);
            if (phase == 2) {
                if (mApplicableResources.contains(text)) {
                    String key = text;
                    if (key.startsWith(STRING_PREFIX)) {
                        key = key.substring(STRING_PREFIX.length());
                    }
                    String label = mKeyToLabel.get(key);
                    boolean isCancel = CANCEL_LABEL.equalsIgnoreCase(label);
                    if (isCancel) {
                        if (isWrongCancelPosition(element)) {
                            reportCancelPosition(context, element);
                        }
                    } else if (OK_LABEL.equalsIgnoreCase(label)) {
                        if (isWrongOkPosition(element)) {
                            reportOkPosition(context, element);
                        }
                    } else {
                        assert BACK_LABEL.equalsIgnoreCase(label) : label + ':' + context.file;
                        Location location = context.getLocation(element);
                        if (context.isEnabled(BACK_BUTTON)) {
                            context.report(BACK_BUTTON, element, location,
                                "Back buttons are not standard on Android; see design guide's " +
                                "navigation section");
                        }
                    }
                }
            } else if (text.equals(CANCEL_LABEL) || text.equals(ANDROID_CANCEL_RESOURCE)) {
                if (isWrongCancelPosition(element)) {
                    reportCancelPosition(context, element);
                }
            } else if (text.equals(OK_LABEL) || text.equals(ANDROID_OK_RESOURCE)) {
                if (isWrongOkPosition(element)) {
                    reportOkPosition(context, element);
                }
            } else {
                boolean isYes = text.equals(ANDROID_YES_RESOURCE);
                if (isYes || text.equals(ANDROID_NO_RESOURCE)) {
                    Attr attribute = element.getAttributeNodeNS(ANDROID_URI, ATTR_TEXT);
                    Location location = context.getLocation(attribute);
                    String message = String.format("%1$s actually returns \"%2$s\", not \"%3$s\"; "
                                    + "use %4$s instead or create a local string resource for %5$s",
                            text,
                            isYes ? OK_LABEL : CANCEL_LABEL,
                            isYes ? YES_LABEL : NO_LABEL,
                            isYes ? ANDROID_OK_RESOURCE : ANDROID_CANCEL_RESOURCE,
                            isYes ? YES_LABEL : NO_LABEL);
                    context.report(CASE, element, location, message);
                }
            }
        }
    }

    private static boolean parentDefinesSelectableItem(Element element) {
        String background = element.getAttributeNS(ANDROID_URI, ATTR_BACKGROUND);
        if (VALUE_SELECTABLE_ITEM_BACKGROUND.equals(background)) {
            return true;
        }

        Node parent = element.getParentNode();
        if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
            return parentDefinesSelectableItem((Element) parent);
        }

        return false;
    }

    /** Report the given OK button as being in the wrong position */
    private void reportOkPosition(XmlContext context, Element element) {
        report(context, element, false /*isCancel*/);
    }

    /** Report the given Cancel button as being in the wrong position */
    private void reportCancelPosition(XmlContext context, Element element) {
        report(context, element, true /*isCancel*/);
    }

    /**
     * We've found a resource reference to some label we're interested in ("OK",
     * "Cancel", "Back", ...). Record the corresponding name such that in the
     * next pass through the layouts we can check the context (for OK/Cancel the
     * button order etc).
     */
    private void foundResource(XmlContext context, String name, Element element) {
        if (!LintUtils.isEnglishResource(context, true)) {
            return;
        }

        if (!context.getProject().getReportIssues()) {
            // If this is a library project not being analyzed, ignore it
            return;
        }

        if (mApplicableResources == null) {
            mApplicableResources = new HashSet<String>();
        }

        mApplicableResources.add(STRING_PREFIX + name);

        // ALSO record all the other string resources in this file to pick up other
        // labels. If you define "OK" in one resource file and "Cancel" in another
        // this won't work, but that's probably not common and has lower overhead.
        Node parentNode = element.getParentNode();

        List<Element> items = LintUtils.getChildren(parentNode);
        if (mKeyToLabel == null) {
            mKeyToLabel = new HashMap<String, String>(items.size());
        }
        for (Element item : items) {
            String itemName = item.getAttribute(ATTR_NAME);
            NodeList childNodes = item.getChildNodes();
            for (int i = 0, n = childNodes.getLength(); i < n; i++) {
                Node child = childNodes.item(i);
                if (child.getNodeType() == Node.TEXT_NODE) {
                    String text = stripLabel(child.getNodeValue());
                    if (!text.isEmpty()) {
                        mKeyToLabel.put(itemName, text);
                        break;
                    }
                }
            }
        }
    }

    /** Report the given OK/Cancel button as being in the wrong position */
    private void report(XmlContext context, Element element, boolean isCancel) {
        if (!context.isEnabled(ORDER)) {
            return;
        }

        if (mIgnore != null && mIgnore.contains(element)) {
            return;
        }

        int target = context.getProject().getTargetSdk();
        if (target < 14) {
            // If you're only targeting pre-ICS UI's, this is not an issue
            return;
        }

        boolean mustCreateIcsLayout = false;
        if (context.getProject().getMinSdk() < 14) {
            // If you're *also* targeting pre-ICS UIs, then this reverse button
            // order is correct for layouts intended for pre-ICS and incorrect for
            // ICS layouts.
            //
            // Therefore, we need to know if this layout is an ICS layout or
            // a pre-ICS layout.
            boolean isIcsLayout = context.getFolderVersion() >= 14;
            if (!isIcsLayout) {
                // This layout is not an ICS layout. However, there *must* also be
                // an ICS layout here, or this button order will be wrong:
                File res = context.file.getParentFile().getParentFile();
                File[] resFolders = res.listFiles();
                String fileName = context.file.getName();
                if (resFolders != null) {
                    for (File folder : resFolders) {
                        String folderName = folder.getName();
                        if (folderName.startsWith(SdkConstants.FD_RES_LAYOUT)
                                && folderName.contains("-v14")) { //$NON-NLS-1$
                            File layout = new File(folder, fileName);
                            if (layout.exists()) {
                                // Yes, a v14 specific layout is available so this pre-ICS
                                // layout order is not a problem
                                return;
                            }
                        }
                    }
                }
                mustCreateIcsLayout = true;
            }
        }

        List<Element> buttons = LintUtils.getChildren(element.getParentNode());

        if (mIgnore == null) {
            mIgnore = new HashSet<Element>();
        }
        for (Element button : buttons) {
            // Mark all the siblings in the ignore list to ensure that we don't
            // report *both* the Cancel and the OK button in "OK | Cancel"
            mIgnore.add(button);
        }

        String message;
        if (isCancel) {
            message = "Cancel button should be on the left";
        } else {
            message = "OK button should be on the right";
        }

        if (mustCreateIcsLayout) {
            message = String.format(
                    "Layout uses the wrong button order for API >= 14: Create a " +
                    "`layout-v14/%1$s` file with opposite order: %2$s",
                    context.file.getName(), message);
        }

        // Show existing button order? We can only do that for LinearLayouts
        // since in for example a RelativeLayout the order of the elements may
        // not be the same as the visual order
        String layout = element.getParentNode().getNodeName();
        if (layout.equals(LINEAR_LAYOUT) || layout.equals(TABLE_ROW)) {
            List<String> labelList = getLabelList(buttons);
            String wrong = describeButtons(labelList);
            sortButtons(labelList);
            String right = describeButtons(labelList);
            message += String.format(" (was \"%1$s\", should be \"%2$s\")", wrong, right);
        }

        Location location = context.getLocation(element);
        context.report(ORDER, element, location, message);
    }

    /**
     * Sort a list of label buttons into the expected order (Cancel on the left,
     * OK on the right
     */
    private static void sortButtons(List<String> labelList) {
        for (int i = 0, n = labelList.size(); i < n; i++) {
            String label = labelList.get(i);
            if (label.equalsIgnoreCase(CANCEL_LABEL) && i > 0) {
                swap(labelList, 0, i);
            } else if (label.equalsIgnoreCase(OK_LABEL) && i < n - 1) {
                swap(labelList, n - 1, i);
            }
        }
    }

    /** Swaps the strings at positions i and j */
    private static void swap(List<String> strings, int i, int j) {
        if (i != j) {
            String temp = strings.get(i);
            strings.set(i, strings.get(j));
            strings.set(j, temp);
        }
    }

    /** Creates a display string for a list of button labels, such as "Cancel | OK" */
    private static String describeButtons(List<String> labelList) {
        StringBuilder sb = new StringBuilder(80);
        for (String label : labelList) {
            if (sb.length() > 0) {
                sb.append(" | "); //$NON-NLS-1$
            }
            sb.append(label);
        }

        return sb.toString();
    }

    /** Returns the ordered list of button labels */
    private List<String> getLabelList(List<Element> views) {
        List<String> labels = new ArrayList<String>();

        if (mIgnore == null) {
            mIgnore = new HashSet<Element>();
        }

        for (Element view : views) {
            if (view.getTagName().equals(BUTTON)) {
                String text = view.getAttributeNS(ANDROID_URI, ATTR_TEXT);
                String label = getLabel(text);
                labels.add(label);

                // Mark all the siblings in the ignore list to ensure that we don't
                // report *both* the Cancel and the OK button in "OK | Cancel"
                mIgnore.add(view);
            }
        }

        return labels;
    }

    private String getLabel(String key) {
        String label = null;
        if (key.startsWith(ANDROID_STRING_PREFIX)) {
            if (key.equals(ANDROID_OK_RESOURCE)) {
                label = OK_LABEL;
            } else if (key.equals(ANDROID_CANCEL_RESOURCE)) {
                label = CANCEL_LABEL;
            }
        } else if (mKeyToLabel != null) {
            if (key.startsWith(STRING_PREFIX)) {
                label = mKeyToLabel.get(key.substring(STRING_PREFIX.length()));
            }
        }

        if (label == null) {
            label = key;
        }

        if (label.indexOf(' ') != -1 && label.indexOf('"') == -1) {
            label = '"' + label + '"';
        }

        return label;
    }

    /** Is the cancel button in the wrong position? It has to be on the left. */
    private static boolean isWrongCancelPosition(Element element) {
        return isWrongPosition(element, true /*isCancel*/);
    }

    /** Is the OK button in the wrong position? It has to be on the right. */
    private static boolean isWrongOkPosition(Element element) {
        return isWrongPosition(element, false /*isCancel*/);
    }

    private static boolean isInButtonBar(Element element) {
        assert element.getTagName().equals(BUTTON) : element.getTagName();
        Node parentNode = element.getParentNode();
        if (parentNode.getNodeType() != Node.ELEMENT_NODE) {
            return false;
        }
        Element parent = (Element) parentNode;

        String style = parent.getAttribute(ATTR_STYLE);
        if (style != null && style.contains("buttonBarStyle")) { //$NON-NLS-1$
            return true;
        }

        // Don't warn about single Cancel / OK buttons
        if (LintUtils.getChildCount(parent) < 2) {
            return false;
        }

        String layout = parent.getTagName();
        if (layout.equals(LINEAR_LAYOUT) || layout.equals(TABLE_ROW)) {
            String orientation = parent.getAttributeNS(ANDROID_URI, ATTR_ORIENTATION);
            if (VALUE_VERTICAL.equals(orientation)) {
                return false;
            }
        } else {
            return false;
        }

        // Ensure that all the children are buttons
        Node n = parent.getFirstChild();
        while (n != null) {
            if (n.getNodeType() == Node.ELEMENT_NODE) {
                if (!BUTTON.equals(n.getNodeName())) {
                    return false;
                }
            }
            n = n.getNextSibling();
        }

        return true;
    }

    /** Is the given button in the wrong position? */
    private static boolean isWrongPosition(Element element, boolean isCancel) {
        Node parentNode = element.getParentNode();
        if (parentNode.getNodeType() != Node.ELEMENT_NODE) {
            return false;
        }
        Element parent = (Element) parentNode;

        // Don't warn about single Cancel / OK buttons
        if (LintUtils.getChildCount(parent) < 2) {
            return false;
        }

        String layout = parent.getTagName();
        if (layout.equals(LINEAR_LAYOUT) || layout.equals(TABLE_ROW)) {
            String orientation = parent.getAttributeNS(ANDROID_URI, ATTR_ORIENTATION);
            if (VALUE_VERTICAL.equals(orientation)) {
                return false;
            }

            if (isCancel) {
                Node n = element.getPreviousSibling();
                while (n != null) {
                    if (n.getNodeType() == Node.ELEMENT_NODE) {
                        return true;
                    }
                    n = n.getPreviousSibling();
                }
            } else {
                Node n = element.getNextSibling();
                while (n != null) {
                    if (n.getNodeType() == Node.ELEMENT_NODE) {
                        return true;
                    }
                    n = n.getNextSibling();
                }
            }

            return false;
        } else if (layout.equals(RELATIVE_LAYOUT)) {
            // In RelativeLayouts, look for attachments which look like a clear sign
            // that the OK or Cancel buttons are out of order:
            //   -- a left attachment on a Cancel button (where the left attachment
            //      is a button; we don't want to complain if it's pointing to a spacer
            //      or image or progress indicator etc)
            //   -- a right-side parent attachment on a Cancel button (unless it's also
            //      attached on the left, e.g. a cancel button stretching across the
            //      layout)
            // etc.
            if (isCancel) {
                if (element.hasAttributeNS(ANDROID_URI, ATTR_LAYOUT_TO_RIGHT_OF)
                        && isButtonId(parent, element.getAttributeNS(ANDROID_URI,
                                ATTR_LAYOUT_TO_RIGHT_OF))) {
                    return true;
                }
                if (isTrue(element, ATTR_LAYOUT_ALIGN_PARENT_RIGHT) &&
                        !isTrue(element, ATTR_LAYOUT_ALIGN_PARENT_LEFT)) {
                    return true;
                }
            } else {
                if (element.hasAttributeNS(ANDROID_URI, ATTR_LAYOUT_TO_LEFT_OF)
                        && isButtonId(parent, element.getAttributeNS(ANDROID_URI,
                                ATTR_LAYOUT_TO_RIGHT_OF))) {
                    return true;
                }
                if (isTrue(element, ATTR_LAYOUT_ALIGN_PARENT_LEFT) &&
                        !isTrue(element, ATTR_LAYOUT_ALIGN_PARENT_RIGHT)) {
                    return true;
                }
            }

            return false;
        } else {
            // TODO: Consider other button layouts - GridLayouts, custom views extending
            // LinearLayout etc?
            return false;
        }
    }

    /**
     * Returns true if the given attribute (in the Android namespace) is set to
     * true on the given element
     */
    private static boolean isTrue(Element element, String attribute) {
        return VALUE_TRUE.equals(element.getAttributeNS(ANDROID_URI, attribute));
    }

    /** Is the given target id the id of a {@code <Button>} within this RelativeLayout? */
    private static boolean isButtonId(Element parent, String targetId) {
        for (Element child : LintUtils.getChildren(parent)) {
            String id = child.getAttributeNS(ANDROID_URI, ATTR_ID);
            if (LintUtils.idReferencesMatch(id, targetId)) {
                return child.getTagName().equals(BUTTON);
            }
        }
        return false;
    }
}
