/*
 * Copyright (C) 2017 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.helpers

import com.android.builder.model.Dependencies
import com.android.tools.lint.client.api.JavaEvaluator
import com.android.tools.lint.detector.api.Project
import com.android.tools.lint.detector.api.computeKotlinArgumentMapping
import com.android.tools.lint.detector.api.isKotlin
import com.google.common.collect.Sets
import com.intellij.codeInsight.AnnotationUtil
import com.intellij.psi.JavaDirectoryService
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiClassType
import com.intellij.psi.PsiCompiledFile
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiModifierListOwner
import com.intellij.psi.PsiPackage
import com.intellij.psi.PsiParameter
import com.intellij.psi.PsiType
import com.intellij.psi.impl.file.PsiPackageImpl
import com.intellij.psi.impl.source.tree.java.PsiCompositeModifierList
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.InheritanceUtil
import com.intellij.psi.util.MethodSignatureUtil
import com.intellij.psi.util.TypeConversionUtil
import com.intellij.util.io.URLUtil
import org.jetbrains.uast.UAnnotated
import org.jetbrains.uast.UAnnotation
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.getContainingUFile
import org.jetbrains.uast.java.JavaUAnnotation

open class DefaultJavaEvaluator(
    private val myProject: com.intellij.openapi.project.Project?,
    private val myLintProject: Project?
) : JavaEvaluator() {
    // cache of package name to package-info.class.
    private val packageInfoCache = mutableMapOf<String, PsiPackage>()

    override val dependencies: Dependencies?
        get() {
            if (myLintProject != null && myLintProject.isAndroidProject) {
                val variant = myLintProject.currentVariant
                if (variant != null) {
                    return variant.mainArtifact.dependencies
                }
            }
            return null
        }

    override fun extendsClass(cls: PsiClass?, className: String, strict: Boolean): Boolean {
        // TODO: This checks interfaces too. Let's find a cheaper method which only checks direct super classes!
        return InheritanceUtil.isInheritor(cls, strict, className)
    }

    override fun implementsInterface(
        cls: PsiClass,
        interfaceName: String,
        strict: Boolean
    ): Boolean {
        // TODO: This checks superclasses too. Let's find a cheaper method which only checks interfaces.
        return InheritanceUtil.isInheritor(cls, strict, interfaceName)
    }

    override fun inheritsFrom(cls: PsiClass, className: String, strict: Boolean): Boolean {
        return InheritanceUtil.isInheritor(cls, strict, className)
    }

    override fun findClass(qualifiedName: String): PsiClass? {
        return JavaPsiFacade.getInstance(myProject ?: return null).findClass(
            qualifiedName,
            GlobalSearchScope.allScope(myProject)
        )
    }

    override fun getClassType(psiClass: PsiClass?): PsiClassType? {
        return if (myProject != null && psiClass != null)
            JavaPsiFacade.getElementFactory(myProject).createType(psiClass)
        else null
    }

    override fun getAllAnnotations(
        owner: UAnnotated,
        inHierarchy: Boolean
    ): List<UAnnotation> {
        if (owner is UDeclaration) {
            // Going to PSI means we drop vital context from Kotlin annotations.
            // Therefore, call into UAST to get the full Kotlin annotations, but also
            // merge in external annotations and inherited annotations from the class
            // files, and pick unique.
            val annotations = owner.annotations
            val psiAnnotations = getAllAnnotations(owner.psi, inHierarchy)

            if (!annotations.isEmpty()) {
                if (psiAnnotations.isEmpty()) {
                    return annotations
                }

                // Filter with preference given to the builtins
                val result = mutableListOf<UAnnotation>()
                for (psi in psiAnnotations) {
                    val signature = psi.qualifiedName
                    var handled = false
                    for (ua in annotations) {
                        if (ua.qualifiedName == signature) {
                            result.add(ua)
                            handled = true
                            break
                        }
                    }
                    if (!handled) {
                        result.add(JavaUAnnotation.wrap(psi))
                    }
                }

                return result
            }

            // Work around bug: Passing in a UAST node to this method generates a
            // "class JavaUParameter not found among parameters: [PsiParameter:something]" error
            return JavaUAnnotation.wrap(psiAnnotations)
        }

        return owner.annotations
    }

    override fun getAllAnnotations(
        owner: PsiModifierListOwner,
        inHierarchy: Boolean
    ): Array<PsiAnnotation> {
        if (owner is UDeclaration) {
            // Work around bug: Passing in a UAST node to this method generates a
            // "class JavaUParameter not found among parameters: [PsiParameter:something]" error
            return getAllAnnotations(owner.psi, inHierarchy)
        }

        // withInferred=false when running outside the IDE: we don't have
        // an InferredAnnotationsManager
        return AnnotationUtil.getAllAnnotations(owner, inHierarchy, null, false)
    }

    override fun findAnnotationInHierarchy(
        listOwner: PsiModifierListOwner,
        vararg annotationNames: String
    ): PsiAnnotation? {
        if (listOwner is UDeclaration) {
            // Work around UAST bug
            return findAnnotationInHierarchy(listOwner.psi, *annotationNames)
        }
        return AnnotationUtil.findAnnotationInHierarchy(
            listOwner,
            Sets.newHashSet(*annotationNames)
        )
    }

    override fun findAnnotation(
        listOwner: PsiModifierListOwner?,
        vararg annotationNames: String
    ): PsiAnnotation? {
        if (listOwner is UDeclaration) {
            // Work around UAST bug
            return findAnnotation(listOwner.psi, *annotationNames)
        }
        return AnnotationUtil.findAnnotation(listOwner, false, *annotationNames)
    }

    override fun areSignaturesEqual(method1: PsiMethod, method2: PsiMethod): Boolean {
        return MethodSignatureUtil.areSignaturesEqual(method1, method2)
    }

    override fun findJarPath(element: PsiElement): String? {
        val containingFile = element.containingFile
        @Suppress("USELESS_CAST")
        return findJarPath(containingFile as PsiFile?)
    }

    override fun findJarPath(element: UElement): String? {
        val uFile = element.getContainingUFile()
        return if (uFile != null) findJarPath(uFile.psi as PsiFile?) else null
    }

    private fun findJarPath(containingFile: PsiFile?): String? {
        if (containingFile is PsiCompiledFile) {
            // This code is roughly similar to the following:
            //      VirtualFile jarVirtualFile = PsiUtil.getJarFile(containingFile);
            //      if (jarVirtualFile != null) {
            //        return jarVirtualFile.getPath();
            //      }
            // However, the above methods will do some extra string manipulation and
            // VirtualFile lookup which we don't actually need (we're just after the
            // raw URL suffix)
            val file = containingFile.virtualFile
            if (file != null && file.fileSystem.protocol == URLUtil.JAR_PROTOCOL) {
                val path = file.path
                val separatorIndex = path.indexOf(URLUtil.JAR_SEPARATOR)
                if (separatorIndex >= 0) {
                    return path.substring(0, separatorIndex)
                }
            }
        }

        return null
    }

    override fun getPackage(node: PsiElement): PsiPackage? {
        val containingFile = node as? PsiFile ?: node.containingFile
        if (containingFile != null) {
            // Optimization: JavaDirectoryService can be slow so try to compute it directly
            if (containingFile is PsiJavaFile) {
                return packageInfoCache.computeIfAbsent(containingFile.packageName) { name ->
                    val cls = findClass(name + '.' + PsiPackage.PACKAGE_INFO_CLASS)
                    val modifierList = cls?.modifierList
                    object : PsiPackageImpl(node.manager, name) {
                        override fun getAnnotationList(): PsiModifierList? {
                            return if (modifierList != null) {
                                // Use composite even if we just have one such that we don't
                                // pass a modifier list tied to source elements in the class
                                // (modifier lists can be part of the AST)
                                PsiCompositeModifierList(
                                    manager,
                                    listOf(modifierList)
                                )
                            } else null
                        }
                    }
                }
            }

            val dir = containingFile.parent
            if (dir != null) {
                return JavaDirectoryService.getInstance().getPackage(dir)
            }
        }
        return null
    }

    override fun getPackage(node: UElement): PsiPackage? {
        val uFile = node.getContainingUFile()
        return if (uFile != null) {
            getPackage(uFile.psi)
        } else null
    }

    override fun getQualifiedName(psiClassType: PsiClassType): String? {
        val erased = erasure(psiClassType)
        return if (erased is PsiClassType) {
            super.getQualifiedName((erased as PsiClassType?)!!)
        } else super.getQualifiedName(psiClassType)
    }

    override fun getQualifiedName(psiClass: PsiClass): String? {
        return psiClass.qualifiedName
    }

    @Suppress("OverridingDeprecatedMember", "DEPRECATION")
    override fun getInternalName(psiClassType: PsiClassType): String? {
        val erased = erasure(psiClassType)
        return if (erased is PsiClassType) {
            super.getInternalName((erased as PsiClassType?)!!)
        } else super.getInternalName(psiClassType)
    }

    @Suppress("OverridingDeprecatedMember")
    override fun getInternalName(psiClass: PsiClass): String? {
        return com.android.tools.lint.detector.api.getInternalName(psiClass)
    }

    override fun erasure(type: PsiType?): PsiType? {
        return TypeConversionUtil.erasure(type)
    }

    override fun computeArgumentMapping(call: UCallExpression, method: PsiMethod):
            Map<UExpression, PsiParameter> {
        val parameterList = method.parameterList
        if (parameterList.parametersCount == 0) {
            return emptyMap()
        }

        // Call into lint-kotlin to look up the argument mapping if this call is a Kotlin method.
        val kotlinMap = computeKotlinArgumentMapping(call, method)
        if (kotlinMap != null) {
            return kotlinMap
        }

        val arguments = call.valueArguments
        val parameters = parameterList.parameters

        var j = 0
        if (parameters.isNotEmpty() && "\$receiver" == parameters[0].name &&
            isKotlin(call.sourcePsi)
        ) {
            // Kotlin extension method.
            j++
        }

        var i = 0
        val n = Math.min(parameters.size, arguments.size)
        val map = HashMap<UExpression, PsiParameter>(2 * n)

        /* Here is a UAST supported way to compute this, but it doesn't handle
           varargs well (some unit tests fail showing the particular scenarios)
        if (call is UCallExpressionEx) {
            for (index in 0 until parameters.size) {
                val argument = call.getArgumentForParameter(index) ?: continue
                val parameter = parameters[index]
                map[argument] = parameter
            }

            return map
        }
         */

        while (j < n) {
            val argument = arguments[i]
            val parameter = parameters[j]
            map[argument] = parameter
            i++
            j++
        }

        if (i < arguments.size && j > 0) {
            // last parameter is varargs (same parameter annotations)
            j--
            while (i < arguments.size) {
                val argument = arguments[i]
                val parameter = parameters[j]
                map[argument] = parameter
                i++
            }
        }

        return map
    }
}
