// This script is used to initialize the build in a module or plugin project.
// During this phase, the script applies the Maven plugin and configures the
// destination of the local repository.
// The local repository will contain the AAR and POM files.

import java.nio.file.Paths
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.publish.maven.MavenPublication

void configureProject(Project project, String outputDir) {
    if (!project.hasProperty("android")) {
        throw new GradleException("Android property not found.")
    }
    if (!project.android.hasProperty("libraryVariants")) {
        throw new GradleException("Can't generate AAR on a non Android library project.");
    }

    // Snapshot versions include the timestamp in the artifact name.
    // Therefore, remove the snapshot part, so new runs of `flutter build aar` overrides existing artifacts.
    // This version isn't relevant in Flutter since the pub version is used
    // to resolve dependencies.
    project.version = project.version.replace("-SNAPSHOT", "")

    if (project.hasProperty("buildNumber")) {
        project.version = project.property("buildNumber")
    }

    project.android.libraryVariants.all { variant ->
        addAarTask(project, variant)
    }

    project.publishing {
        repositories {
            maven {
                url = uri("file://${outputDir}/outputs/repo")
            }
        }
    }

    // Some extra work to have alternative publications with the same format as the old maven plugin.
    // Instead of using classifiers for the variants, the old maven plugin appended `_{variant}` to the artifactId

    // First, create a default MavenPublication for each variant (except "all" since that is used to publish artifacts in the new way)
    project.components.forEach { component ->
        if (component.name != "all") {
            project.publishing.publications.create(component.name, MavenPublication) {
                from component
            }
        }
    }

    // then, rename the artifactId to include the variant and make sure to remove any classifier
    // data tha gradle has set, as well as adding a <relocation> tag pointing to the new coordinates
    project.publishing.publications.forEach { pub ->
        def relocationArtifactId = pub.artifactId
        pub.artifactId = "${relocationArtifactId}_${pub.name}"
        pub.alias = true

        pub.pom.distributionManagement {
            relocation {
                // New artifact coordinates
                groupId = "${pub.groupId}"
                artifactId = "${relocationArtifactId}"
                version = "${pub.version}"
                message = "Use classifiers rather than _variant for new publish plugin"
            }
        }

    }

    // also publish the artifacts in the new way, using one set of coordinates with classifiers
    project.publishing.publications.create("all", MavenPublication) {
        from project.components.all
        alias false
    }

    if (!project.property("is-plugin").toBoolean()) {
        return
    }

    String storageUrl = System.getenv('FLUTTER_STORAGE_BASE_URL') ?: "https://storage.googleapis.com"
    // This is a Flutter plugin project. Plugin projects don't apply the Flutter Gradle plugin,
    // as a result, add the dependency on the embedding.
    project.repositories {
        maven {
            url "$storageUrl/download.flutter.io"
        }
    }
    String engineVersion = Paths.get(getFlutterRoot(project), "bin", "internal", "engine.version")
        .toFile().text.trim()
    project.dependencies {
        // Add the embedding dependency.
        compileOnly ("io.flutter:flutter_embedding_release:1.0.0-$engineVersion") {
            // We only need to expose io.flutter.plugin.*
            // No need for the embedding transitive dependencies.
            transitive = false
        }
    }
}

void configurePlugin(Project project, String outputDir) {
    if (!project.hasProperty("android")) {
        // A plugin doesn't support the Android platform when this property isn't defined in the plugin.
        return
    }
    configureProject(project, outputDir)
}

String getFlutterRoot(Project project) {
    if (!project.hasProperty("flutter-root")) {
        throw new GradleException("The `-Pflutter-root` flag must be specified.")
    }
    return project.property("flutter-root")
}

void addAarTask(Project project, variant) {
    String variantName = variant.name.capitalize()
    String taskName = "assembleAar$variantName"
    project.tasks.create(name: taskName) {
        // This check is required to be able to configure the archives before `publish` runs.
        if (!project.gradle.startParameter.taskNames.contains(taskName)) {
            return
        }
        // Generate the Maven artifacts.
        finalizedBy "publish"
    }
}

// maven-publish has to be applied _before_ the project gets evaluated, but some of the code in
// `configureProject` requires the project to be evaluated. Apply the maven plugin to all projects, but
// only configure it if it matches the conditions in `projectsEvaluated`

allprojects {
   apply plugin: "maven-publish"
}

projectsEvaluated {
    assert rootProject.hasProperty("is-plugin")
    if (rootProject.property("is-plugin").toBoolean()) {
        assert rootProject.hasProperty("output-dir")
        // In plugin projects, the root project is the plugin.
        configureProject(rootProject, rootProject.property("output-dir"))
        return
    }
    // The module project is the `:flutter` subproject.
    Project moduleProject = rootProject.subprojects.find { it.name == "flutter" }
    assert moduleProject != null
    assert moduleProject.hasProperty("output-dir")
    configureProject(moduleProject, moduleProject.property("output-dir"))

    // Gets the plugin subprojects.
    Set<Project> modulePlugins = rootProject.subprojects.findAll {
        it.name != "flutter" && it.name != "app"
    }
    // When a module is built as a Maven artifacts, plugins must also be built this way
    // because the module POM's file will include a dependency on the plugin Maven artifact.
    // This is due to the Android Gradle Plugin expecting all library subprojects to be published
    // as Maven artifacts.
    modulePlugins.each { pluginProject ->
        configurePlugin(pluginProject, moduleProject.property("output-dir"))
        moduleProject.android.libraryVariants.all { variant ->
            // Configure the `assembleAar<variantName>` task for each plugin's projects and make
            // the module's equivalent task depend on the plugin's task.
            String variantName = variant.name.capitalize()
            moduleProject.tasks.findByPath("assembleAar$variantName")
                .dependsOn(pluginProject.tasks.findByPath("assembleAar$variantName"))
        }
    }
}
