apply plugin: 'cpp'

import java.nio.file.Paths

def rootPath = rootProject.projectDir.absolutePath

String bulletSrcPath = bulletFolder + '/src'

if (!hasProperty('mainClass')) {
    ext.mainClass = ''
}

dependencies {
    compile project(':jme3-bullet')
}
clean { dependsOn 'cleanHeaders', 'cleanUnzipped' }

// clean up auto-generated C++ headers
task cleanHeaders(type: Delete) {
    delete fileTree(dir: 'src/native/cpp', include: 'com_jme3_bullet_*.h')
}
// clean up unzipped files
task cleanUnzipped(type: Delete) {
    delete bulletFolder
}
// clean up the downloaded archive
task cleanZipFile(type: Delete) {
    delete bulletZipFile
}

model {
    components {
        bulletjme(NativeLibrarySpec) {


            String[] targets=[
                "Windows64",
                "Windows32",
                "Mac64",
                "Linux64",
                "Linux32",
                "LinuxArm",
                "LinuxArmHF",
                "LinuxArm64"    
            ];
          
            String[] filter=gradle.rootProject.ext.usePrebuildNatives==true?null:buildForPlatforms.split(",");
            if(filter==null)println("No filter set. build for all");
            for(String target:targets){
                if(filter==null){
                    targetPlatform(target);
                }else{
                    for(String f:filter){
                        if(f.equals(target)){
                            targetPlatform(target);
                            break;
                        }
                    }
                }
            }

            sources {
                cpp {
                    source {
                        srcDir 'src/native/cpp'
                        srcDir bulletSrcPath
                        exclude 'Bullet3Collision/**'
                        exclude 'Bullet3Dynamics/**'
                        exclude 'Bullet3Geometry/**'
                        exclude 'Bullet3OpenCL/**'
                        exclude 'Bullet3Serialize/**'
                        include '**/*.cpp'
                        exclude '**/*All.cpp'
                    }
                    exportedHeaders {
                        srcDir 'src/native/cpp'
                        srcDir bulletSrcPath
                        exclude 'Bullet3Collision/**'
                        exclude 'Bullet3Dynamics/**'
                        exclude 'Bullet3Geometry/**'
                        exclude 'Bullet3OpenCL/**'
                        exclude 'Bullet3Serialize/**'
                        include '**/*.h'
                    }
                }
            }
        }
    }

     
    toolChains {
        visualCpp(VisualCpp)
        gcc(Gcc)
        clang(Clang)
        gccArm(Gcc) {
            // Fun Fact: Gradle uses gcc as linker frontend, so we don't specify ld directly here
            target("LinuxArm"){
                path "/usr/bin"
                cCompiler.executable = "arm-linux-gnueabi-gcc-8"
                cppCompiler.executable = "arm-linux-gnueabi-g++-8"
                linker.executable = "arm-linux-gnueabi-gcc-8"
                assembler.executable = "arm-linux-gnueabi-as"
            }

            target("LinuxArmHF"){
                path "/usr/bin"
                cCompiler.executable = "arm-linux-gnueabihf-gcc-8"
                cppCompiler.executable = "arm-linux-gnueabihf-g++-8"
                linker.executable = "arm-linux-gnueabihf-gcc-8"
                assembler.executable = "arm-linux-gnueabihf-as"
            }

            target("LinuxArm64"){
                path "/usr/bin"
                cCompiler.executable = "aarch64-linux-gnu-gcc-8"
                cppCompiler.executable = "aarch64-linux-gnu-g++-8"
                linker.executable = "aarch64-linux-gnu-gcc-8"
                assembler.executable = "aarch64-linux-gnu-as"
            }
        }  
    }

    binaries {
        withType(SharedLibraryBinarySpec) {
            def javaHome = org.gradle.internal.jvm.Jvm.current().javaHome
            def os = targetPlatform.operatingSystem.name
            def arch = targetPlatform.architecture.name
            def fileName = sharedLibraryFile.name

            // Gradle decided to change underscores to dashes - fix that.
            arch = arch.replaceAll('-', '_')

            // For all binaries that can't be built on the current system
            if (buildNativeProjects != "true")  buildable = false

            if (buildable) {            
                cppCompiler.define('BT_NO_PROFILE')
                if (toolChain in VisualCpp) {
                    cppCompiler.args "/I$javaHome\\include"
                } else{
                    cppCompiler.args '-I', "$javaHome/include"
                }

                if (os == "osx") {
                    cppCompiler.args '-I', "$javaHome/include/darwin"
                    cppCompiler.args "-O3"
                    cppCompiler.args "-U_FORTIFY_SOURCE"
                } else if (os == "linux") {
                    cppCompiler.args "-fvisibility=hidden"
                    cppCompiler.args '-I', "$javaHome/include/linux"
                    cppCompiler.args "-fPIC"
                    cppCompiler.args "-O3"
                    cppCompiler.args "-U_FORTIFY_SOURCE"
                    cppCompiler.args "-fpermissive"
                    linker.args "-fvisibility=hidden"
                } else if (os == "windows") {
                    if (toolChain in Gcc) {
                        if (toolChain.name.startsWith('mingw'))  cppCompiler.args '-I', "$projectDir/src/native/cpp/fake_win32"
                        else  cppCompiler.args '-I', "$javaHome/include/win32"                        
                        cppCompiler.args "-fpermissive"
                        cppCompiler.args "-static"
                        cppCompiler.args "-O3"
                        cppCompiler.args "-U_FORTIFY_SOURCE"
                        linker.args "-static"
                        linker.args "-Wl,--exclude-all-symbols"
                    } else if (toolChain in VisualCpp) {
                        cppCompiler.args "/I$javaHome\\include\\win32"
                    }
                    cppCompiler.define('WIN32')
                }
                tasks.all { 
                    dependsOn unzipBulletIfNeeded
                    dependsOn ':jme3-bullet:compileJava'
                }

                task "copyBinaryToLibs${targetPlatform.name}"(type: Copy, dependsOn: tasks) {
                    from sharedLibraryFile
                    into "${rootPath}/build/native/bullet/native/${os}/${arch}"
                } 

                // Add depend on copy
                jar.dependsOn("copyBinaryToLibs${targetPlatform.name}")

            }
        }
        withType(StaticLibraryBinarySpec) {
            buildable = false
        }
    }

    platforms {
        Windows32 {
            architecture "x86"
            operatingSystem "windows"
        }
        Windows64 {
            architecture "x86_64"
            operatingSystem "windows"
        }
        Mac64 {
            architecture "x86_64"
            operatingSystem "osx"
        }
        Linux32 {
            architecture "x86"
            operatingSystem "linux"
        }
        Linux64 {
            architecture "x86_64"
            operatingSystem "linux"
        }
        LinuxArm {
            architecture "arm"
            operatingSystem "linux"
        }
        LinuxArmHF {
            architecture "armhf"
            operatingSystem "linux"        
        }
        LinuxArm64 {
            architecture "aarch64"
            operatingSystem "linux"
        }
    }
}

// Java source sets for IDE access and source jar bundling / mavenization
sourceSets {
    main {
        java {
            srcDir 'src/native/cpp'
        }
        resources {
            srcDir file(Paths.get(rootPath, 'build', 'native', 'bullet'))
        }
    }
}

task downloadBullet(type: MyDownload) {
    sourceUrl = bulletUrl
    target = file(bulletZipFile)
}

task unzipBullet(type: Copy) {
    from zipTree(bulletZipFile)
    into file('.')
}

unzipBullet.dependsOn {
    if (!file(bulletZipFile).exists()) {
        downloadBullet
    }
}

task unzipBulletIfNeeded {
}

unzipBulletIfNeeded.dependsOn {
    if (buildNativeProjects == "true") {
        unzipBullet
    }
}

// Helper class to wrap ant download task
class MyDownload extends DefaultTask {
    @Input
    String sourceUrl

    @OutputFile
    File target

    @TaskAction
    void download() {
        ant.get(src: sourceUrl, dest: target)
    }
}