/*
 * Copyright 2020 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 androidx.fragment.lint

import com.android.tools.lint.client.api.UElementHandler
import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Detector
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.LintFix
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.isKotlin
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiMethod
import java.util.Locale
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.ULocalVariable
import org.jetbrains.uast.UPostfixExpression
import org.jetbrains.uast.UQualifiedReferenceExpression
import org.jetbrains.uast.USimpleNameReferenceExpression
import org.jetbrains.uast.getContainingUClass
import org.jetbrains.uast.skipParenthesizedExprDown
import org.jetbrains.uast.skipParenthesizedExprUp
import org.jetbrains.uast.toUElement
import org.jetbrains.uast.tryResolve

/**
 * Androidx added new "require____()" versions of common "get___()" APIs, such as
 * getContext/getActivity/getArguments/etc. Rather than wrap these in something like
 * requireNotNull() or null-checking with `!!` in Kotlin, using these APIs will allow the
 * underlying component to try to tell you _why_ it was null, and thus yield a better error
 * message.
 */
@Suppress("UnstableApiUsage")
class UseRequireInsteadOfGet : Detector(), SourceCodeScanner {

    companion object {
        val ISSUE: Issue = Issue.create(
            "UseRequireInsteadOfGet",
            "Use the 'require_____()' API rather than 'get____()' API for more " +
                "descriptive error messages when it's null.",
            """
            AndroidX added new "require____()" versions of common "get___()" APIs, such as \
            getContext/getActivity/getArguments/etc. Rather than wrap these in something like \
            requireNotNull(), using these APIs will allow the underlying component to try \
            to tell you _why_ it was null, and thus yield a better error message.
            """,
            Category.CORRECTNESS,
            6,
            Severity.ERROR,
            Implementation(UseRequireInsteadOfGet::class.java, Scope.JAVA_FILE_SCOPE)
        )

        private const val FRAGMENT_FQCN = "androidx.fragment.app.Fragment"
        internal val REQUIRABLE_METHODS = setOf(
            "getArguments",
            "getContext",
            "getActivity",
            "getFragmentManager",
            "getHost",
            "getParentFragment",
            "getView"
        )
        // Convert 'getArguments' to 'arguments'
        internal val REQUIRABLE_REFERENCES = REQUIRABLE_METHODS.map {
            it.removePrefix("get").decapitalize(Locale.US)
        }
        internal val KNOWN_NULLCHECKS = setOf(
            "checkNotNull",
            "requireNonNull"
        )
    }

    override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
        super.visitMethodCall(context, node, method)
    }

    override fun getApplicableUastTypes(): List<Class<out UElement>>? {
        return listOf(UCallExpression::class.java, USimpleNameReferenceExpression::class.java)
    }

    override fun createUastHandler(context: JavaContext): UElementHandler? {
        return object : UElementHandler() {

            /** This covers Kotlin accessor syntax expressions like "fragment.arguments" */
            override fun visitSimpleNameReferenceExpression(node: USimpleNameReferenceExpression) {
                val parent = skipParenthesizedExprUp(node.uastParent)
                if (parent is UQualifiedReferenceExpression) {
                    checkReferenceExpression(parent, node.identifier) {
                        parent.receiver.getExpressionType()
                            ?.let { context.evaluator.findClass(it.canonicalText) }
                    }
                } else {
                    // It's a member of the enclosing class
                    checkReferenceExpression(node, node.identifier) {
                        node.getContainingUClass()
                    }
                }
            }

            private fun checkReferenceExpression(
                node: UExpression,
                identifier: String,
                resolveEnclosingClass: () -> PsiClass?
            ) {
                if (identifier in REQUIRABLE_REFERENCES) {
                    // If this is a local variable do nothing
                    // We are doing this to avoid false positives on local variables that shadow
                    // Kotlin property accessors.  There is probably a better way to organize
                    // this Lint rule.
                    val element = node.tryResolve()
                    if (element != null && element.toUElement() is ULocalVariable) {
                        return
                    }
                    val enclosingClass = resolveEnclosingClass() ?: return
                    if (context.evaluator.extendsClass(enclosingClass, FRAGMENT_FQCN, false)) {
                        checkForIssue(node, identifier)
                    }
                }
            }

            /** This covers function/method calls like "fragment.getArguments()" */
            override fun visitCallExpression(node: UCallExpression) {
                val targetMethod = node.resolve() ?: return
                val containingClass = targetMethod.containingClass ?: return
                if (targetMethod.name in REQUIRABLE_METHODS &&
                    context.evaluator.extendsClass(containingClass, FRAGMENT_FQCN, false)
                ) {
                    checkForIssue(node, targetMethod.name, "${targetMethod.name}()")
                }
            }

            /** Called only when we know we're looking at an exempted method call type. */
            private fun checkForIssue(
                node: UExpression,
                targetMethodName: String,
                targetExpression: String = targetMethodName
            ) {
                // Note we go up potentially two parents - the first one may just be the qualified reference expression
                val nearestNonQualifiedReferenceParent =
                    skipParenthesizedExprUp(node.nearestNonQualifiedReferenceParent) ?: return
                if (isKotlin(node.lang) && nearestNonQualifiedReferenceParent.isNullCheckBlock()) {
                    // We're a double-bang expression (!!)
                    val parentSourceToReplace =
                        nearestNonQualifiedReferenceParent.asSourceString()
                    var correctMethod = correctMethod(
                        parentSourceToReplace,
                        "$targetExpression!!",
                        targetMethodName
                    )
                    if (correctMethod == parentSourceToReplace.removeSingleParentheses()) {
                        correctMethod = parentSourceToReplace.removeSingleParentheses().replace(
                            "$targetExpression?", "$targetExpression!!"
                        ).replaceFirstOccurrenceAfter("!!", "", "$targetExpression!!")
                    }
                    report(nearestNonQualifiedReferenceParent, parentSourceToReplace, correctMethod)
                } else if (nearestNonQualifiedReferenceParent is UCallExpression) {
                    // See if we're in a "requireNotNull(...)" or similar expression
                    val enclosingMethodCall =
                        (
                            skipParenthesizedExprUp(
                                nearestNonQualifiedReferenceParent
                            ) as UCallExpression
                            ).resolve() ?: return

                    if (enclosingMethodCall.name in KNOWN_NULLCHECKS) {
                        // Only match for single (specified) parameter. If existing code had a
                        // custom failure message, we don't want to overwrite it.
                        val singleParameterSpecified =
                            isSingleParameterSpecified(
                                enclosingMethodCall,
                                nearestNonQualifiedReferenceParent
                            )

                        if (singleParameterSpecified) {
                            // Grab the source of this argument as it's represented.
                            val source = nearestNonQualifiedReferenceParent.valueArguments[0]
                                .skipParenthesizedExprDown()!!.asSourceString()
                            val parentToReplace =
                                nearestNonQualifiedReferenceParent.fullyQualifiedNearestParent()
                                    .asSourceString()
                            val correctMethod =
                                correctMethod(source, targetExpression, targetMethodName)
                            report(
                                nearestNonQualifiedReferenceParent,
                                parentToReplace,
                                correctMethod
                            )
                        }
                    }
                }
            }

            private fun isSingleParameterSpecified(
                enclosingMethodCall: PsiMethod,
                nearestNonQualifiedRefParent: UCallExpression
            ) = enclosingMethodCall.parameterList.parametersCount == 1 ||
                (
                    isKotlin(nearestNonQualifiedRefParent.lang) &&
                        nearestNonQualifiedRefParent.getArgumentForParameter(1) == null
                    )

            private fun correctMethod(
                source: String,
                targetExpression: String,
                targetMethodName: String
            ): String {
                return source.removeSingleParentheses().replace(
                    targetExpression,
                    "require${targetMethodName.removePrefix("get").capitalize(Locale.US)}()"
                )
            }

            // Replaces the first occurrence of a substring after given String
            private fun String.replaceFirstOccurrenceAfter(
                oldValue: String,
                newValue: String,
                prefix: String
            ): String = prefix + substringAfter(prefix).replaceFirst(oldValue, newValue)

            private fun report(node: UElement, targetExpression: String, correctMethod: String) {
                context.report(
                    ISSUE,
                    context.getLocation(node),
                    "Use $correctMethod instead of $targetExpression",
                    LintFix.create()
                        .replace()
                        .name("Replace with $correctMethod")
                        .text(targetExpression)
                        .with(correctMethod)
                        .autoFix()
                        .build()
                )
            }
        }
    }
}

/**
 * Copy of the currently experimental Kotlin stdlib version. Can be removed once the stdlib version
 * comes out of experimental.
 */
internal fun String.decapitalize(locale: Locale): String {
    return if (isNotEmpty() && !this[0].isLowerCase()) {
        substring(0, 1).lowercase(locale) + substring(1)
    } else {
        this
    }
}

/**
 * Copy of the currently experimental Kotlin stdlib version. Can be removed once the stdlib version
 * comes out of experimental.
 */
internal fun String.capitalize(locale: Locale): String {
    if (isNotEmpty()) {
        val firstChar = this[0]
        if (firstChar.isLowerCase()) {
            return buildString {
                val titleChar = firstChar.titlecaseChar()
                if (titleChar != firstChar.uppercaseChar()) {
                    append(titleChar)
                } else {
                    append(this@capitalize.substring(0, 1).uppercase(locale))
                }
                append(this@capitalize.substring(1))
            }
        }
    }
    return this
}

internal fun UElement.isNullCheckBlock(): Boolean {
    return this is UPostfixExpression && operator.text == "!!"
}

internal fun String.removeSingleParentheses(): String {
    return this.replace("[(](?=[^)])".toRegex(), "")
        .replace("(?<![(])[)]".toRegex(), "")
}
