/*
 * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.generators.interpreter

import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.generators.TypeTranslatorImpl
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.utils.Printer
import java.io.File

val DESTINATION = File("compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/builtins/IrBuiltInsMapGenerated.kt")

fun main() {
    GeneratorsFileUtil.writeFileIfContentChanged(DESTINATION, generateMap())
}

fun generateMap(): String {
    val sb = StringBuilder()
    val p = Printer(sb)
    p.println(File("license/COPYRIGHT.txt").readText())
    p.println("@file:Suppress(\"DEPRECATION\", \"DEPRECATION_ERROR\", \"UNCHECKED_CAST\")")
    p.println()
    p.println("package org.jetbrains.kotlin.ir.interpreter.builtins")
    p.println()
    p.println("import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterMethodNotFoundError")
    p.println("import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy")
    p.println()
    p.println("/** This file is generated by `./gradlew generateInterpreterMap`. DO NOT MODIFY MANUALLY */")
    p.println()

    val irBuiltIns = getIrBuiltIns()

    generateInterpretUnaryFunction(p, getOperationMap(1).apply {
        val irNullCheck = irBuiltIns.checkNotNullSymbol.owner
        this += Operation(irNullCheck.name.asString(), listOf("T0?"), customExpression = "a!!")
        this += Operation("toString", listOf("Any?"), customExpression = "a?.toString() ?: \"null\"")
    })

    generateInterpretBinaryFunction(p, getOperationMap(2) + getBinaryIrOperationMap(irBuiltIns))

    generateInterpretTernaryFunction(p, getOperationMap(3))

    return sb.toString()
}

private fun generateInterpretUnaryFunction(p: Printer, unaryOperations: List<Operation>) {
    p.println("internal fun interpretUnaryFunction(name: String, type: String, a: Any?): Any? {")
    p.pushIndent()
    p.println("when (name) {")
    p.pushIndent()
    for ((name, operations) in unaryOperations.groupBy(Operation::name)) {
        p.println("\"$name\" -> when (type) {")
        p.pushIndent()
        for (operation in operations) {
            p.println("\"${operation.typeA}\" -> return ${operation.expressionString}")
        }
        p.popIndent()
        p.println("}")
    }
    p.popIndent()
    p.println("}")
    p.println("throw InterpreterMethodNotFoundError(\"Unknown function: \$name(\$type)\")")
    p.popIndent()
    p.println("}")
    p.println()
}

private fun generateInterpretBinaryFunction(p: Printer, binaryOperations: List<Operation>) {
    p.println("internal fun interpretBinaryFunction(name: String, typeA: String, typeB: String, a: Any?, b: Any?): Any? {")
    p.pushIndent()
    p.println("when (name) {")
    p.pushIndent()
    for ((name, operations) in binaryOperations.groupBy(Operation::name)) {
        p.println("\"$name\" -> when (typeA) {")
        p.pushIndent()
        for ((typeA, operationsOnTypeA) in operations.groupBy(Operation::typeA)) {
            val singleOperation = operationsOnTypeA.singleOrNull()
            if (singleOperation != null) {
                // Slightly improve readability if there's only one operation with such name and typeA.
                p.println("\"$typeA\" -> if (typeB == \"${singleOperation.typeB}\") return ${singleOperation.expressionString}")
            } else {
                p.println("\"$typeA\" -> when (typeB) {")
                p.pushIndent()
                for ((typeB, operationsOnTypeB) in operationsOnTypeA.groupBy(Operation::typeB)) {
                    for (operation in operationsOnTypeB) {
                        p.println("\"$typeB\" -> return ${operation.expressionString}")
                    }
                }
                p.popIndent()
                p.println("}")
            }
        }
        p.popIndent()
        p.println("}")
    }
    p.popIndent()
    p.println("}")
    p.println("throw InterpreterMethodNotFoundError(\"Unknown function: \$name(\$typeA, \$typeB)\")")
    p.popIndent()
    p.println("}")
    p.println()
}

private fun generateInterpretTernaryFunction(p: Printer, ternaryOperations: List<Operation>) {
    p.println("internal fun interpretTernaryFunction(name: String, typeA: String, typeB: String, typeC: String, a: Any?, b: Any?, c: Any?): Any {")
    p.pushIndent()
    p.println("when (name) {")
    p.pushIndent()
    for ((name, operations) in ternaryOperations.groupBy(Operation::name)) {
        p.println("\"$name\" -> when (typeA) {")
        p.pushIndent()
        for (operation in operations) {
            val (typeA, typeB, typeC) = operation.parameterTypes
            p.println("\"$typeA\" -> if (typeB == \"$typeB\" && typeC == \"$typeC\") return ${operation.expressionString}")
        }
        p.popIndent()
        p.println("}")
    }
    p.popIndent()
    p.println("}")
    p.println("throw InterpreterMethodNotFoundError(\"Unknown function: \$name(\$typeA, \$typeB, \$typeC)\")")
    p.popIndent()
    p.println("}")
    p.println()
}

private fun castValue(name: String, type: String): String = when (type) {
    "Any?", "T" -> name
    "Array" -> "$name as Array<Any?>"
    "Comparable" -> "$name as Comparable<Any?>"
    else -> "$name as $type"
}

private fun castValueParenthesized(name: String, type: String): String =
    if (type == "Any?") name else "(${castValue(name, type)})"

private data class Operation(
    val name: String,
    val parameterTypes: List<String>,
    val isFunction: Boolean = true,
    val customExpression: String? = null,
) {
    val typeA: String get() = parameterTypes[0]
    val typeB: String get() = parameterTypes[1]

    val expressionString: String
        get() {
            val receiver = castValueParenthesized("a", typeA)
            println(name)
            return when {
                name == IrBuiltIns.OperatorNames.EQEQEQ && parameterTypes.all { it == "Any?" } ->
                    "if (a is Proxy && b is Proxy) a.state === b.state else a === b"
                customExpression != null -> customExpression
                else -> buildString {
                    append(receiver)
                    append(".")
                    append(name)
                    if (isFunction) append("(")
                    parameterTypes.withIndex().drop(1).joinTo(this) { (index, type) ->
                        castValue(('a' + index).toString(), type)
                    }
                    if (isFunction) append(")")
                }
            }
        }
}

private fun getOperationMap(argumentsCount: Int): MutableList<Operation> {
    val builtIns = DefaultBuiltIns.Instance
    val operationMap = mutableListOf<Operation>()
    val allPrimitiveTypes = PrimitiveType.values().map { builtIns.getBuiltInClassByFqName(it.typeFqName) }
    val arrays = PrimitiveType.values().map { builtIns.getPrimitiveArrayClassDescriptor(it) } + builtIns.array
    val additionalBuiltIns = listOf(
        builtIns.string, builtIns.any, builtIns.charSequence, builtIns.number, builtIns.comparable, builtIns.throwable
    )

    fun CallableDescriptor.isFakeOverride(classDescriptor: ClassDescriptor): Boolean {
        val isPrimitive = KotlinBuiltIns.isPrimitiveClass(classDescriptor) || KotlinBuiltIns.isString(classDescriptor.defaultType)
        val isFakeOverridden = (this as? FunctionDescriptor)?.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
        return !isPrimitive && isFakeOverridden
    }

    for (classDescriptor in allPrimitiveTypes + additionalBuiltIns + arrays) {
        val compileTimeFunctions = classDescriptor.unsubstitutedMemberScope.getContributedDescriptors()
            .filterIsInstance<CallableDescriptor>()
            .filter { !it.isFakeOverride(classDescriptor) && it.valueParameters.size + 1 == argumentsCount }

        for (function in compileTimeFunctions) {
            operationMap.add(
                Operation(
                    function.name.asString(),
                    listOf(classDescriptor.defaultType.constructor.toString()) + function.valueParameters.map { it.type.toString() },
                    function is FunctionDescriptor
                )
            )
        }
    }

    return operationMap
}

private fun getBinaryIrOperationMap(irBuiltIns: IrBuiltIns): List<Operation> {
    val operationMap = mutableListOf<Operation>()
    val irFunSymbols =
        (irBuiltIns.lessFunByOperandType.values + irBuiltIns.lessOrEqualFunByOperandType.values +
                irBuiltIns.greaterFunByOperandType.values + irBuiltIns.greaterOrEqualFunByOperandType.values +
                irBuiltIns.eqeqSymbol + irBuiltIns.eqeqeqSymbol + irBuiltIns.ieee754equalsFunByOperandType.values +
                irBuiltIns.andandSymbol + irBuiltIns.ororSymbol)
            .map { it.owner }

    for (function in irFunSymbols) {
        val parametersTypes = function.valueParameters.map { it.type.originalKotlinType!!.toString() }

        check(parametersTypes.size == 2) { "Couldn't add following method from ir builtins to operations map: ${function.name}" }
        operationMap.add(
            Operation(
                function.name.asString(), parametersTypes,
                customExpression = castValueParenthesized("a", parametersTypes[0]) + " " +
                        getIrMethodSymbolByName(function.name.asString()) + " " +
                        castValueParenthesized("b", parametersTypes[1])
            )
        )
    }

    return operationMap
}

private fun getIrMethodSymbolByName(methodName: String): String {
    return when (methodName) {
        IrBuiltIns.OperatorNames.LESS -> "<"
        IrBuiltIns.OperatorNames.LESS_OR_EQUAL -> "<="
        IrBuiltIns.OperatorNames.GREATER -> ">"
        IrBuiltIns.OperatorNames.GREATER_OR_EQUAL -> ">="
        IrBuiltIns.OperatorNames.EQEQ -> "=="
        IrBuiltIns.OperatorNames.EQEQEQ -> "==="
        IrBuiltIns.OperatorNames.IEEE754_EQUALS -> "=="
        IrBuiltIns.OperatorNames.ANDAND -> "&&"
        IrBuiltIns.OperatorNames.OROR -> "||"
        else -> throw UnsupportedOperationException("Unknown ir operation \"$methodName\"")
    }
}

private fun getIrBuiltIns(): IrBuiltIns {
    val languageSettings = LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3)

    val moduleDescriptor = ModuleDescriptorImpl(Name.special("<test-module>"), LockBasedStorageManager(""), DefaultBuiltIns.Instance)
    val signaturer = object : IdSignatureComposer {
        override fun composeSignature(descriptor: DeclarationDescriptor): IdSignature? = null

        override fun composeEnumEntrySignature(descriptor: ClassDescriptor): IdSignature? = null
    }
    val symbolTable = SymbolTable(signaturer, IrFactoryImpl)
    val typeTranslator = TypeTranslatorImpl(symbolTable, languageSettings, moduleDescriptor)
    return IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, symbolTable)
}
