ext {
    nativeName = "photontargeting"
}

apply plugin: 'cpp'
apply plugin: 'google-test-test-suite'
apply plugin: 'edu.wpi.first.NativeUtils'
apply plugin: 'edu.wpi.first.WpilibTools'
apply plugin: 'edu.wpi.first.GradleJni'

ext.licenseFile = file("$rootDir/LICENSE")
apply from: "${rootDir}/shared/config.gradle"
apply from: "${rootDir}/shared/javacommon.gradle"

apply from: "${rootDir}/versioningHelper.gradle"

nativeUtils {
    exportsConfigs {
        "${nativeName}" {}
    }
}

sourceSets.main.java.srcDir "${projectDir}/src/generated/main/java"

// Folder whose contents will be included in the final jar
def outputsFolder = file("$buildDir/extra_resources")

// Sync task: like the copy task, but all files that exist in the destination directory will be deleted before copying files
task syncOutputsFolder(type: Sync) {
    into outputsFolder
}

// And package our outputs folder into the final jar
jar {
    from outputsFolder
    dependsOn syncOutputsFolder
}

model {
    components {
        "${nativeName}"(NativeLibrarySpec) {
            sources {
                cpp {
                    source {
                        srcDirs 'src/main/native/cpp', "$buildDir/generated/source/proto/main/cpp", 'src/generated/main/native/cpp'
                        include '**/*.cpp', '**/*.cc'
                    }
                    exportedHeaders {
                        srcDirs 'src/main/native/include', 'src/generated/main/native/include', "$buildDir/generated/source/proto/main/cpp", 'src/generated/main/native/include'
                        if (project.hasProperty('generatedHeaders')) {
                            srcDir generatedHeaders
                        }
                        include "**/*.h"
                    }
                }
            }

            binaries.all {
                it.tasks.withType(CppCompile) {
                    it.dependsOn generateProto
                }
            }

            nativeUtils.useRequiredLibrary(it, "wpiutil_shared")
            nativeUtils.useRequiredLibrary(it, "wpimath_shared")
            nativeUtils.useRequiredLibrary(it, "wpinet_shared")
            nativeUtils.useRequiredLibrary(it, "ntcore_shared")
        }
        "${nativeName}JNI"(JniNativeLibrarySpec) {

            enableCheckTask project.hasProperty('doJniCheck')
            javaCompileTasks << compileJava
            jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.roborio)
            jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm32)
            jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm64)

            sources {
                cpp {
                    source {
                        srcDirs 'src/main/native/jni'
                        include '**/*.cpp', '**/*.cc'
                    }
                }
            }

            binaries.all {
                lib library: nativeName, linkage: 'shared'
            }

            nativeUtils.useRequiredLibrary(it, "wpiutil_shared")
            nativeUtils.useRequiredLibrary(it, "wpinet_shared")
            nativeUtils.useRequiredLibrary(it, "ntcore_shared")
            nativeUtils.useRequiredLibrary(it, "wpimath_shared")
        }

        all {
            binaries.withType(SharedLibraryBinarySpec) { binary ->
                // check that we're building for the platform (per PArchOverride/wpilib plat detection)
                def platName = jniPlatform
                def realWpilibName = wpilibNativeName;

                if (jniPlatform.equals("osxarm64") || jniPlatform.equals("osxx86-64")) {
                    // native-utils calls this osxuniversal
                    platName = "osxuniversal";
                    realWpilibName = "osxuniversal";
                }

                if (binary.targetPlatform.name == platName) {
                    // only include release binaries (hard coded for now)
                    def isDebug = binary.buildType.name.contains('debug')
                    if (!isDebug) {
                        syncOutputsFolder {
                            // Just shove the shared library into the root of the jar output by photon-targeting:jar
                            from(binary.sharedLibraryFile) {
                                into "nativelibraries/${realWpilibName}/"
                            }
                            // And (not sure if this is a hack) make the jar task depend on the build task
                            dependsOn binary.identifier.projectScopedName
                        }
                    }
                }
            }
        }
    }
    testSuites {
        "${nativeName}Test"(GoogleTestTestSuiteSpec) {
            for(NativeComponentSpec c : $.components) {
                if (c.name == nativeName) {
                    testing c
                    break
                }
            }
            sources {
                cpp {
                    source {
                        srcDirs 'src/test/native/cpp'
                        include '**/*.cpp'
                    }
                    exportedHeaders {
                        srcDirs 'src/test/native/include', "$buildDir/generated/source/proto/main/cpp"
                    }
                }
            }

            binaries.all {
                lib library: nativeName, linkage: 'shared'
                lib library: "${nativeName}JNI", linkage: 'shared'
                it.tasks.withType(CppCompile) {
                    it.dependsOn generateProto
                }
            }

            nativeUtils.useRequiredLibrary(it, "wpilib_executable_shared")
            nativeUtils.useRequiredLibrary(it, "googletest_static")
            nativeUtils.useRequiredLibrary(it, "apriltag_shared")
        }
    }

    tasks {
        def c = $.testSuites
        project.tasks.create('runCpp', Exec) {
            description = "Run the photon-lib executable"
            def found = false
            def systemArch = getCurrentArch()
            c.each {
                if (it in GoogleTestTestSuiteSpec && it.name == "${nativeName}Test") {
                    it.binaries.each {
                        if (!found) {
                            def arch = it.targetPlatform.name
                            if (arch == systemArch) {
                                dependsOn it.tasks.install
                                commandLine it.tasks.install.runScriptFile.get().asFile.toString()
                                def filePath = it.tasks.install.installDirectory.get().toString() + File.separatorChar + 'lib'
                                test.dependsOn it.tasks.install
                                test.systemProperty 'java.library.path', filePath
                                test.environment 'LD_LIBRARY_PATH', filePath
                                test.environment 'DYLD_LIBRARY_PATH', filePath
                                test.workingDir filePath

                                found = true
                            }
                        }
                    }
                }
            }
        }
    }
}

apply from: "${rootDir}/shared/javacpp/publish.gradle"

// quickly hack our raw jar into publishing
def rawjavaJar = tasks.register("rawjavaJar", Jar) {
    dependsOn classes
    includeEmptyDirs = false
    from sourceSets.main.output
    archiveClassifier = 'raw'
}

publishing {
    publications {
        rawjava(MavenPublication) {
            artifact (rawjavaJar) {
                classifier = null
            }
            artifactId = "${nativeName}-rawjava"
            groupId artifactGroupId
            version pubVersion
        }
    }
}

// Add photon serde headers to our published sources
cppHeadersZip {
    from('src/generated/main/native/include') {
        into '/'
    }
}

// make sure native libraries can be loaded in tests
test {
    classpath += files(outputsFolder)
    dependsOn syncOutputsFolder
}

// setup wpilib bundled native libs
wpilibTools.deps.wpilibVersion = wpi.versions.wpilibVersion.get()

def nativeConfigName = 'wpilibNatives'
def nativeConfig = configurations.create(nativeConfigName)

def nativeTasks = wpilibTools.createExtractionTasks {
    configurationName = nativeConfigName
}

nativeTasks.addToSourceSetResources(sourceSets.test)

nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpiutil")
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpimath")
nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpinet")
nativeConfig.dependencies.add wpilibTools.deps.wpilib("ntcore")
nativeConfig.dependencies.add wpilibTools.deps.wpilib("hal")
nativeConfig.dependencies.add wpilibTools.deps.wpilib("cscore")
nativeConfig.dependencies.add wpilibTools.deps.wpilibOpenCv("frc" + openCVYear, wpi.versions.opencvVersion.get())
nativeConfig.dependencies.add wpilibTools.deps.wpilib("apriltag")
