// 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.BufferedReader
import java.io.File
import java.io.IOException
import java.io.InputStreamReader
import java.nio.charset.StandardCharsets
import java.util.Arrays
import java.util.stream.Collectors
import javax.inject.Inject
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputDirectories
import org.gradle.api.tasks.OutputFiles
import org.gradle.api.tasks.TaskAction
import org.gradle.internal.os.OperatingSystem
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters
import org.gradle.workers.WorkerExecutor

abstract class DownloadAllDependenciesTask : DefaultTask() {

  private var _root: File? = null
  private var _thirdPartyDeps: List<ThirdPartyDependency>? = null

  @InputFiles
  fun getInputFile(): List<File> {
    return _thirdPartyDeps!!.map { _root!!.resolve(it.sha1File) }
  }

  @OutputDirectories
  fun getOutputDir(): List<File> {
    return _thirdPartyDeps!!.map { _root!!.resolve(it.path) }
  }

  @OutputFiles
  fun getOutputFiles(): List<File> {
    return _thirdPartyDeps!!.map {
      _root!!.resolve(it.sha1File.resolveSibling(it.sha1File.name.replace(".sha1", "")))
    }
  }

  @Inject protected abstract fun getWorkerExecutor(): WorkerExecutor?

  fun setDependencies(root: File, thirdPartyDeps: List<ThirdPartyDependency>) {
    this._root = root
    this._thirdPartyDeps = thirdPartyDeps
  }

  @TaskAction
  fun execute() {
    val noIsolation = getWorkerExecutor()!!.noIsolation()
    _thirdPartyDeps?.forEach {
      val root = _root!!
      val sha1File = root.resolve(it.sha1File)
      val tarGzFile = sha1File.resolveSibling(sha1File.name.replace(".sha1", ""))
      val outputDir = root.resolve(it.path)
      if (!sha1File.exists()) {
        throw RuntimeException("Missing sha1 file: $sha1File")
      }
      if (shouldExecute(outputDir, tarGzFile, sha1File)) {
        println("Downloading ${it}")
        noIsolation.submit(RunDownload::class.java) {
          type.set(it.type)
          this.sha1File.set(sha1File)
          this.outputDir.set(outputDir)
          this.tarGzFile.set(tarGzFile)
          this.root.set(root)
        }
      }
    }
  }

  interface RunDownloadParameters : WorkParameters {
    val type: Property<DependencyType>
    val sha1File: RegularFileProperty
    val outputDir: RegularFileProperty
    val tarGzFile: RegularFileProperty
    val root: RegularFileProperty
  }

  abstract class RunDownload : WorkAction<RunDownloadParameters> {
    override fun execute() {
      val sha1File = parameters.sha1File.asFile.get()
      val outputDir = parameters.outputDir.asFile.get()
      val tarGzFile = parameters.tarGzFile.asFile.get()
      if (!shouldExecute(outputDir, tarGzFile, sha1File)) {
        return
      }
      if (outputDir.exists() && outputDir.isDirectory) {
        outputDir.delete()
      }
      when (parameters.type.get()) {
        DependencyType.GOOGLE_STORAGE -> {
          downloadFromGoogleStorage(parameters, sha1File)
        }
        DependencyType.X20 -> {
          downloadFromX20(parameters, sha1File)
        }
      }
    }

    @Throws(IOException::class, InterruptedException::class)
    private fun downloadFromGoogleStorage(parameters: RunDownloadParameters, sha1File: File) {
      val args = Arrays.asList("-n", "-b", "r8-deps", "-s", "-u", sha1File.toString())
      if (OperatingSystem.current().isWindows) {
        val command: MutableList<String> = ArrayList()
        command.add("download_from_google_storage.bat")
        command.addAll(args)
        runProcess(parameters, ProcessBuilder().command(command))
      } else {
        runProcess(
          parameters,
          ProcessBuilder()
            .command(
              "bash",
              "-c",
              "download_from_google_storage " + java.lang.String.join(" ", args),
            ),
        )
      }
    }

    @Throws(IOException::class, InterruptedException::class)
    private fun downloadFromX20(parameters: RunDownloadParameters, sha1File: File) {
      if (OperatingSystem.current().isWindows) {
        throw RuntimeException("Downloading from x20 unsupported on windows")
      }
      runProcess(
        parameters,
        ProcessBuilder().command("bash", "-c", "tools/download_from_x20.py $sha1File"),
      )
    }

    @Throws(IOException::class, InterruptedException::class)
    private fun runProcess(parameters: RunDownloadParameters, builder: ProcessBuilder) {
      builder.directory(parameters.root.asFile.get())
      val command = java.lang.String.join(" ", builder.command())
      val p = builder.start()
      val exit = p.waitFor()
      if (exit != 0) {
        throw IOException(
          "Process failed for $command\n" +
            BufferedReader(InputStreamReader(p.errorStream, StandardCharsets.UTF_8))
              .lines()
              .collect(Collectors.joining("\n"))
        )
      }
    }
  }

  companion object {
    fun shouldExecute(outputDir: File, tarGzFile: File, sha1File: File): Boolean {
      // First run will write the tar.gz file, causing the second run to still be out-of-date.
      // Check if the modification time of the tar is newer than the sha in which case we are done.
      if (
        outputDir.exists() &&
          outputDir.isDirectory &&
          outputDir.list()!!.isNotEmpty() &&
          tarGzFile.exists() &&
          sha1File.lastModified() <= tarGzFile.lastModified()
      ) {
        return false
      }
      return true
    }
  }
}
