/*
 * Copyright 2018 The Bazel Authors. All rights reserved.
 *
 * 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 io.bazel.kotlin.builder

import com.google.inject.*
import com.google.inject.util.Modules
import io.bazel.kotlin.builder.utils.executeAndAwait
import io.bazel.kotlin.builder.utils.resolveVerified
import io.bazel.kotlin.builder.utils.verifiedRelativeFiles
import org.jetbrains.kotlin.preloading.ClassPreloadingUtils
import org.jetbrains.kotlin.preloading.Preloader
import java.io.File
import java.io.PrintStream
import java.io.PrintWriter
import java.nio.file.Path
import java.nio.file.Paths

class KotlinToolchain constructor(
    val kotlinLibraryDirectory: Path,
    val kotlinStandardLibraries: Array<String> = arrayOf(
        "kotlin-stdlib.jar",
        "kotlin-stdlib-jdk7.jar",
        "kotlin-stdlib-jdk8.jar"
    )
) : AbstractModule() {
    companion object {
        internal val NO_ARGS = arrayOf<Any>()

        @JvmStatic
        fun createInjector(output: PrintStream, overrides: Module? = null): Injector =
            Guice.createInjector(
                object : AbstractModule() {
                    override fun configure() {
                        bind(PrintStream::class.java).toInstance(output)
                        install(
                            KotlinToolchain.TCModule(
                                javaHome = Paths.get("external", "local_jdk"),
                                kotlinHome = Paths.get("external", "com_github_jetbrains_kotlin")
                            )
                        )
                    }
                }.let { module -> overrides?.let { Modules.override(module).with(it) }?: module }
            )
    }

    data class CompilerPlugin(val jarPath: String, val id: String) {
        @BindingAnnotation
        annotation class Kapt3
    }

    interface JavacInvoker {
        fun compile(args: Array<String>): Int
        fun compile(args: Array<String>, out: PrintWriter): Int
    }


    interface JDepsInvoker {
        fun run(args: Array<String>, out: PrintWriter): Int
    }


    interface KotlincInvoker {
        fun compile(args: Array<String>, out: PrintStream): Int
    }

    interface JarToolInvoker {
        fun invoke(args: List<String>, directory: File? = null)
    }

    private class TCModule constructor(
        javaHome: Path,
        kotlinHome: Path,
        kotlinLibraryDirectory: Path = kotlinHome.resolveVerified("lib").toPath(),
        kapt3Jar: File= kotlinLibraryDirectory.resolveVerified("kotlin-annotation-processing.jar"),
        classloader: ClassLoader = ClassPreloadingUtils.preloadClasses(
            mutableListOf<File>().let {
                it.addAll(kotlinLibraryDirectory.verifiedRelativeFiles(Paths.get("kotlin-compiler.jar")))
                it.addAll(javaHome.verifiedRelativeFiles(Paths.get("lib", "tools.jar")))
                it.toList()
            },
            Preloader.DEFAULT_CLASS_NUMBER_ESTIMATE,
            Thread.currentThread().contextClassLoader,
            null
        )
    ): AbstractModule() {
        private val toolchain = KotlinToolchain(kotlinHome)

        private val kapt3 = CompilerPlugin(kapt3Jar.toString(), "org.jetbrains.kotlin.kapt3")

        private val jarToolInvoker = object : JarToolInvoker {
            val jarToolPath = javaHome.resolveVerified("bin", "jar").absolutePath.toString()
            override fun invoke(args: List<String>, directory: File?) {
                val command = mutableListOf(jarToolPath).also { it.addAll(args) }
                executeAndAwait(10, directory, command).takeIf { it != 0 }?.also {
                    throw CompilationStatusException("error running jar command ${command.joinToString(" ")}", it)
                }
            }
        }

        private val javacInvoker = object : JavacInvoker {
            val c = classloader.loadClass("com.sun.tools.javac.Main")
            val m = c.getMethod("compile", Array<String>::class.java)
            val mPw = c.getMethod("compile", Array<String>::class.java, PrintWriter::class.java)
            override fun compile(args: Array<String>) = m.invoke(c, args) as Int
            override fun compile(args: Array<String>, out: PrintWriter) = mPw.invoke(c, args, out) as Int
        }

        private val jdepsInvoker = object : JDepsInvoker {
            val clazz = classloader.loadClass("com.sun.tools.jdeps.Main")
            val method = clazz.getMethod("run", Array<String>::class.java, PrintWriter::class.java)
            override fun run(args: Array<String>, out: PrintWriter): Int = method.invoke(clazz, args, out) as Int
        }

        private val kotlincInvoker = object : KotlincInvoker {
            val compilerClass = classloader.loadClass("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler")
            val exitCodeClass = classloader.loadClass("org.jetbrains.kotlin.cli.common.ExitCode")

            val compiler = compilerClass.newInstance()
            val execMethod = compilerClass.getMethod("exec", PrintStream::class.java, Array<String>::class.java)
            val getCodeMethod = exitCodeClass.getMethod("getCode")


            override fun compile(args: Array<String>, out: PrintStream): Int {
                val exitCodeInstance: Any
                try {
                    exitCodeInstance = execMethod.invoke(compiler, out, args)
                    return getCodeMethod.invoke(exitCodeInstance, *NO_ARGS) as Int
                } catch (e: Exception) {
                    throw RuntimeException(e)
                }
            }
        }

        override fun configure() {
            bind(KotlinToolchain::class.java).toInstance(toolchain)
            bind(JarToolInvoker::class.java).toInstance(jarToolInvoker)
            bind(JavacInvoker::class.java).toInstance(javacInvoker)
            bind(JDepsInvoker::class.java).toInstance(jdepsInvoker)
            bind(KotlincInvoker::class.java).toInstance(kotlincInvoker)
        }

        @Provides
        @CompilerPlugin.Kapt3
        fun provideKapt3(): CompilerPlugin = kapt3

        @Provides
        fun provideBazelWorker(
            kotlinBuilder: KotlinBuilder,
            output: PrintStream
        ): BazelWorker = BazelWorker(kotlinBuilder, output, "KotlinCompile")
    }
}


