/*
 * 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.tools.lint.checks

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.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.getMethodName
import com.intellij.psi.PsiLocalVariable
import com.intellij.psi.PsiMethod
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.ULocalVariable
import org.jetbrains.uast.UMethod
import org.jetbrains.uast.UQualifiedReferenceExpression
import org.jetbrains.uast.getParentOfType
import org.jetbrains.uast.tryResolve

/** Some lint checks around WorkManager usage. */
class WorkManagerDetector : Detector(), SourceCodeScanner {
    companion object {
        private val IMPLEMENTATION = Implementation(
            WorkManagerDetector::class.java,
            Scope.JAVA_FILE_SCOPE
        )

        /** Problems with enqueueing work manager continuations. */
        @JvmField
        val ISSUE = Issue.create(
            id = "EnqueueWork",
            briefDescription = "WorkManager Enqueue",
            explanation = """
                `WorkContinuations` cannot be enqueued automatically.  You must call `enqueue()` \
                on a `WorkContinuation` to have it and its parent continuations enqueued inside \
                `WorkManager`.
            """,
            category = Category.CORRECTNESS,
            priority = 6,
            severity = Severity.WARNING,
            androidSpecific = true,
            implementation = IMPLEMENTATION
        )

        private const val CLASS_WORK_MANAGER = "androidx.work.WorkManager"
        private const val CLASS_WORK_CONTINUATION = "androidx.work.WorkContinuation"
        private const val METHOD_BEGIN_WITH = "beginWith"
        private const val METHOD_BEGIN_UNIQUE_WORK = "beginUniqueWork"
        private const val METHOD_ENQUEUE = "enqueue"
        private const val METHOD_ENQUEUE_SYNC = "enqueueSync"
        private const val METHOD_ENQUEUE_UNIQUE = "enqueueUniquePeriodicWork"
        private const val METHOD_THEN = "then"
        private const val METHOD_COMBINE = "combine"
    }

    override fun getApplicableMethodNames(): List<String> {
        return listOf(METHOD_BEGIN_WITH, METHOD_BEGIN_UNIQUE_WORK, METHOD_THEN, METHOD_COMBINE)
    }

    override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
        if (!context.evaluator.isMemberInClass(method, CLASS_WORK_MANAGER) &&
            !context.evaluator.isMemberInClass(method, CLASS_WORK_CONTINUATION)
        ) {
            return
        }

        val surrounding = node.getParentOfType<UMethod>(UMethod::class.java, true) ?: return

        if (surrounding.returnType?.canonicalText == CLASS_WORK_CONTINUATION) {
            return
        }

        var enqueued = false

        surrounding.accept(object : DataFlowAnalyzer(listOf(node)) {
            override fun receiver(call: UCallExpression) {
                val methodName = getMethodName(call)
                if (methodName == METHOD_ENQUEUE ||
                    methodName == METHOD_ENQUEUE_SYNC ||
                    methodName == METHOD_ENQUEUE_UNIQUE
                ) {
                    // TODO: check that it's called on the WorkContinuation?
                    enqueued = true
                } else if (methodName == METHOD_THEN || methodName == METHOD_COMBINE) {
                    // Implicitly enqueued by the then/combine methods on the WorkContinuation
                    enqueued = true
                }
            }

            override fun argument(call: UCallExpression, reference: UElement) {
                val methodName = getMethodName(call)
                if (methodName == METHOD_COMBINE) {
                    enqueued = true
                } else {
                    // Used in a list etc: start to track the list
                    val parent = call.uastParent
                    if (parent is UQualifiedReferenceExpression) {
                        val listVariable = parent.receiver.tryResolve()
                        if (listVariable is PsiLocalVariable) {
                            references.add(listVariable)
                        } else {
                            // List factory method?
                            val parentParent = parent.uastParent
                            if (parentParent is ULocalVariable) {
                                addVariableReference(parentParent)
                            }
                        }
                    } else if (parent is ULocalVariable) {
                        // Some direct list construction call, such as listOf() in Kotlin
                        addVariableReference(parent)
                    }
                }
            }

            override fun returnsSelf(call: UCallExpression): Boolean {
                val methodName = getMethodName(call)
                if (methodName == "synchronous") {
                    return true
                }
                return super.returnsSelf(call)
            }
        })

        if (!enqueued) {
            val name = (node.uastParent?.uastParent as? ULocalVariable)?.name
            val nameString = if (name != null) "`$name` " else ""
            context.report(
                ISSUE, node, context.getLocation(node),
                "WorkContinuation ${nameString}not enqueued: did you forget to call `enqueue()`?"
            )
        }
    }
}
