// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    apply from: 'config.gradle'

    repositories {
        google()
        mavenCentral()
        maven { url "https://plugins.gradle.org/m2/" }
        maven { url "https://central.sonatype.com/repository/maven-snapshots/"}
    }
    dependencies {
        classpath "com.android.tools.build:gradle:$versions.gradlePluginVersion"
        classpath "io.github.gradle-nexus:publish-plugin:$versions.nexusPublishVersion"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlinVersion"
    }
}

plugins {
    id 'io.github.gradle-nexus.publish-plugin'
}

apply from: 'config.gradle'
apply from: 'scripts/publish-root.gradle'

group = ossrhGroupId
version = getReleaseVersion()

task clean(type: Delete) {
    delete rootProject.buildDir

    dependsOn 'cleanAddon'
    dependsOn 'cleanBuildFromSamples'
    dependsOn 'cleanZippedSamples'
    dependsOn 'cleanScons'

    dependsOn ':plugin:clean'
}

/**
 * Clean the artifacts for the 'godotopenxrvendors' addon
 */
task cleanAddon(type: Delete) {
    // Delete the bin directory for the addon
    delete("demo/addons/godotopenxrvendors/.bin")
}

/**
 * Build the 'godotopenxrvendors' plugin
 */
task buildPlugin {
    // Generate the editor gdextension binaries
    dependsOn ':buildSconsArtifacts'
    dependsOn ":plugin:build"
    finalizedBy "copyBuildToSamples"
}

/*
 * Find scons executable path
 */
def getSconsExecutableFile() {
    File sconsExecutableFile = null
    def sconsName = "scons"
    def sconsExts = (org.gradle.internal.os.OperatingSystem.current().isWindows()
            ? [".bat", ".cmd", ".ps1", ".exe"]
            : [""])
    logger.debug("Looking for $sconsName executable path")
    for (ext in sconsExts) {
        String sconsNameExt = sconsName + ext
        logger.debug("Checking $sconsNameExt")
        sconsExecutableFile = org.gradle.internal.os.OperatingSystem.current().findInPath(sconsNameExt)
        if (sconsExecutableFile != null) {
            // We're done!
            break
        }
        // Check all the options in path
        List<File> allOptions = org.gradle.internal.os.OperatingSystem.current().findAllInPath(sconsNameExt)
        if (!allOptions.isEmpty()) {
            // Pick the first option and we're done!
            sconsExecutableFile = allOptions.get(0)
            break
        }
    }

    return sconsExecutableFile
}

def createSconsTasks(File sconsExecutableFile, boolean clean) {
    def defaultArgs = [
        "--directory=.",
        "custom_api_file=thirdparty/godot_cpp_gdextension_api/extension_api.json",
        "build_profile=thirdparty/godot_cpp_build_profile/build_profile.json",
    ]

    def sconsExtraArgs = []
    if (project.hasProperty("scons_extra_args")) {
        sconsExtraArgs = project.property("scons_extra_args").trim().split(/\s+/) as List
    }

    String meta_headers = project.hasProperty("meta_headers") ? project.property("meta_headers") : ""
    if (meta_headers != null && !meta_headers.isEmpty()) {
        defaultArgs << "meta_headers=${meta_headers}"
    }

    if (clean) {
        defaultArgs << "-c"
    }

    def taskPrefix = (clean ? "clean" : "build")

    // Android.
    tasks.create(name: "${taskPrefix}GodotOpenXRVendorsAndroidArm64Debug", type: Exec) {
        executable sconsExecutableFile.absolutePath
        args defaultArgs + ["platform=android", "target=template_debug", "arch=arm64"] + sconsExtraArgs
    }
    tasks.create(name: "${taskPrefix}GodotOpenXRVendorsAndroidArm64Release", type: Exec) {
        executable sconsExecutableFile.absolutePath
        args defaultArgs + ["platform=android", "target=template_release", "arch=arm64"] + sconsExtraArgs
    }
    tasks.create(name: "${taskPrefix}GodotOpenXRVendorsAndroidX86_64Debug", type: Exec) {
        executable sconsExecutableFile.absolutePath
        args defaultArgs + ["platform=android", "target=template_debug", "arch=x86_64"] + sconsExtraArgs
    }
    tasks.create(name: "${taskPrefix}GodotOpenXRVendorsAndroidX86_64Release", type: Exec) {
        executable sconsExecutableFile.absolutePath
        args defaultArgs + ["platform=android", "target=template_release", "arch=x86_64"] + sconsExtraArgs
    }

    // Desktop.
    tasks.create(name: "${taskPrefix}GodotOpenXRVendorsDesktopDebug", type: Exec) {
        executable sconsExecutableFile.absolutePath
        args defaultArgs + ["target=template_debug"] + sconsExtraArgs
    }
    tasks.create(name: "${taskPrefix}GodotOpenXRVendorsDesktopRelease", type: Exec) {
        executable sconsExecutableFile.absolutePath
        args defaultArgs + ["target=template_release"] + sconsExtraArgs
    }
}

/**
 * Build the scons artifacts for the project
 */
task buildSconsArtifacts {
    File sconsExecutableFile = getSconsExecutableFile()

    // Using `doFirst` so the exception doesn't happen until this task actually runs.
    doFirst {
        if (sconsExecutableFile == null) {
            throw new GradleException("Unable to find executable path for the 'scons' command.")
        } else {
            logger.debug("Found executable path for scons: ${sconsExecutableFile.absolutePath}")
        }
    }

    if (sconsExecutableFile != null) {
        createSconsTasks(sconsExecutableFile, false)

        // Android.
        dependsOn 'buildGodotOpenXRVendorsAndroidArm64Debug'
        dependsOn 'buildGodotOpenXRVendorsAndroidArm64Release'
        dependsOn 'buildGodotOpenXRVendorsAndroidX86_64Debug'
        dependsOn 'buildGodotOpenXRVendorsAndroidX86_64Release'

        // Desktop.
        dependsOn 'buildGodotOpenXRVendorsDesktopDebug'
        dependsOn 'buildGodotOpenXRVendorsDesktopRelease'
    }
}

/**
 * Scons clean for the project
 */
task cleanScons {
    File sconsExecutableFile = getSconsExecutableFile()

    // Using `doFirst` so the exception doesn't happen until this task actually runs.
    doFirst {
        if (sconsExecutableFile == null) {
            throw new GradleException("Unable to find executable path for the 'scons' command.")
        } else {
            logger.debug("Found executable path for scons: ${sconsExecutableFile.absolutePath}")
        }
    }

    if (sconsExecutableFile != null) {
        createSconsTasks(sconsExecutableFile, true)

        // Android.
        dependsOn 'cleanGodotOpenXRVendorsAndroidArm64Debug'
        dependsOn 'cleanGodotOpenXRVendorsAndroidArm64Release'
        dependsOn 'cleanGodotOpenXRVendorsAndroidX86_64Debug'
        dependsOn 'cleanGodotOpenXRVendorsAndroidX86_64Release'

        // Desktop.
        dependsOn 'cleanGodotOpenXRVendorsDesktopDebug'
        dependsOn 'cleanGodotOpenXRVendorsDesktopRelease'
    }
}

task copyBuildToSamples {
    def sourceDir = file 'demo/addons/godotopenxrvendors'
    def samplesDir = file 'samples'
    doLast{
        samplesDir.eachDir { targetSubdir ->
            if (targetSubdir.name != 'builds') {
                copy {
                    from sourceDir
                    into "${targetSubdir}/addons/godotopenxrvendors"
                }
            }
        }
    }
}

task cleanBuildFromSamples {
    def samplesDir = file 'samples'
    doLast{
        samplesDir.eachDir { targetSubdir ->
            if (targetSubdir.name != 'builds') {
                delete {
                    delete "${targetSubdir}/addons/godotopenxrvendors"
                }
            }
        }
    }
}

task zipSamples {
    def samplesDir = file 'samples'
    def directoriesToZip = samplesDir.listFiles().findAll { it.isDirectory() && it.name != 'builds' }

    def destinationDir = file 'zippedSamples'
    destinationDir.mkdirs()

    directoriesToZip.each { dir ->
        def zipTask = tasks.create(name: "zip${dir.name.capitalize()}", type: Zip) {
            from(dir.parentFile) {
                include "${dir.name}/**"
            }
            archiveFileName = "${dir.name}.zip"
            destinationDirectory = destinationDir
        }

        zipTask.doFirst {
            def godotFolder = new File(dir, '.godot')
            if (godotFolder.exists()) {
                godotFolder.deleteDir()
            }

            def androidFolder = new File(dir, 'android')
            if (androidFolder.exists()) {
                androidFolder.deleteDir()
            }
        }

        dependsOn zipTask
    }
}

task cleanZippedSamples {
    delete 'zippedSamples'
}
