/*
 * Copyright (C) 2015 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_URI;
import static com.android.SdkConstants.ATTR_EXPORTED;
import static com.android.SdkConstants.ATTR_HOST;
import static com.android.SdkConstants.ATTR_PATH;
import static com.android.SdkConstants.ATTR_PATH_PREFIX;
import static com.android.SdkConstants.ATTR_SCHEME;
import static com.android.SdkConstants.CLASS_ACTIVITY;
import static com.android.xml.AndroidManifest.ATTRIBUTE_MIME_TYPE;
import static com.android.xml.AndroidManifest.ATTRIBUTE_NAME;
import static com.android.xml.AndroidManifest.ATTRIBUTE_PORT;
import static com.android.xml.AndroidManifest.NODE_ACTION;
import static com.android.xml.AndroidManifest.NODE_ACTIVITY;
import static com.android.xml.AndroidManifest.NODE_APPLICATION;
import static com.android.xml.AndroidManifest.NODE_CATEGORY;
import static com.android.xml.AndroidManifest.NODE_DATA;
import static com.android.xml.AndroidManifest.NODE_INTENT;
import static com.android.xml.AndroidManifest.NODE_MANIFEST;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.res2.AbstractResourceRepository;
import com.android.ide.common.res2.ResourceItem;
import com.android.ide.common.resources.ResourceUrl;
import com.android.resources.ResourceType;
import com.android.tools.lint.client.api.JavaEvaluator;
import com.android.tools.lint.client.api.LintClient;
import com.android.tools.lint.client.api.XmlParser;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.Detector;
import com.android.tools.lint.detector.api.Detector.JavaPsiScanner;
import com.android.tools.lint.detector.api.Detector.XmlScanner;
import com.android.tools.lint.detector.api.Implementation;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.JavaContext;
import com.android.tools.lint.detector.api.LintUtils;
import com.android.tools.lint.detector.api.Project;
import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
import com.android.tools.lint.detector.api.XmlContext;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.psi.JavaRecursiveElementVisitor;
import com.intellij.psi.PsiAnonymousClass;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethodCallExpression;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;


/**
 * Check if the usage of App Indexing is correct.
 */
public class AppIndexingApiDetector extends Detector implements XmlScanner, JavaPsiScanner {

    private static final Implementation URL_IMPLEMENTATION = new Implementation(
            AppIndexingApiDetector.class, Scope.MANIFEST_SCOPE);

    @SuppressWarnings("unchecked")
    private static final Implementation APP_INDEXING_API_IMPLEMENTATION =
            new Implementation(
                    AppIndexingApiDetector.class,
                    EnumSet.of(Scope.JAVA_FILE, Scope.MANIFEST),
                    Scope.JAVA_FILE_SCOPE, Scope.MANIFEST_SCOPE);

    public static final Issue ISSUE_URL_ERROR = Issue.create(
            "GoogleAppIndexingUrlError", //$NON-NLS-1$
            "URL not supported by app for Google App Indexing",
            "Ensure the URL is supported by your app, to get installs and traffic to your"
                    + " app from Google Search.",
            Category.USABILITY, 5, Severity.ERROR, URL_IMPLEMENTATION)
            .addMoreInfo("https://g.co/AppIndexing/AndroidStudio");

    public static final Issue ISSUE_APP_INDEXING =
      Issue.create(
        "GoogleAppIndexingWarning", //$NON-NLS-1$
        "Missing support for Google App Indexing",
        "Adds URLs to get your app into the Google index, to get installs"
          + " and traffic to your app from Google Search.",
        Category.USABILITY, 5, Severity.WARNING, URL_IMPLEMENTATION)
        .addMoreInfo("https://g.co/AppIndexing/AndroidStudio");

    public static final Issue ISSUE_APP_INDEXING_API =
            Issue.create(
                    "GoogleAppIndexingApiWarning", //$NON-NLS-1$
                    "Missing support for Google App Indexing Api",
                    "Adds URLs to get your app into the Google index, to get installs"
                            + " and traffic to your app from Google Search.",
                    Category.USABILITY, 5, Severity.WARNING, APP_INDEXING_API_IMPLEMENTATION)
                    .addMoreInfo("https://g.co/AppIndexing/AndroidStudio")
                    .setEnabledByDefault(false);

    private static final String[] PATH_ATTR_LIST = new String[]{ATTR_PATH_PREFIX, ATTR_PATH};
    private static final String SCHEME_MISSING = "android:scheme is missing";
    private static final String HOST_MISSING = "android:host is missing";
    private static final String DATA_MISSING = "Missing data element";
    private static final String URL_MISSING = "Missing URL for the intent filter";
    private static final String NOT_BROWSABLE
            = "Activity supporting ACTION_VIEW is not set as BROWSABLE";
    private static final String ILLEGAL_NUMBER = "android:port is not a legal number";

    private static final String APP_INDEX_START = "start"; //$NON-NLS-1$
    private static final String APP_INDEX_END = "end"; //$NON-NLS-1$
    private static final String APP_INDEX_VIEW = "view"; //$NON-NLS-1$
    private static final String APP_INDEX_VIEW_END = "viewEnd"; //$NON-NLS-1$
    private static final String CLIENT_CONNECT = "connect"; //$NON-NLS-1$
    private static final String CLIENT_DISCONNECT = "disconnect"; //$NON-NLS-1$
    private static final String ADD_API = "addApi"; //$NON-NLS-1$

    private static final String APP_INDEXING_API_CLASS
            = "com.google.android.gms.appindexing.AppIndexApi";
    private static final String GOOGLE_API_CLIENT_CLASS
            = "com.google.android.gms.common.api.GoogleApiClient";
    private static final String GOOGLE_API_CLIENT_BUILDER_CLASS
            = "com.google.android.gms.common.api.GoogleApiClient.Builder";
    private static final String API_CLASS = "com.google.android.gms.appindexing.AppIndex";

    public enum IssueType {
        SCHEME_MISSING(AppIndexingApiDetector.SCHEME_MISSING),
        HOST_MISSING(AppIndexingApiDetector.HOST_MISSING),
        DATA_MISSING(AppIndexingApiDetector.DATA_MISSING),
        URL_MISSING(AppIndexingApiDetector.URL_MISSING),
        NOT_BROWSABLE(AppIndexingApiDetector.NOT_BROWSABLE),
        ILLEGAL_NUMBER(AppIndexingApiDetector.ILLEGAL_NUMBER),
        EMPTY_FIELD("cannot be empty"),
        MISSING_SLASH("attribute should start with '/'"),
        UNKNOWN("unknown error type");

        private final String message;

        IssueType(String str) {
            this.message = str;
        }

        public static IssueType parse(String str) {
            for (IssueType type : IssueType.values()) {
                if (str.contains(type.message)) {
                    return type;
                }
            }
            return UNKNOWN;
        }
    }

    // ---- Implements XmlScanner ----
    @Override
    @Nullable
    public Collection<String> getApplicableElements() {
        return Collections.singletonList(NODE_APPLICATION);
    }

    @Override
    public void visitElement(@NonNull XmlContext context, @NonNull Element application) {
        List<Element> activities = extractChildrenByName(application, NODE_ACTIVITY);
        boolean applicationHasActionView = false;
        for (Element activity : activities) {
            List<Element> intents = extractChildrenByName(activity, NODE_INTENT);
            boolean activityHasActionView = false;
            for (Element intent : intents) {
                boolean actionView = hasActionView(intent);
                if (actionView) {
                    activityHasActionView = true;
                }
                visitIntent(context, intent);
            }
            if (activityHasActionView) {
                applicationHasActionView = true;
                if (activity.hasAttributeNS(ANDROID_URI, ATTR_EXPORTED)) {
                    Attr exported = activity.getAttributeNodeNS(ANDROID_URI, ATTR_EXPORTED);
                    if (!exported.getValue().equals("true")) {
                        // Report error if the activity supporting action view is not exported.
                        context.report(ISSUE_URL_ERROR, activity,
                                       context.getLocation(activity),
                                       "Activity supporting ACTION_VIEW is not exported");
                    }
                }
            }
        }
        if (!applicationHasActionView && !context.getProject().isLibrary()) {
            // Report warning if there is no activity that supports action view.
            context.report(ISSUE_APP_INDEXING, application, context.getLocation(application),
                           // This error message is more verbose than the other app indexing lint warnings, because it
                           // shows up on a blank project, and we want to make it obvious by just looking at the error
                           // message what this is
                           "App is not indexable by Google Search; consider adding at least one Activity with an ACTION-VIEW " +
                           "intent filter. See issue explanation for more details.");
        }
    }

    @Nullable
    @Override
    public List<String> applicableSuperClasses() {
        return Collections.singletonList(CLASS_ACTIVITY);
    }

    @Override
    public void checkClass(@NonNull JavaContext context, @NonNull PsiClass declaration) {
        if (declaration.getName() == null) {
            return;
        }

        // In case linting the base class itself.
        if (!context.getEvaluator().extendsClass(declaration, CLASS_ACTIVITY, true)) {
            return;
        }

        declaration.accept(new MethodVisitor(context, declaration));
    }

    static class MethodVisitor extends JavaRecursiveElementVisitor {
        private final JavaContext mContext;
        private final PsiClass mCls;

        private final List<PsiMethodCallExpression> mStartMethods;
        private final List<PsiMethodCallExpression> mEndMethods;
        private final List<PsiMethodCallExpression> mConnectMethods;
        private final List<PsiMethodCallExpression> mDisconnectMethods;
        private boolean mHasAddAppIndexApi;

        MethodVisitor(JavaContext context, PsiClass cls) {
            mCls = cls;
            mContext = context;
            mStartMethods = Lists.newArrayListWithExpectedSize(2);
            mEndMethods = Lists.newArrayListWithExpectedSize(2);
            mConnectMethods = Lists.newArrayListWithExpectedSize(2);
            mDisconnectMethods = Lists.newArrayListWithExpectedSize(2);
        }

        @Override
        public void visitClass(PsiClass aClass) {
            if (aClass == mCls) {
                super.visitClass(aClass);
                report();
            } // else: don't go into inner classes
        }

        @Override
        public void visitMethodCallExpression(PsiMethodCallExpression node) {
            super.visitMethodCallExpression(node);

            String methodName = node.getMethodExpression().getReferenceName();
            if (methodName == null) {
                return;
            }

            JavaEvaluator evaluator = mContext.getEvaluator();
            if (methodName.equals(APP_INDEX_START)) {
                if (evaluator.isMemberInClass(node.resolveMethod(), APP_INDEXING_API_CLASS)) {
                    mStartMethods.add(node);
                }
            } else if (methodName.equals(APP_INDEX_END)) {
                if (evaluator.isMemberInClass(node.resolveMethod(), APP_INDEXING_API_CLASS)) {
                    mEndMethods.add(node);
                }
            } else if (methodName.equals(APP_INDEX_VIEW)) {
                if (evaluator.isMemberInClass(node.resolveMethod(), APP_INDEXING_API_CLASS)) {
                    mStartMethods.add(node);
                }
            } else if (methodName.equals(APP_INDEX_VIEW_END)) {
                if (evaluator.isMemberInClass(node.resolveMethod(), APP_INDEXING_API_CLASS)) {
                    mEndMethods.add(node);
                }
            } else if (methodName.equals(CLIENT_CONNECT)) {
                if (evaluator.isMemberInClass(node.resolveMethod(), GOOGLE_API_CLIENT_CLASS)) {
                    mConnectMethods.add(node);
                }
            } else if (methodName.equals(CLIENT_DISCONNECT)) {
                if (evaluator.isMemberInClass(node.resolveMethod(), GOOGLE_API_CLIENT_CLASS)) {
                    mDisconnectMethods.add(node);
                }
            } else if (methodName.equals(ADD_API)) {
                if (evaluator.isMemberInClass(node.resolveMethod(), GOOGLE_API_CLIENT_BUILDER_CLASS)) {
                    PsiExpression[] args = node.getArgumentList().getExpressions();
                    if (args.length > 0) {
                        PsiElement resolved = evaluator.resolve(args[0]);
                        if (resolved instanceof PsiField &&
                                evaluator.isMemberInClass((PsiField) resolved, API_CLASS)) {
                            mHasAddAppIndexApi = true;
                        }
                    }
                }
            }
        }

        @Override
        public void visitAnonymousClass(PsiAnonymousClass aClass) {
            // Don't jump into inner classes
        }

        private void report() {
            // finds the activity classes that need app activity annotation
            Set<String> activitiesToCheck = getActivitiesToCheck(mContext);

            // app indexing API used but no support in manifest
            boolean hasIntent = activitiesToCheck.contains(mCls.getQualifiedName());
            if (!hasIntent) {
                for (PsiMethodCallExpression call : mStartMethods) {
                    mContext.report(ISSUE_APP_INDEXING_API, call,
                            mContext.getNameLocation(call),
                            "Missing support for Google App Indexing in the manifest");
                }
                for (PsiMethodCallExpression call : mEndMethods) {
                    mContext.report(ISSUE_APP_INDEXING_API, call,
                            mContext.getNameLocation(call),
                            "Missing support for Google App Indexing in the manifest");
                }
                return;
            }

            // `AppIndex.AppIndexApi.start / end / view / viewEnd` should exist
            if (mStartMethods.isEmpty() && mEndMethods.isEmpty()) {
                mContext.report(ISSUE_APP_INDEXING_API, mCls,
                        mContext.getNameLocation(mCls),
                        "Missing support for Google App Indexing API");
                return;
            }

            for (PsiMethodCallExpression startNode : mStartMethods) {
                PsiExpression[] expressions = startNode.getArgumentList().getExpressions();
                if (expressions.length == 0) {
                    continue;
                }
                PsiExpression startClient = expressions[0];

                // GoogleApiClient should `addApi(AppIndex.APP_INDEX_API)`
                if (!mHasAddAppIndexApi) {
                    String message = String.format(
                            "GoogleApiClient `%1$s` has not added support for App Indexing API",
                            startClient.getText());
                    mContext.report(ISSUE_APP_INDEXING_API, startClient,
                            mContext.getLocation(startClient), message);
                }

                // GoogleApiClient `connect` should exist
                if (!hasOperand(startClient, mConnectMethods)) {
                    String message = String.format("GoogleApiClient `%1$s` is not connected",
                                    startClient.getText());
                    mContext.report(ISSUE_APP_INDEXING_API, startClient,
                            mContext.getLocation(startClient), message);
                }

                // `AppIndex.AppIndexApi.end` should pair with `AppIndex.AppIndexApi.start`
                if (!hasFirstArgument(startClient, mEndMethods)) {
                    mContext.report(ISSUE_APP_INDEXING_API, startNode,
                            mContext.getNameLocation(startNode),
                            "Missing corresponding `AppIndex.AppIndexApi.end` method");
                }
            }

            for (PsiMethodCallExpression endNode : mEndMethods) {
                PsiExpression[] expressions = endNode.getArgumentList().getExpressions();
                if (expressions.length == 0) {
                    continue;
                }
                PsiExpression endClient = expressions[0];

                // GoogleApiClient should `addApi(AppIndex.APP_INDEX_API)`
                if (!mHasAddAppIndexApi) {
                    String message = String.format(
                            "GoogleApiClient `%1$s` has not added support for App Indexing API",
                            endClient.getText());
                    mContext.report(ISSUE_APP_INDEXING_API, endClient,
                            mContext.getLocation(endClient), message);
                }

                // GoogleApiClient `disconnect` should exist
                if (!hasOperand(endClient, mDisconnectMethods)) {
                    String message = String.format("GoogleApiClient `%1$s`"
                            + " is not disconnected", endClient.getText());
                    mContext.report(ISSUE_APP_INDEXING_API, endClient,
                            mContext.getLocation(endClient), message);
                }

                // `AppIndex.AppIndexApi.start` should pair with `AppIndex.AppIndexApi.end`
                if (!hasFirstArgument(endClient, mStartMethods)) {
                    mContext.report(ISSUE_APP_INDEXING_API, endNode,
                            mContext.getNameLocation(endNode),
                            "Missing corresponding `AppIndex.AppIndexApi.start` method");
                }
            }
        }
    }

    /**
     * Gets names of activities which needs app indexing. i.e. the activities have data tag in their
     * intent filters.
     * TODO: Cache the activities to speed up batch lint.
     *
     * @param context The context to check in.
     */
    private static Set<String> getActivitiesToCheck(Context context) {
        Set<String> activitiesToCheck = Sets.newHashSet();
        List<File> manifestFiles = context.getProject().getManifestFiles();
        XmlParser xmlParser = context.getDriver().getClient().getXmlParser();
        if (xmlParser != null) {
            // TODO: Avoid visit all manifest files before enable this check by default.
            for (File manifest : manifestFiles) {
                XmlContext xmlContext =
                        new XmlContext(context.getDriver(), context.getProject(),
                                null, manifest, null, xmlParser);
                Document doc = xmlParser.parseXml(xmlContext);
                if (doc != null) {
                    List<Element> children = LintUtils.getChildren(doc);
                    for (Element child : children) {
                        if (child.getNodeName().equals(NODE_MANIFEST)) {
                            List<Element> apps = extractChildrenByName(child, NODE_APPLICATION);
                            for (Element app : apps) {
                                List<Element> acts = extractChildrenByName(app, NODE_ACTIVITY);
                                for (Element act : acts) {
                                    List<Element> intents = extractChildrenByName(act, NODE_INTENT);
                                    for (Element intent : intents) {
                                        List<Element> data = extractChildrenByName(intent,
                                                NODE_DATA);
                                        if (!data.isEmpty() && act.hasAttributeNS(
                                                ANDROID_URI, ATTRIBUTE_NAME)) {
                                            Attr attr = act.getAttributeNodeNS(
                                                    ANDROID_URI, ATTRIBUTE_NAME);
                                            String activityName = attr.getValue();
                                            int dotIndex = activityName.indexOf('.');
                                            if (dotIndex <= 0) {
                                                String pkg = context.getMainProject().getPackage();
                                                if (pkg != null) {
                                                    if (dotIndex == 0) {
                                                        activityName = pkg + activityName;
                                                    }
                                                    else {
                                                        activityName = pkg + '.' + activityName;
                                                    }
                                                }
                                            }
                                            activitiesToCheck.add(activityName);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return activitiesToCheck;
    }

    private static void visitIntent(@NonNull XmlContext context, @NonNull Element intent) {
        boolean actionView = hasActionView(intent);
        boolean browsable = isBrowsable(intent);
        boolean isHttp = false;
        boolean hasScheme = false;
        boolean hasHost = false;
        boolean hasPort = false;
        boolean hasPath = false;
        boolean hasMimeType = false;
        Element firstData = null;
        List<Element> children = extractChildrenByName(intent, NODE_DATA);
        for (Element data : children) {
            if (firstData == null) {
                firstData = data;
            }
            if (isHttpSchema(data)) {
                isHttp = true;
            }
            checkSingleData(context, data);

            for (String name : PATH_ATTR_LIST) {
                if (data.hasAttributeNS(ANDROID_URI, name)) {
                    hasPath = true;
                }
            }

            if (data.hasAttributeNS(ANDROID_URI, ATTR_SCHEME)) {
                hasScheme = true;
            }

            if (data.hasAttributeNS(ANDROID_URI, ATTR_HOST)) {
                hasHost = true;
            }

            if (data.hasAttributeNS(ANDROID_URI, ATTRIBUTE_PORT)) {
                hasPort = true;
            }

            if (data.hasAttributeNS(ANDROID_URI, ATTRIBUTE_MIME_TYPE)) {
                hasMimeType = true;
            }
        }

        // In data field, a URL is consisted by
        // <scheme>://<host>:<port>[<path>|<pathPrefix>|<pathPattern>]
        // Each part of the URL should not have illegal character.
        if ((hasPath || hasHost || hasPort) && !hasScheme) {
            context.report(ISSUE_URL_ERROR, firstData, context.getLocation(firstData),
                    SCHEME_MISSING);
        }

        if ((hasPath || hasPort) && !hasHost) {
            context.report(ISSUE_URL_ERROR, firstData, context.getLocation(firstData),
                    HOST_MISSING);
        }

        if (actionView && browsable) {
            if (firstData == null) {
                // If this activity is an ACTION_VIEW action with category BROWSABLE, but doesn't
                // have data node, it may be a mistake and we will report error.
                context.report(ISSUE_URL_ERROR, intent, context.getLocation(intent),
                        DATA_MISSING);
            } else if (!hasScheme && !hasMimeType) {
                // If this activity is an action view, is browsable, but has neither a
                // URL nor mimeType, it may be a mistake and we will report error.
                context.report(ISSUE_URL_ERROR, firstData, context.getLocation(firstData),
                        URL_MISSING);
            }
        }

        // If this activity is an ACTION_VIEW action, has a http URL but doesn't have
        // BROWSABLE, it may be a mistake and and we will report warning.
        if (actionView && isHttp && !browsable) {
            context.report(ISSUE_APP_INDEXING, intent, context.getLocation(intent),
                    NOT_BROWSABLE);
        }

        if (actionView && !hasScheme) {
            context.report(ISSUE_APP_INDEXING, intent, context.getLocation(intent),
                    "Missing URL");
        }
    }

    /**
     * Check if the intent filter supports action view.
     *
     * @param intent the intent filter
     * @return true if it does
     */
    private static boolean hasActionView(@NonNull Element intent) {
        List<Element> children = extractChildrenByName(intent, NODE_ACTION);
        for (Element action : children) {
            if (action.hasAttributeNS(ANDROID_URI, ATTRIBUTE_NAME)) {
                Attr attr = action.getAttributeNodeNS(ANDROID_URI, ATTRIBUTE_NAME);
                if (attr.getValue().equals("android.intent.action.VIEW")) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Check if the intent filter is browsable.
     *
     * @param intent the intent filter
     * @return true if it does
     */
    private static boolean isBrowsable(@NonNull Element intent) {
        List<Element> children = extractChildrenByName(intent, NODE_CATEGORY);
        for (Element e : children) {
            if (e.hasAttributeNS(ANDROID_URI, ATTRIBUTE_NAME)) {
                Attr attr = e.getAttributeNodeNS(ANDROID_URI, ATTRIBUTE_NAME);
                if (attr.getNodeValue().equals("android.intent.category.BROWSABLE")) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Check if the data node contains http schema
     *
     * @param data the data node
     * @return true if it does
     */
    private static boolean isHttpSchema(@NonNull Element data) {
        if (data.hasAttributeNS(ANDROID_URI, ATTR_SCHEME)) {
            String value = data.getAttributeNodeNS(ANDROID_URI, ATTR_SCHEME).getValue();
            if (value.equalsIgnoreCase("http") || value.equalsIgnoreCase("https")) {
                return true;
            }
        }
        return false;
    }

    private static void checkSingleData(@NonNull XmlContext context, @NonNull Element data) {
        // path, pathPrefix and pathPattern should starts with /.
        for (String name : PATH_ATTR_LIST) {
            if (data.hasAttributeNS(ANDROID_URI, name)) {
                Attr attr = data.getAttributeNodeNS(ANDROID_URI, name);
                String path = replaceUrlWithValue(context, attr.getValue());
                if (!path.startsWith("/") && !path.startsWith(SdkConstants.PREFIX_RESOURCE_REF)) {
                    context.report(ISSUE_URL_ERROR, attr, context.getLocation(attr),
                            "android:" + name + " attribute should start with '/', but it is : "
                                    + path);
                }
            }
        }

        // port should be a legal number.
        if (data.hasAttributeNS(ANDROID_URI, ATTRIBUTE_PORT)) {
            Attr attr = data.getAttributeNodeNS(ANDROID_URI, ATTRIBUTE_PORT);
            try {
                String port = replaceUrlWithValue(context, attr.getValue());
                Integer.parseInt(port);
            } catch (NumberFormatException e) {
                context.report(ISSUE_URL_ERROR, attr, context.getLocation(attr),
                        ILLEGAL_NUMBER);
            }
        }

        // Each field should be non empty.
        NamedNodeMap attrs = data.getAttributes();
        for (int i = 0; i < attrs.getLength(); i++) {
            Node item = attrs.item(i);
            if (item.getNodeType() == Node.ATTRIBUTE_NODE) {
                Attr attr = (Attr) attrs.item(i);
                if (attr.getValue().isEmpty()) {
                    context.report(ISSUE_URL_ERROR, attr, context.getLocation(attr),
                            attr.getName() + " cannot be empty");
                }
            }
        }
    }

    private static String replaceUrlWithValue(@NonNull XmlContext context,
            @NonNull String str) {
        Project project = context.getProject();
        LintClient client = context.getClient();
        if (!client.supportsProjectResources()) {
            return str;
        }
        ResourceUrl style = ResourceUrl.parse(str);
        if (style == null || style.type != ResourceType.STRING || style.framework) {
            return str;
        }
        AbstractResourceRepository resources = client.getProjectResources(project, true);
        if (resources == null) {
            return str;
        }
        List<ResourceItem> items = resources.getResourceItem(ResourceType.STRING, style.name);
        if (items == null || items.isEmpty()) {
            return str;
        }
        ResourceValue resourceValue = items.get(0).getResourceValue(false);
        if (resourceValue == null) {
            return str;
        }
        return resourceValue.getValue() == null ? str : resourceValue.getValue();
    }

    /**
     * If a method with a certain argument exists in the list of methods.
     *
     * @param argument The first argument of the method.
     * @param list     The methods list.
     * @return If such a method exists in the list.
     */
    private static boolean hasFirstArgument(PsiExpression argument, List<PsiMethodCallExpression> list) {
        for (PsiMethodCallExpression call : list) {
            PsiExpression[] expressions = call.getArgumentList().getExpressions();
            if (expressions.length > 0) {
                PsiExpression argument2 = expressions[0];
                if (argument.getText().equals(argument2.getText())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * If a method with a certain operand exists in the list of methods.
     *
     * @param operand The operand of the method.
     * @param list    The methods list.
     * @return If such a method exists in the list.
     */
    private static boolean hasOperand(PsiExpression operand, List<PsiMethodCallExpression> list) {
        for (PsiMethodCallExpression method : list) {
            PsiElement operand2 = method.getMethodExpression().getQualifier();
            if (operand2 != null && operand.getText().equals(operand2.getText())) {
                return true;
            }
        }
        return false;
    }

    private static List<Element> extractChildrenByName(@NonNull Element node,
            @NonNull String name) {
        List<Element> result = Lists.newArrayList();
        List<Element> children = LintUtils.getChildren(node);
        for (Element child : children) {
            if (child.getNodeName().equals(name)) {
                result.add(child);
            }
        }
        return result;
    }
}
