// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import java.io.ByteArrayOutputStream
import java.io.File
import java.io.PrintStream
import java.nio.charset.StandardCharsets
import java.util.Date
import java.util.concurrent.TimeUnit
import org.gradle.api.Project
import org.gradle.api.tasks.testing.Test
import org.gradle.api.tasks.testing.TestDescriptor
import org.gradle.api.tasks.testing.TestListener
import org.gradle.api.tasks.testing.TestResult

class TestConfigurationHelper {

  companion object {

    fun retrace(project: Project, r8jar: File, mappingFile: File, exception: Throwable): String {
      val out = StringBuilder()
      val header = "RETRACED STACKTRACE: " + System.currentTimeMillis()
      out.append("\n--------------------------------------\n")
      out.append("${header}\n")
      out.append("--------------------------------------\n")
      val retracePath = project.getRoot().resolveAll("tools", "retrace.py")
      val command =
              mutableListOf(
                      "python3", retracePath.toString(),
                      "--quiet",
                      "--map", mappingFile.toString(),
                      "--r8jar", r8jar.toString())
      val process = ProcessBuilder(command).start()
      process.outputStream.use { exception.printStackTrace(PrintStream(it)) }
      process.outputStream.close()
      val processCompleted = process.waitFor(20L, TimeUnit.SECONDS)
        && process.exitValue() == 0
      out.append(process.inputStream.bufferedReader().use { it.readText() })
      if (!processCompleted) {
        out.append(command.joinToString(" ") + "\n")
        out.append("ERROR DURING RETRACING: " + System.currentTimeMillis() + "\n")
        out.append(process.errorStream.bufferedReader().use { it.readText() })
      }
      if (project.hasProperty("print_obfuscated_stacktraces") || !processCompleted) {
        out.append("\n\n--------------------------------------\n")
        out.append("OBFUSCATED STACKTRACE\n")
        out.append("--------------------------------------\n")
        var baos = ByteArrayOutputStream();
        exception.printStackTrace(PrintStream(baos, true, StandardCharsets.UTF_8))
        out.append(baos.toString())
      }
      return out.toString()
    }

    fun setupTestTask(test: Test, isR8Lib: Boolean, r8Jar: File?, r8LibMappingFile: File?) {
      val project = test.project
      if (project.hasProperty("testfilter")) {
        val testFilter = project.property("testfilter").toString()
        test.filter.setFailOnNoMatchingTests(false)
        test.filter.setIncludePatterns(*(testFilter.split("|").toTypedArray()))
      }
      if (project.hasProperty("kotlin_compiler_dev")) {
        test.systemProperty("com.android.tools.r8.kotlincompilerdev", "1")
      }

      if (project.hasProperty("kotlin_compiler_old")) {
        test.systemProperty("com.android.tools.r8.kotlincompilerold", "1")
      }

      if (project.hasProperty("dex_vm")
          && project.property("dex_vm") != "default") {
        println("NOTE: Running with non default vm: " + project.property("dex_vm"))
        test.systemProperty("dex_vm", project.property("dex_vm")!!)
      }

      // Forward runtime configurations for test parameters.
      if (project.hasProperty("runtimes")) {
        println("NOTE: Running with runtimes: " + project.property("runtimes"))
        test.systemProperty("runtimes", project.property("runtimes")!!)
      }

      if (project.hasProperty("art_profile_rewriting_completeness_check")) {
        test.systemProperty(
          "com.android.tools.r8.artprofilerewritingcompletenesscheck",
          project.property("art_profile_rewriting_completeness_check")!!)
      }

      if (project.hasProperty("disable_assertions")) {
        test.enableAssertions = false
      }

      // Forward project properties into system properties.
      listOf(
        "local_development",
        "slow_tests",
        "desugar_jdk_json_dir",
        "desugar_jdk_libs",
        "test_dir",
        "command_cache_dir",
        "command_cache_stats_dir").forEach {
        val propertyName = it
        if (project.hasProperty(propertyName)) {
          project.property(propertyName)?.let { v -> test.systemProperty(propertyName, v) }
        }
      }

      if (project.hasProperty("no_internal")) {
        test.exclude("com/android/tools/r8/internal/**")
      }
      if (project.hasProperty("only_internal")) {
        test.include("com/android/tools/r8/internal/**")
      }
      if (project.hasProperty("no_arttests")) {
        test.exclude("com/android/tools/r8/art/**")
      }

      if (project.hasProperty("test_xmx")) {
        test.maxHeapSize = project.property("test_xmx")!!.toString()
      } else {
        test.maxHeapSize = "4G"
      }

      if (isR8Lib
        || project.hasProperty("one_line_per_test")
        || project.hasProperty("update_test_timestamp")) {
        test.addTestListener(object : TestListener {
          val testTimes = mutableMapOf<TestDescriptor?,Long>()
          val maxPrintTimesCount = 200
          override fun beforeSuite(desc: TestDescriptor?) {}
          override fun afterSuite(desc: TestDescriptor?, result: TestResult?) {
            if (project.hasProperty("print_times")) {
              // desc.parent == null when we are all done
              if (desc?.parent == null) {
                testTimes.toList()
                  .sortedByDescending { it.second }
                  .take(maxPrintTimesCount)
                  .forEach {
                    println("${it.first} took: ${it.second}")
                }
              }
            }
          }
          override fun beforeTest(desc: TestDescriptor?) {
            if (project.hasProperty("one_line_per_test")) {
              println("Start executing ${desc}")
            }
            if (project.hasProperty("print_times")) {
              testTimes[desc] = Date().getTime()
            }
          }

          override fun afterTest(desc: TestDescriptor?, result: TestResult?) {
            if (project.hasProperty("one_line_per_test")) {
              println("Done executing ${desc} with result: ${result?.resultType}")
            }
            if (project.hasProperty("print_times")) {
              testTimes[desc] = Date().getTime() - testTimes[desc]!!
            }
            if (project.hasProperty("update_test_timestamp")) {
              File(project.property("update_test_timestamp")!!.toString())
                .writeText(Date().getTime().toString())
            }
            if (isR8Lib
              && result?.resultType == TestResult.ResultType.FAILURE
              && result.exception != null) {
              println(retrace(project, r8Jar!!, r8LibMappingFile!!, result.exception as Throwable))
            }
          }
        })
      }

      val userDefinedCoresPerFork = System.getenv("R8_GRADLE_CORES_PER_FORK")
      val processors = Runtime.getRuntime().availableProcessors()
      // See https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html.
      if (!userDefinedCoresPerFork.isNullOrEmpty()) {
        test.maxParallelForks = processors.div(userDefinedCoresPerFork.toInt())
      } else {
        // On work machines this seems to give the best test execution time (without freezing).
        test.maxParallelForks = maxOf(processors.div(3), 1)
        // On low cpu count machines (bots) we under subscribe, so increase the count.
        if (processors == 32) {
          test.maxParallelForks = 15
        }
      }
    }
  }
}
