/*
 * Copyright (C) 2020 The Dagger Authors.
 *
 * 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.
 */

import java.io.File
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.BuildTask
import org.gradle.testkit.runner.GradleRunner
import org.junit.rules.TemporaryFolder

/**
 * Testing utility class that sets up a simple Android project that applies the Hilt plugin.
 */
class GradleTestRunner(val tempFolder: TemporaryFolder) {
  private val dependencies = mutableListOf<String>()
  private val activities = mutableListOf<String>()
  private val additionalAndroidOptions = mutableListOf<String>()
  private val hiltOptions = mutableListOf<String>()
  private var appClassName: String? = null
  private var buildFile: File? = null
  private var gradlePropertiesFile: File? = null
  private var manifestFile: File? = null
  private var additionalTasks = mutableListOf<String>()

  init {
    tempFolder.newFolder("src", "main", "java", "minimal")
    tempFolder.newFolder("src", "test", "java", "minimal")
    tempFolder.newFolder("src", "main", "res")
  }

  // Adds project dependencies, e.g. "implementation <group>:<id>:<version>"
  fun addDependencies(vararg deps: String) {
    dependencies.addAll(deps)
  }

  // Adds an <activity> tag in the project's Android Manifest, e.g. "<activity name=".Foo"/>
  fun addActivities(vararg activityElements: String) {
    activities.addAll(activityElements)
  }

  // Adds 'android' options to the project's build.gradle, e.g. "lintOptions.checkReleaseBuilds = false"
  fun addAndroidOption(vararg options: String) {
    additionalAndroidOptions.addAll(options)
  }

  // Adds 'hilt' options to the project's build.gradle, e.g. "enableExperimentalClasspathAggregation = true"
  fun addHiltOption(vararg options: String) {
    hiltOptions.addAll(options)
  }

  // Adds a source package to the project. The package path is relative to 'src/main/java'.
  fun addSrcPackage(packagePath: String) {
    File(tempFolder.root, "src/main/java/$packagePath").mkdirs()
  }

  // Adds a source file to the project. The source path is relative to 'src/main/java'.
  fun addSrc(srcPath: String, srcContent: String): File {
    File(tempFolder.root, "src/main/java/${srcPath.substringBeforeLast(File.separator)}").mkdirs()
    return tempFolder.newFile("/src/main/java/$srcPath").apply { writeText(srcContent) }
  }

  // Adds a test source file to the project. The source path is relative to 'src/test/java'.
  fun addTestSrc(srcPath: String, srcContent: String): File {
    File(tempFolder.root, "src/test/java/${srcPath.substringBeforeLast(File.separator)}").mkdirs()
    return tempFolder.newFile("/src/test/java/$srcPath").apply { writeText(srcContent) }
  }

  // Adds a resource file to the project. The source path is relative to 'src/main/res'.
  fun addRes(resPath: String, resContent: String): File {
    File(tempFolder.root, "src/main/res/${resPath.substringBeforeLast(File.separator)}").mkdirs()
    return tempFolder.newFile("/src/main/res/$resPath").apply { writeText(resContent) }
  }

  fun setAppClassName(name: String) {
    appClassName = name
  }

  fun runAdditionalTasks(taskName: String) {
    additionalTasks.add(taskName)
  }

  // Executes a Gradle builds and expects it to succeed.
  fun build(): Result {
    setupFiles()
    return Result(tempFolder.root, createRunner().build())
  }

  // Executes a Gradle build and expects it to fail.
  fun buildAndFail(): Result {
    setupFiles()
    return Result(tempFolder.root, createRunner().buildAndFail())
  }

  private fun setupFiles() {
    writeBuildFile()
    writeGradleProperties()
    writeAndroidManifest()
  }

  private fun writeBuildFile() {
    buildFile?.delete()
    buildFile = tempFolder.newFile("build.gradle").apply {
      writeText(
        """
        buildscript {
          repositories {
            google()
            mavenCentral()
          }
          dependencies {
            classpath 'com.android.tools.build:gradle:4.2.0'
          }
        }

        plugins {
          id 'com.android.application'
          id 'dagger.hilt.android.plugin'
        }

        android {
          compileSdkVersion 30
          buildToolsVersion "30.0.2"

          defaultConfig {
            applicationId "plugin.test"
            minSdkVersion 21
            targetSdkVersion 30
          }

          compileOptions {
              sourceCompatibility 1.8
              targetCompatibility 1.8
          }
          ${additionalAndroidOptions.joinToString(separator = "\n")}
        }

        allprojects {
          repositories {
            mavenLocal()
            google()
            mavenCentral()
          }
        }

        dependencies {
          ${dependencies.joinToString(separator = "\n")}
        }

        hilt {
          ${hiltOptions.joinToString(separator = "\n")}
        }
        """.trimIndent()
      )
    }
  }

  private fun writeGradleProperties() {
    gradlePropertiesFile?.delete()
    gradlePropertiesFile = tempFolder.newFile("gradle.properties").apply {
      writeText(
        """
        android.useAndroidX=true
        """.trimIndent()
      )
    }
  }

  private fun writeAndroidManifest() {
    manifestFile?.delete()
    manifestFile = tempFolder.newFile("/src/main/AndroidManifest.xml").apply {
      writeText(
        """
        <?xml version="1.0" encoding="utf-8"?>
        <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="minimal">
            <application
                android:name="${appClassName ?: "android.app.Application"}"
                android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
                ${activities.joinToString(separator = "\n")}
            </application>
        </manifest>
        """.trimIndent()
      )
    }
  }

  private fun createRunner() = GradleRunner.create()
    .withProjectDir(tempFolder.root)
    .withArguments(listOf("--stacktrace", "assembleDebug") + additionalTasks)
    .withPluginClasspath()
//    .withDebug(true) // Add this line to enable attaching a debugger to the gradle test invocation
    .forwardOutput()

  // Data class representing a Gradle Test run result.
  data class Result(
    private val projectRoot: File,
    private val buildResult: BuildResult
  ) {

    val tasks: List<BuildTask> get() = buildResult.tasks

    // Finds a task by name.
    fun getTask(name: String) = buildResult.task(name) ?: error("Task '$name' not found.")

    // Gets the full build output.
    fun getOutput() = buildResult.output

    // Finds a transformed file. The srcFilePath is relative to the app's package.
    fun getTransformedFile(srcFilePath: String): File {
      val parentDir =
        File(projectRoot, "build/intermediates/asm_instrumented_project_classes/debug")
      return File(parentDir, srcFilePath).also {
        if (!it.exists()) {
          error("Unable to find transformed class ${it.path}")
        }
      }
    }
  }
}
