import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import java.util.*

buildscript {
    repositories {
        google()
        gradlePluginPortal()
    }
}

plugins {
    kotlin("jvm") version "2.0.20"
    id("org.jetbrains.kotlin.plugin.compose") version "2.0.20"
    id("org.jetbrains.compose") version "1.7.3"
    kotlin("plugin.serialization") version "2.0.20"
    id("com.github.gmazzo.buildconfig") version "5.5.0"
}

repositories {
    google()
    mavenCentral()
    maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
    maven("https://plugins.gradle.org/m2/")
}

dependencies {
    implementation(compose.desktop.currentOs)
    implementation(compose.components.resources)
    implementation(compose.materialIconsExtended)
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")

    // SQLite is needed to access the Pyfa databse.
    // Instead of the single jar with the .so files for all the supported platforms, we use a custom
    // jar with just the single .so file for the current platform.
    //    implementation("org.xerial:sqlite-jdbc:3.49.1.0")
    implementation(
        fileTree("libs") {
            include(sqliteJdbcJarName())
        }
    )
    implementation("org.slf4j:slf4j-api:2.0.17")  // Used by org.xerial:sqlite-jdbc
    implementation("org.slf4j:slf4j-nop:2.0.17")  // Prevents a warning being printed by slf4j-api

//    implementation("com.caoccao.javet:javet:4.1.1")  // Core
//    implementation("com.caoccao.javet:${javetNativeDependencyName()}:4.1.1")

    implementation(":EveData")
    implementation(":Esi")
    implementation(":FittingEngine")
    implementation(":ComposeWidgets")

    testImplementation(compose.desktop.uiTestJUnit4)
    testImplementation(kotlin("test", version = "2.0.20"))
}

// To avoid bloating the distribution with all the native JDBC implementations, I removed all but the necessary,
// per platform .so files from the jar in misc/sqlite-jdbc-3.49.1.0-original.jar, and put them in separate jars in
// libs/. This function returns the name of the jar for the running platform.
// The original jar was downloaded from https://github.com/xerial/sqlite-jdbc
fun sqliteJdbcJarName(): String {
    val os = org.gradle.internal.os.OperatingSystem.current()
    val osType = when {
        os.isWindows -> "windows"
        os.isMacOsX -> "macosx"
        os.isLinux -> "linux"
        else -> throw UnsupportedOperationException("$os is not currently supported by the custom sqlite-jdbc")
    }
    val arch = System.getProperty("os.arch")
    val archType = if (arch == "aarch64" || arch == "arm64") "aarch64" else "x64"
    return "sqlite-jdbc-3.49.1.0-$osType-$archType.jar"
}

//fun javetNativeDependencyName(): String {
//    val os = org.gradle.internal.os.OperatingSystem.current()
//    val osType = when {
//        os.isWindows -> "windows"
//        os.isMacOsX -> "macos"
//        os.isLinux -> "linux"
//        else -> throw UnsupportedOperationException("$os is not supported by Javet")
//    }
//    val arch = System.getProperty("os.arch")
//    val archType = if (arch == "aarch64" || arch == "arm64") "arm64" else "x86_64"
//    return "javet-v8-$osType-$archType"
//}

kotlin {
    jvmToolchain(17)

    compilerOptions.freeCompilerArgs.apply {
        add("-Xlambdas=indy")
        add("-Xcontext-receivers")
    }
}

// Prevents the Java icon from being shown in the macOS dock when running tests
tasks.withType<Test>().configureEach {
    systemProperty("apple.awt.UIElement", "true")
}

// Load local.properties
val localProperties = Properties().apply {
    val localPropertiesFile = rootProject.file("local.properties")
    if (localPropertiesFile.exists())
        load(localPropertiesFile.inputStream())
}

val appName = "Theorycrafter"
val version = "1.8.0-atxxi"  // Don't forget to update versionCode, packageVersion and releases.json
val versionCode = 16
val releaseType = "stable"  // stable, beta, dev
val releasesInfoUrl = "https://theorycrafter.pro/releases.json"
//val releasesInfoUrl = "http://localhost:8000/releases.json"

buildConfig {
    packageName("theorycrafter")
    className("Theorycrafter")

    // App stuff
    buildConfigField("AppName", appName)
    buildConfigField("Version", version)
    buildConfigField("VersionCode", versionCode)
    buildConfigField("theorycrafter.ReleaseType", "AppReleaseType", "ReleaseType.byId(\"$releaseType\")")
    buildConfigField("BuildTimestamp", System.currentTimeMillis())
    buildConfigField("ReleasesInfoUrl", releasesInfoUrl)
    buildConfigField("MaintainerEmail", "evetheorycrafter@gmail.com")

    // EVE SSO
    buildConfigField("EveSsoClientId", localProperties.getProperty("eve.sso.client_id", ""))
    buildConfigField("EveSsoCallbackUrl", localProperties.getProperty("eve.sso.callback_url", ""))

    // Google Analytics
    buildConfigField("GaMeasurementId", localProperties.getProperty("ga.measurement_id", ""))
    buildConfigField("GaApiSecret", localProperties.getProperty("ga.api_secret", ""))
}

compose.desktop {
    application {
        mainClass = "theorycrafter.MainKt"
        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb, TargetFormat.Rpm/*, TargetFormat.AppImage*/)
            packageName = appName
            packageVersion = "1.8.0"

            modules("java.sql")

            macOS {
                iconFile.set(project.file("misc/icon/mac/theorycrafter.icns"))
                jvmArgs += "-Dapple.awt.application.appearance=system"
            }
            windows {
                menuGroup = "" // This adds a launcher to the start menu directly (without a group)
                iconFile.set(project.file("misc/icon/win/theorycrafter.ico"))
            }
            linux {
                iconFile.set(project.file("misc/icon/linux/theorycrafter.png"))
            }
        }

        buildTypes.release.proguard {
            configurationFiles.from(
                project.file("proguard_rules/okhttp3.pro"),
                project.file("proguard_rules/theorycrafter.pro"),
            )
        }
    }
}

tasks.register("packageSource") {
    description = "Packages the source code into a zip file"
    group = "other"

    val outputFile = layout.projectDirectory.file("${appName}-${version}-src.zip")
    outputs.file(outputFile)

    doLast {
        val file = outputFile.asFile

        // Ensure output directory exists
        file.parentFile.mkdirs()

        // Use git archive to create zip of tracked files
        exec {
            commandLine(
                "git", "archive",
                "--format=zip",
                "--output=${file.absolutePath}",
                "HEAD",
                ".", // Include everything
                // Exclude these
                ":(exclude)website",
                ":(exclude).git",
                ":(exclude)*.gitignore",
                ":(exclude)*.gitattributes",
                ":(exclude).github",
                ":(exclude).idea",
                ":(exclude)*.DS_Store",
            )
        }
    }
}