/*
 * 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_URI;
import static com.android.SdkConstants.ATTR_NAME;
import static com.android.SdkConstants.CLASS_ACTIVITY;
import static com.android.SdkConstants.CLASS_APPLICATION;
import static com.android.SdkConstants.CLASS_BROADCASTRECEIVER;
import static com.android.SdkConstants.CLASS_CONTENTPROVIDER;
import static com.android.SdkConstants.CLASS_SERVICE;
import static com.android.SdkConstants.TAG_ACTIVITY;
import static com.android.SdkConstants.TAG_APPLICATION;
import static com.android.SdkConstants.TAG_PROVIDER;
import static com.android.SdkConstants.TAG_RECEIVER;
import static com.android.SdkConstants.TAG_SERVICE;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.builder.model.AndroidProject;
import com.android.builder.model.ProductFlavorContainer;
import com.android.builder.model.SourceProviderContainer;
import com.android.tools.lint.client.api.JavaEvaluator;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Detector.JavaPsiScanner;
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.LayoutDetector;
import com.android.tools.lint.detector.api.Location;
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.android.utils.SdkUtils;
import com.google.common.collect.Maps;
import com.intellij.psi.PsiClass;

import org.w3c.dom.Element;

import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;

/**
 * Checks for missing manifest registrations for activities, services etc
 * and also makes sure that they are registered with the correct tag
 */
public class RegistrationDetector extends LayoutDetector implements JavaPsiScanner {
    /** Unregistered activities and services */
    public static final Issue ISSUE = Issue.create(
            "Registered", //$NON-NLS-1$
            "Class is not registered in the manifest",

            "Activities, services and content providers should be registered in the " +
            "`AndroidManifest.xml` file using `<activity>`, `<service>` and `<provider>` tags.\n" +
            "\n" +
            "If your activity is simply a parent class intended to be subclassed by other " +
            "\"real\" activities, make it an abstract class.",

            Category.CORRECTNESS,
            6,
            Severity.WARNING,
            new Implementation(
                    RegistrationDetector.class,
                    EnumSet.of(Scope.MANIFEST, Scope.JAVA_FILE)))
            .addMoreInfo(
            "http://developer.android.com/guide/topics/manifest/manifest-intro.html"); //$NON-NLS-1$

    protected Map<String, String> mManifestRegistrations;

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

    // ---- Implements XmlScanner ----

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

    @Override
    public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
        if (!element.hasAttributeNS(ANDROID_URI, ATTR_NAME)) {
            // For example, application appears in manifest and doesn't always have a name
            return;
        }
        String fqcn = getFqcn(context, element);
        String tag = element.getTagName();
        String frameworkClass = tagToClass(tag);
        if (frameworkClass != null) {
            String signature = fqcn;
            if (mManifestRegistrations == null) {
                mManifestRegistrations = Maps.newHashMap();
            }
            mManifestRegistrations.put(signature, frameworkClass);
            if (signature.indexOf('$') != -1) {
                signature = signature.replace('$', '.');
                mManifestRegistrations.put(signature, frameworkClass);
            }
        }
    }

    /**
     * Returns the fully qualified class name for a manifest entry element that
     * specifies a name attribute
     *
     * @param context the query context providing the project
     * @param element the element
     * @return the fully qualified class name
     */
    @NonNull
    private static String getFqcn(@NonNull XmlContext context, @NonNull Element element) {
        String className = element.getAttributeNS(ANDROID_URI, ATTR_NAME);
        if (className.startsWith(".")) { //$NON-NLS-1$
            return context.getProject().getPackage() + className;
        } else if (className.indexOf('.') == -1) {
            // According to the <activity> manifest element documentation, this is not
            // valid ( http://developer.android.com/guide/topics/manifest/activity-element.html )
            // but it appears in manifest files and appears to be supported by the runtime
            // so handle this in code as well:
            return context.getProject().getPackage() + '.' + className;
        } // else: the class name is already a fully qualified class name

        return className;
    }

    // ---- Implements JavaScanner ----

    @Nullable
    @Override
    public List<String> applicableSuperClasses() {
        return Arrays.asList(
                // Common super class for Activity, ContentProvider, Service, Application
                // (as well as some other classes not registered in the manifest, such as
                // Fragment and VoiceInteractionSession)
                "android.content.ComponentCallbacks2",
                CLASS_BROADCASTRECEIVER);
    }

    @Override
    public void checkClass(@NonNull JavaContext context, @NonNull PsiClass cls) {
        if (cls.getName() == null) {
            // anonymous class; can't be registered
            return;
        }

        JavaEvaluator evaluator = context.getEvaluator();
        if (evaluator.isAbstract(cls) || evaluator.isPrivate(cls)) {
            // Abstract classes do not need to be registered, and
            // private classes are clearly not intended to be registered
            return;
        }

        String rightTag = getTag(evaluator, cls);
        if (rightTag == null) {
            // some non-registered Context, such as a BackupAgent
            return;
        }
        String className = cls.getQualifiedName();
        if (className == null) {
            return;
        }
        if (mManifestRegistrations != null) {
            String framework = mManifestRegistrations.get(className);
            if (framework == null) {
                reportMissing(context, cls, className, rightTag);
            } else if (!evaluator.extendsClass(cls, framework, false)) {
                reportWrongTag(context, cls, rightTag, className, framework);
            }
        } else {
            reportMissing(context, cls, className, rightTag);
        }
    }

    private static void reportWrongTag(
            @NonNull JavaContext context,
            @NonNull PsiClass node,
            @NonNull String rightTag,
            @NonNull String className,
            @NonNull String framework) {
        String wrongTag = classToTag(framework);
        if (wrongTag == null) {
            return;
        }
        Location location = context.getNameLocation(node);
        String message = String.format("`%1$s` is %2$s but is registered "
                        + "in the manifest as %3$s", className, describeTag(rightTag),
                describeTag(wrongTag));
        context.report(ISSUE, location, message);
    }

    private static String describeTag(@NonNull String tag) {
        String article = tag.startsWith("a") ? "an" : "a"; // an for activity and application
        return String.format("%1$s `<%2$s>`", article, tag);
    }

    private static void reportMissing(
            @NonNull JavaContext context,
            @NonNull PsiClass node,
            @NonNull String className,
            @NonNull String tag) {
        if (tag.equals(TAG_RECEIVER)) {
            // Receivers can be registered in code; don't flag these.
            return;
        }

        // Don't flag activities registered in test source sets
        if (context.getProject().isGradleProject()) {
            AndroidProject model = context.getProject().getGradleProjectModel();
            if (model != null) {
                String javaSource = context.file.getPath();
                // Test source set?

                for (SourceProviderContainer extra : model.getDefaultConfig().getExtraSourceProviders()) {
                    String artifactName = extra.getArtifactName();
                    if (AndroidProject.ARTIFACT_ANDROID_TEST.equals(artifactName)) {
                        for (File file : extra.getSourceProvider().getJavaDirectories()) {
                            if (SdkUtils.startsWithIgnoreCase(javaSource, file.getPath())) {
                                return;
                            }
                        }
                    }
                }

                for (ProductFlavorContainer container : model.getProductFlavors()) {
                    for (SourceProviderContainer extra : container.getExtraSourceProviders()) {
                        String artifactName = extra.getArtifactName();
                        if (AndroidProject.ARTIFACT_ANDROID_TEST.equals(artifactName)) {
                            for (File file : extra.getSourceProvider().getJavaDirectories()) {
                                if (SdkUtils.startsWithIgnoreCase(javaSource, file.getPath())) {
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }

        Location location = context.getNameLocation(node);
        String message = String.format("The `<%1$s> %2$s` is not registered in the manifest",
                tag, className);
        context.report(ISSUE, location, message);
    }

    private static String getTag(@NonNull JavaEvaluator evaluator, @NonNull PsiClass cls) {
        String tag = null;
        for (String s : sClasses) {
            if (evaluator.extendsClass(cls, s, false)) {
                tag = classToTag(s);
                break;
            }
        }
        return tag;
    }

    /** The manifest tags we care about */
    private static final String[] sTags = new String[] {
        TAG_ACTIVITY,
        TAG_SERVICE,
        TAG_RECEIVER,
        TAG_PROVIDER,
        TAG_APPLICATION
        // Keep synchronized with {@link #sClasses}
    };

    /** The corresponding framework classes that the tags in {@link #sTags} should extend */
    private static final String[] sClasses = new String[] {
            CLASS_ACTIVITY,
            CLASS_SERVICE,
            CLASS_BROADCASTRECEIVER,
            CLASS_CONTENTPROVIDER,
            CLASS_APPLICATION
            // Keep synchronized with {@link #sTags}
    };

    /** Looks up the corresponding framework class a given manifest tag's class should extend */
    private static String tagToClass(String tag) {
        for (int i = 0, n = sTags.length; i < n; i++) {
            if (sTags[i].equals(tag)) {
                return sClasses[i];
            }
        }

        return null;
    }

    /** Looks up the tag a given framework class should be registered with */
    protected static String classToTag(String className) {
        for (int i = 0, n = sClasses.length; i < n; i++) {
            if (sClasses[i].equals(className)) {
                return sTags[i];
            }
        }

        return null;
    }
}
