import groovy.json.JsonSlurper
import org.gradle.internal.logging.text.StyledTextOutputFactory
import static org.gradle.internal.logging.text.StyledTextOutput.Style
import java.nio.file.Paths

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize'

buildscript {
    // project.ext.USER_PROJECT_ROOT = "$rootDir/../../.."
    project.ext.PLATFORMS_ANDROID = "platforms/android"
    project.ext.PLUGIN_NAME = "{{pluginName}}"

    def USER_PROJECT_ROOT_FROM_ENV = System.getenv('USER_PROJECT_ROOT');
    if (USER_PROJECT_ROOT_FROM_ENV != null && !USER_PROJECT_ROOT_FROM_ENV.equals("")) {
        project.ext.USER_PROJECT_ROOT = USER_PROJECT_ROOT_FROM_ENV;
    } else {
        project.ext.USER_PROJECT_ROOT = "$rootDir/../../../"
    }

    def USER_PROJECT_PLATFORMS_ANDROID_FROM_ENV = System.getenv('USER_PROJECT_PLATFORMS_ANDROID');
    if (USER_PROJECT_PLATFORMS_ANDROID_FROM_ENV != null && !USER_PROJECT_PLATFORMS_ANDROID_FROM_ENV.equals("")) {
        project.ext.USER_PROJECT_PLATFORMS_ANDROID = USER_PROJECT_PLATFORMS_ANDROID_FROM_ENV;
    } else {
        project.ext.USER_PROJECT_PLATFORMS_ANDROID = project.ext.USER_PROJECT_ROOT + PLATFORMS_ANDROID
    }


    def getDepPlatformDir = { dep ->
        file("${project.ext.USER_PROJECT_PLATFORMS_ANDROID}/${dep.directory}/$PLATFORMS_ANDROID")
    }
    def computeKotlinVersion = { -> project.hasProperty("kotlinVersion") ? kotlinVersion : "2.0.0" }
    def kotlinVersion = computeKotlinVersion()
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:{{runtimeAndroidPluginVersion}}'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }

    // Set up styled logger
    project.ext.getDepPlatformDir = getDepPlatformDir
    project.ext.outLogger = services.get(StyledTextOutputFactory).create("colouredOutputLogger")

    // the build script will not work with previous versions of the CLI (3.1 or earlier)
    def dependenciesJson = file("${project.ext.USER_PROJECT_PLATFORMS_ANDROID}/dependencies.json")
    def appDependencies = new JsonSlurper().parseText(dependenciesJson.text)
    def pluginData = appDependencies.find { it.name == project.ext.PLUGIN_NAME }
    project.ext.nativescriptDependencies = appDependencies.findAll{pluginData.dependencies.contains(it.name)}
    project.ext.getAppPath = { ->
        def relativePathToApp = "app"
        def nsConfigFile = file("$USER_PROJECT_ROOT/nsconfig.json")
        def nsConfig

        if (nsConfigFile.exists()) {
            nsConfig = new JsonSlurper().parseText(nsConfigFile.getText("UTF-8"))
        }

        if (project.hasProperty("appPath")) {
            // when appPath is passed through -PappPath=/path/to/app
            // the path could be relative or absolute - either case will work
            relativePathToApp = appPath
        } else if (nsConfig != null && nsConfig.appPath != null) {
            relativePathToApp = nsConfig.appPath
        }

        project.ext.appPath = Paths.get(USER_PROJECT_ROOT).resolve(relativePathToApp).toAbsolutePath()

        return project.ext.appPath
    }

    project.ext.getAppResourcesPath = { ->
        def relativePathToAppResources
        def absolutePathToAppResources
        def nsConfigFile = file("$USER_PROJECT_ROOT/nsconfig.json")
        def nsConfig

        if (nsConfigFile.exists()) {
            nsConfig = new JsonSlurper().parseText(nsConfigFile.getText("UTF-8"))
        }

        if (project.hasProperty("appResourcesPath")) {
            // when appResourcesPath is passed through -PappResourcesPath=/path/to/App_Resources
            // the path could be relative or absolute - either case will work
            relativePathToAppResources = appResourcesPath
            absolutePathToAppResources = Paths.get(USER_PROJECT_ROOT).resolve(relativePathToAppResources).toAbsolutePath()
        } else if (nsConfig != null && nsConfig.appResourcesPath != null) {
            relativePathToAppResources = nsConfig.appResourcesPath
            absolutePathToAppResources = Paths.get(USER_PROJECT_ROOT).resolve(relativePathToAppResources).toAbsolutePath()
        } else {
            absolutePathToAppResources = "${getAppPath()}/App_Resources"
        }

        project.ext.appResourcesPath = absolutePathToAppResources

        return absolutePathToAppResources
    }

    def applyBuildScriptConfigurations = { ->
        def absolutePathToAppResources = getAppResourcesPath()
        def pathToBuildScriptGradle = "$absolutePathToAppResources/Android/buildscript.gradle"
        def buildScriptGradle = file(pathToBuildScriptGradle)
        if (buildScriptGradle.exists()) {
            outLogger.withStyle(Style.SuccessHeader).println "\t ~ applying user-defined buildscript from ${buildScriptGradle}"
            apply from: pathToBuildScriptGradle, to: buildscript
        }

        nativescriptDependencies.each { dep ->
            def pathToPluginBuildScriptGradle = "${getDepPlatformDir(dep)}/buildscript.gradle"
            def pluginBuildScriptGradle = file(pathToPluginBuildScriptGradle)
            if (pluginBuildScriptGradle.exists()) {
                outLogger.withStyle(Style.SuccessHeader).println "\t + applying user-defined buildscript from dependency ${pluginBuildScriptGradle}"
                apply from: pathToPluginBuildScriptGradle, to: buildscript
            }
        }

        def pathToPluginBuildScriptGradle = "$rootDir/buildscript.gradle"
        def pluginBuildScriptGradle = file(pathToPluginBuildScriptGradle)
        if (pluginBuildScriptGradle.exists()) {
            outLogger.withStyle(Style.SuccessHeader).println "\t ~ applying user-defined buildscript from dependency ${pluginBuildScriptGradle}"
            apply from: pathToPluginBuildScriptGradle, to: buildscript
        }
    }
    applyBuildScriptConfigurations()

}

def pluginDependencies

allprojects {
    repositories {
        // used for local *.AAR files
        pluginDependencies = nativescriptDependencies.collect {
            getDepPlatformDir(it)
        }

        // some plugins may have their android dependencies in a /libs subdirectory
        pluginDependencies.addAll(nativescriptDependencies.collect {
            "${getDepPlatformDir(it)}/libs"
        })
        mavenLocal()
        mavenCentral()
        maven {
            url 'https://maven.google.com/'
            name 'Google'
        }
        if (pluginDependencies.size() > 0) {
            flatDir {
                dirs pluginDependencies
            }
        }
    }
}


def computeCompileSdkVersion = { -> project.hasProperty("compileSdk") ? compileSdk : 34 }
def computeTargetSdkVersion = { -> project.hasProperty("targetSdk") ? targetSdk : 34 as int }
def computeBuildToolsVersion = { ->
    project.hasProperty("buildToolsVersion") ? buildToolsVersion : "34.0.0"
}

android {
    namespace "{{pluginNamespace}}"

    kotlinOptions {
        jvmTarget = '17'
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }


    if (project.hasProperty("ndkVersion")) {
        ndkVersion project.ndkVersion
    }

    def applyPluginGradleConfigurations = { ->
        nativescriptDependencies.each { dep ->
            def includeGradlePath = "${getDepPlatformDir(dep)}/include.gradle"
            if (file(includeGradlePath).exists()) {
                apply from: includeGradlePath
            }
        }
    }
    applyBeforePluginGradleConfiguration()
    applyPluginGradleConfigurations()

    compileSdkVersion computeCompileSdkVersion()
    buildToolsVersion computeBuildToolsVersion()

    defaultConfig {
        targetSdkVersion computeTargetSdkVersion()
        versionCode 1
        versionName "1.0"
    }
}


def applyBeforePluginGradleConfiguration() {
    def appResourcesPath = getAppResourcesPath()
    def pathToBeforePluginGradle = "$appResourcesPath/Android/before-plugins.gradle"
    def beforePluginGradle = file(pathToBeforePluginGradle)
    if (beforePluginGradle.exists()) {
        outLogger.withStyle(Style.SuccessHeader).println "\t ~ applying user-defined configuration from ${beforePluginGradle}"
        apply from: pathToBeforePluginGradle
    }
}

task addDependenciesFromNativeScriptPlugins {
    nativescriptDependencies.each { dep ->
        def aarFiles = fileTree(dir: getDepPlatformDir(dep), include: ["**/*.aar"])
        aarFiles.each { aarFile ->
            def length = aarFile.name.length() - 4
            def fileName = aarFile.name[0..<length]
            outLogger.withStyle(Style.SuccessHeader).println "\t + adding aar plugin dependency: " + aarFile.getAbsolutePath()
            project.dependencies.add("implementation", [name: fileName, ext: "aar"])
        }

        def jarFiles = fileTree(dir: getDepPlatformDir(dep), include: ["**/*.jar"])
        jarFiles.each { jarFile ->
            def jarFileAbsolutePath = jarFile.getAbsolutePath()
            outLogger.withStyle(Style.SuccessHeader).println "\t + adding jar plugin dependency: $jarFileAbsolutePath"
            pluginsJarLibraries.add(jarFile.getAbsolutePath())
        }

        project.dependencies.add("implementation", jarFiles)
    }
}

tasks.whenTaskAdded({ DefaultTask currentTask ->
    if (currentTask.name == 'bundleRelease' || currentTask.name == 'bundleDebug') {
        def generateBuildConfig =  project.hasProperty("generateBuildConfig") ? project.generateBuildConfig : false
        def generateR =  project.hasProperty("generateR") ? project.generateR : false
        if (!generateBuildConfig) {
            currentTask.exclude '**/BuildConfig.class'
        }
        if (!generateR) {
            currentTask.exclude '**/R.class', '**/R$*.class'
        }
    }
})
