/*
 * Copyright (C) 2018 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.apifinder;

import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;

import com.google.auto.service.AutoService;
import com.google.errorprone.BugPattern;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
import com.google.errorprone.bugpatterns.BugChecker.NewClassTreeMatcher;
import com.google.errorprone.matchers.Description;
import com.google.errorprone.util.ASTHelpers;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.NewClassTree;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import java.util.ArrayList;
import java.util.List;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;

/** Bug checker to detect method or field used by a mainline module */
@AutoService(BugChecker.class)
@BugPattern(
    name = "JavaApiUsedByMainlineModule",
    summary = "Any public method used by a mainline module.",
    severity = WARNING)
public final class JavaApiUsedByMainlineModule extends BugChecker
    implements MethodInvocationTreeMatcher, NewClassTreeMatcher {

    /*
     * Checks if a method or class is private.
     * A method is considered as private method when any of the following condition met.
     *    1. Method is defined as private.
     *    2. Method's class is defined as private.
     *    3. Method's ancestor classes is defined as private.
     */
    private boolean isPrivate(Symbol sym) {
        Symbol tmpSym = sym;
        while (tmpSym != null) {
            if (!tmpSym.getModifiers().contains(Modifier.PUBLIC)) {
                return true;
            }
            tmpSym = ASTHelpers.enclosingClass(tmpSym);
        }
        return false;
    }

    /*
     * Constructs parameters. Only return parameter type.
     * For example
     *     (int, boolean, java.lang.String)
     */
    private String constructParameters(Symbol sym) {
        List<VarSymbol> paramsList = ((MethodSymbol) sym).getParameters();
        List<StringBuilder> stringParamsList = new ArrayList();
        for (VarSymbol paramSymbol : paramsList) {
            StringBuilder tmpParam = new StringBuilder(paramSymbol.asType().toString());

            // Removes "<*>" in parameter type.
            if (tmpParam.indexOf("<") != -1) {
                tmpParam = tmpParam.replace(
                    tmpParam.indexOf("<"), tmpParam.lastIndexOf(">") + 1, "");
            }

            stringParamsList.add(tmpParam);
        }
        return "(" + String.join(", ", stringParamsList) + ")";
    }

    @Override
    public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
        Symbol sym = ASTHelpers.getSymbol(tree);

        // Exclude private function.
        if (isPrivate(sym)) {
            return Description.NO_MATCH;
        }

        // Constructs method name formatted as superClassName.className.methodName,
        // using supperClassName.className.className for constructor
        String methodName = sym.name.toString();
        List<String> nameList = new ArrayList();
        if (sym.getKind() == ElementKind.CONSTRUCTOR) {
            Symbol classSymbol = ASTHelpers.enclosingClass(sym);
            while (classSymbol != null) {
                nameList.add(0, classSymbol.name.toString());
                classSymbol = ASTHelpers.enclosingClass(classSymbol);
            }
            methodName = String.join(".", nameList);
        }

        String params = constructParameters(sym);

        return buildDescription(tree)
            .setMessage(
                String.format("%s.%s%s", ASTHelpers.enclosingClass(sym), methodName, params))
            .build();
    }

    @Override
    public Description matchNewClass(NewClassTree tree, VisitorState state) {
        Symbol sym = ASTHelpers.getSymbol(tree);

        // Excludes private class.
        if (isPrivate(sym)) {
            return Description.NO_MATCH;
        }

        String params = constructParameters(sym);

        // Constructs constructor name.
        Symbol tmpSymbol = ASTHelpers.enclosingClass(sym);
        List<String> nameList = new ArrayList();
        while (tmpSymbol != null) {
            nameList.add(0, tmpSymbol.name.toString());
            tmpSymbol = ASTHelpers.enclosingClass(tmpSymbol);
        }
        String constructorName = String.join(".", nameList);

        return buildDescription(tree)
            .setMessage(
                String.format(
                    "%s.%s%s", ASTHelpers.enclosingClass(sym), constructorName, params))
            .build();
    }
}

