plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.kotlinxSerialization)
    `maven-publish`
    id("org.jetbrains.dokka") version "2.1.0"
    id("com.gradleup.shadow") version "9.2.2"
}

group = "com.dropbear"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

val hostOs = providers.systemProperty("os.name").get()
val isArm64 = providers.systemProperty("os.arch").map { it == "aarch64" }.get()
val isMingwX64 = hostOs.startsWith("Windows")
val isLinux = hostOs == "Linux"
val isMacOs = hostOs == "Mac OS X"

val libName = when {
    isMacOs -> "libeucalyptus_core.dylib"
    isLinux -> "libeucalyptus_core.so"
    isMingwX64 -> "eucalyptus_core.dll"
    else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}

val libPathProvider = provider {
    val candidates = listOf(
        layout.projectDirectory.file("target/debug/$libName").asFile,
        layout.projectDirectory.file("target/release/$libName").asFile,
        layout.projectDirectory.file("libs/$libName").asFile
    )

    val foundFile = candidates.firstOrNull { it.exists() }
    if (foundFile != null) {
        foundFile.absolutePath
    } else {
        println("No Rust library exists")
        ""
    }
}

kotlin {
    jvm { }

    val nativeTarget = when {
        isMacOs && isArm64 -> macosArm64("nativeLib")
        isMacOs && !isArm64 -> macosX64("nativeLib")
        isLinux && isArm64 -> linuxArm64("nativeLib")
        isLinux && !isArm64 -> linuxX64("nativeLib")
        isMingwX64 -> mingwX64("nativeLib")
        else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
    }

    val nativeLibPathRaw = libPathProvider.get()

    if (nativeLibPathRaw.isNotBlank()) {
        val nativeLibPath = file(nativeLibPathRaw)
        val nativeLibDir = nativeLibPath.parentFile.absolutePath
        val nativeLibFileName = nativeLibPath.name
        val nativeLibNameForLinking = when {
            isMacOs -> nativeLibFileName.removePrefix("lib").removeSuffix(".dylib")
            isLinux -> nativeLibFileName.removePrefix("lib").removeSuffix(".so")
            isMingwX64 -> nativeLibFileName.removeSuffix(".dll")
            else -> throw GradleException("Unsupported OS for library name derivation.")
        }

        nativeTarget.apply {
            compilations.getByName("main") {
                cinterops {
                    val dropbear by creating {
                        defFile(project.file("scripting/dropbear.def"))
                        includeDirs.headerFilterOnly(project.file("include"))
                        compilerOpts("-I${project.file("include").absolutePath}")
                    }
                }
            }
            binaries {
                sharedLib {
                    baseName = "dropbear"

                    if (isLinux || isMacOs) {
                        linkerOpts("-L$nativeLibDir", "-l$nativeLibNameForLinking", "-Wl,-rpath,\\\$ORIGIN")
                    } else if (isMingwX64) {
                        val importLibName = "$nativeLibNameForLinking.dll.lib"
                        val importLibPath = file("$nativeLibDir/$importLibName").absolutePath
                        linkerOpts(importLibPath)
                    }
                }
            }
        }
    } else {
        println("Skipping native target configuration due to missing library path.")
        nativeTarget.apply {
            compilations.getByName("main") {
                cinterops {
                    val dropbear by creating {
                        defFile(project.file("scripting/dropbear.def"))
                        includeDirs.headerFilterOnly(project.file("include"))
                    }
                }
            }
        }
    }

    sourceSets {
        commonMain {
            kotlin.srcDirs("scripting/commonMain/kotlin")
            dependencies {
                api("org.jetbrains.kotlinx:kotlinx-datetime:0.7.0")
            }
        }
        nativeMain {
            kotlin.srcDirs("scripting/nativeMain/kotlin")
            dependencies {
                implementation(libs.kotlinxSerializationJson)
            }
        }

        jvmMain {
            kotlin.srcDirs("scripting/jvmMain/kotlin", "scripting/jvmMain/java")
            dependencies {

            }
        }
    }

    java {
        sourceSets.getByName("jvmMain") {
            java.srcDirs("scripting/jvmMain/java")
        }
    }

    targets.all {
        compilations.all {
            compileTaskProvider.configure {
                compilerOptions {
                    freeCompilerArgs.add("-Xexpect-actual-classes")
                }
            }
        }
    }
}

tasks.register<JavaCompile>("generateJniHeaders") {
    val outputDir = layout.buildDirectory.dir("generated/jni-include")
    options.headerOutputDirectory.set(outputDir.get().asFile)

    destinationDirectory.set(layout.buildDirectory.dir("classes/java/jni"))

    classpath = files(
        tasks.named("compileKotlinJvm"),
    )

    source = fileTree("scripting/jvmMain/java") {
        include("**/*.java")
    }

    dependsOn("compileKotlinJvm")

    doFirst {
        val javaFiles = source.files
        if (javaFiles.isEmpty()) {
            println("WARNING: No Java files found in scripting/jvmMain/kotlin for JNI header generation")
        } else {
            println("Generating JNI include for ${javaFiles.size} Java files:")
            javaFiles.forEach { println("  - ${it.name}") }
        }
    }

    doLast {
        val headerDir = outputDir.get().asFile
        val headers = headerDir.listFiles()?.filter { it.extension == "h" } ?: emptyList()
        println("Generated ${headers.size} JNI include:")
        headers.forEach { println("  - ${it.name}") }
    }
}

publishing {
    repositories {
        maven {
            name = "GitHubPages"
            url = uri(layout.buildDirectory.dir("repo"))
        }
    }

    publications.withType<MavenPublication> {
        pom {
            name.set("dropbear")
            description.set("The dropbear scripting part of the engine... uhh yeah!")
            url.set("https://github.com/tirbofish/dropbear")

            licenses {
                license {
                    name.set("dropbear engine License, Version 1.2")
                    url.set("https://raw.githubusercontent.com/tirbofish/dropbear/refs/heads/main/LICENSE.md")
                }
            }

            developers {
                developer {
                    id.set("tirbofish")
                    name.set("tk")
                    email.set("4tkbytes@pm.me")
                }
            }

            scm {
                url.set("https://github.com/tirbofish/dropbear")
                connection.set("scm:git:git://github.com/tirbofish/dropbear.git")
                developerConnection.set("scm:git:ssh://git@github.com/tirbofish/dropbear.git")
            }
        }
    }
}