import java.text.SimpleDateFormat

buildscript {
    repositories {
        mavenCentral()
        maven {
            url 'https://jitpack.io'
            content {
                includeGroup "com.github.RyanTheAllmighty.gettext"
                includeGroup "com.github.ATLauncher.gradle-macappbundle"
            }
        }
    }
    dependencies {
        classpath 'com.github.RyanTheAllmighty.gettext:gettext-gradle-plugin:aab5c30bf8'
        classpath 'com.github.ATLauncher.gradle-macappbundle:edu.sc.seis.macAppBundle.gradle.plugin:d22f8cdb94'
    }
}

plugins {
    id 'java'
    id 'application'

    id 'org.cadixdev.licenser' version '0.6.1'
    id 'com.adarshr.test-logger' version '4.0.0'
    id 'edu.sc.seis.macAppBundle' version '2.3.0'
    id 'edu.sc.seis.launch4j' version '3.0.6'
    id 'de.undercouch.download' version '5.6.0'
    id 'com.github.johnrengelman.shadow' version '8.1.1'
    id 'com.github.ben-manes.versions' version '0.52.0'
    id 'com.apollographql.apollo' version '2.5.14' // Cannot update past 2.x.x as Kotlin is required
    id 'net.ltgt.errorprone' version '4.1.0'
}

apply plugin: 'org.mini2Dx.gettext'
apply plugin: 'net.ltgt.errorprone'

sourceCompatibility = '1.8'
targetCompatibility = '1.8'

group = 'com.atlauncher'
version = rootProject.file('src/main/resources/version').text.trim().replace('.Beta', '')

repositories {
    mavenCentral()
    gradlePluginPortal()
    maven {
        url 'https://libraries.minecraft.net'
    }
    maven {
        url 'https://jitpack.io'
        content {
            includeGroup "com.github.RyanTheAllmighty.gettext"
            includeGroup "com.github.Vatuu"
            includeGroup "com.gitlab.doomsdayrs"
            includeGroup "com.github.MCRcortex"
        }
    }
}

dependencies {
    implementation 'net.java.dev.jna:jna:5.16.0'
    implementation 'net.java.dev.jna:jna-platform:5.16.0'
    implementation 'com.google.code.gson:gson:2.11.0'
    implementation 'com.google.guava:guava:33.4.0-jre'
    implementation 'org.tukaani:xz:1.10'
    implementation 'net.iharder:base64:2.3.9'
    implementation 'net.sf.jopt-simple:jopt-simple:5.0.4'
    implementation 'org.zeroturnaround:zt-zip:1.17'
    implementation 'io.sentry:sentry:8.0.0'
    implementation 'com.github.RyanTheAllmighty.gettext:gettext-lib:88ae68d897'
    implementation 'com.sangupta:murmur:1.0.0'
    implementation 'com.github.oshi:oshi-core:6.6.6'
    implementation 'net.freeutils:jlhttp:3.2'
    implementation 'joda-time:joda-time:2.13.0'
    implementation 'org.commonmark:commonmark:0.21.0' // Cannot update past 0.21.0 as needs >=Java 11
    implementation 'com.github.hypfvieh:dbus-java:3.3.2'
    implementation 'com.github.MCRcortex:nekodetector:Version-1.1-pre'
    implementation 'com.twelvemonkeys.imageio:imageio-webp:3.12.0'

    // Commons
    implementation 'org.apache.commons:commons-compress:1.27.1'

    // OkHttp
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
    implementation 'com.squareup.okhttp3:okhttp-tls:4.12.0'

    // FlatLaf UI (https://www.formdev.com/flatlaf/)
    implementation 'com.formdev:flatlaf:3.5.4'
    implementation 'com.formdev:flatlaf-extras:3.5.4'

    // Log4J
    implementation 'org.apache.logging.log4j:log4j-api:2.24.3'
    implementation 'org.apache.logging.log4j:log4j-core:2.24.3'

    // Apollo GraphQL (Cannot update past 2.x.x as Kotlin is required)
    implementation 'com.apollographql.apollo:apollo-runtime:2.5.14'
    implementation 'com.apollographql.apollo:apollo-http-cache:2.5.14'
    implementation 'com.apollographql.apollo:apollo-rx3-support:2.5.14'

    // RxJava
    implementation("io.reactivex.rxjava3:rxjava:3.1.10")
    implementation("com.gitlab.doomsdayrs:rxswing:a5749ad421") // TODO tag

    testImplementation 'org.mockito:mockito-core:4.11.0' // Cannot update to 5.x.x as Java 11 min
    testImplementation 'org.mockito:mockito-inline:4.11.0' // Cannot update to 5.x.x as Java 11 min
    testImplementation 'org.assertj:assertj-swing-junit:3.17.1'
    testImplementation 'org.mock-server:mockserver-netty:5.15.0'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.4'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.4'
    testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.11.4'
}

application {
    mainClass = 'com.atlauncher.App'
    applicationDefaultJvmArgs = [
        "-Djna.nosys=true",
        "-Djava.net.preferIPv4Stack=true",
        "-Dawt.useSystemAAFontSettings=on",
        "-Dswing.aatext=true"
    ]
}

test {
    if (JavaVersion.current().isJava9Compatible()) {
        jvmArgs '--add-opens=java.base/sun.security.x509=ALL-UNNAMED'
    }

    useJUnitPlatform {
        excludeTags 'ui'
    }

    testlogger {
        theme 'mocha'
    }
}

tasks.withType(JavaCompile).configureEach {
    // compile with JDK 17
    javaCompiler = javaToolchains.compilerFor {
        languageVersion = JavaLanguageVersion.of(17)
    }

    dependencies {
        errorprone "com.google.errorprone:error_prone_core:2.36.0"
    }

    options.errorprone {
        enabled = true
        allErrorsAsWarnings = true
        disableWarningsInGeneratedCode = true
        excludedPaths = ".*/build/generated/.*|.*/src/test/.*|.*/src/main/java/io/github/asyncronous/.*"

        disable(
            "CheckReturnValue", // Too many of these and unimportant
            "UnnecessaryParentheses", // Usually there for readability
            "JavaUtilDate", // Lots of these, of low concern vs cost to fix
            "MissingSummary", // Not worth fixing, any comments there are fine
            "CatchAndPrintStackTrace", // Don't care about these
            "StringSplitter",
            "TypeParameterUnusedInFormals",
            "MixedMutabilityReturnType",
            "Finally",
            "FutureReturnValueIgnored",
            "NarrowCalculation",
        )
    }
}

tasks.register('uiTest', Test) {
    useJUnitPlatform {
        includeTags 'ui'
    }
}

jar {
    manifest {
        attributes(
            'SplashScreen-Image': '/assets/image/splash-screen.png',
            'Implementation-Title': project.name,
            'Implementation-Version': archiveVersion,
            'Implementation-Vender': 'ATLauncher',
            'Main-Class': 'com.atlauncher.App',
            'Multi-Release': 'true'
        )
    }
}

apollo {
    customTypeMapping = [
        "ID"      : "java.lang.String",
        "DateTime": "java.util.Date"
    ]
    packageName = "com.atlauncher.graphql"
}

gettext {
    translations {
        srcDir = 'src'
        include = 'main/java/com/atlauncher/**/*.java'
        excludes = [
            'main/java/com/atlauncher/adapter/**/*.java',
            'main/java/com/atlauncher/annot/**/*.java',
            'main/java/com/atlauncher/collection/**/*.java',
            'main/java/com/atlauncher/evnt/**/*.java',
            'main/java/com/atlauncher/exceptions/**/*.java',
            'main/java/com/atlauncher/interfaces/**/*.java',
            'main/java/com/atlauncher/listener/**/*.java',
            'main/java/com/atlauncher/utils/**/*.java'
        ]
        commentFormat = ' #. '
        outputFilename = 'translations.pot'
    }
}

license {
    header = project.file('LICENSEHEADER')
    include '**/*.java'
    exclude 'io/github/**/*.java'
    exclude 'net/minecraft/**/*.java'
    exclude 'com/atlauncher/graphql/**/*.java'
    exclude 'com/atlauncher/gui/layouts/WrapLayout.java'
    exclude 'com/atlauncher/gui/WheelScrollLayerUI.java'
    newLine = false
    skipExistingHeaders = true
    properties {
        year = currentYear()
    }
}

shadowJar {
    archiveClassifier.set(null)
    minimize {
        exclude(dependency('org.apache.logging.log4j:.*:.*'))
        exclude(dependency('net.java.dev.jna:.*:.*'))
        exclude(dependency('com.formdev:.*:.*'))
        exclude(dependency('com.github.jnr:.*:.*'))
        exclude(dependency('com.github.hypfvieh:.*:.*'))
        exclude(dependency('org.apache.commons:commons-compress:.*'))
        exclude(dependency('com.twelvemonkeys.imageio:imageio-webp:.*'))
    }

    // these are included by dbus-java which is only used on Linux
    exclude("jni/x86_64-Windows/")
    exclude("jni/x86_64-SunOS/")
    exclude("jni/x86_64-OpenBSD/")
    exclude("jni/x86_64-FreeBSD/")
    exclude("jni/x86_64-DragonFlyBSD/")
    exclude("jni/sparcv9-SunOS/")
    exclude("jni/ppc-AIX/")
    exclude("jni/ppc64-AIX/")
    exclude("jni/i386-Windows/")
    exclude("jni/i386-SunOS/")
    exclude("jni/Darwin/")

    archiveClassifier.set('')
}

macAppBundle {
    mainClassName = 'com.atlauncher.App'
    appName = 'ATLauncher'
    appStyle = 'universalJavaApplicationStub'
    runtimeConfigurationName = 'shadow'
    jarTask = 'shadowJar'
    icon = 'src/main/resources/assets/image/icon.icns'
    javaProperties.put('user.dir', '$APP_ROOT/Contents/Java')
    javaProperties.put('apple.laf.useScreenMenuBar', 'true')
    javaExtras.put("-Djna.nosys", "true")
    javaExtras.put("-Djava.net.preferIPv4Stack", "true")
    javaExtras.put("-Dawt.useSystemAAFontSettings", "on")
    javaExtras.put("-Dswing.aatext", "true")
    bundleExtras.put("JVMVersion", project.targetCompatibility.toString() + "+")
}

copyToResourcesJava {
    rename("ATLauncher-${project.version}.jar", "ATLauncher.jar")
}

def currentYear() {
    def df = new SimpleDateFormat("yyyy")
    df.setTimeZone(TimeZone.getTimeZone("UTC"))
    return df.format(new Date())
}

launch4j {
    outfile = "ATLauncher-${project.version}.exe"
    jreMinVersion = "${project.targetCompatibility.toString()}"
    mainClassName = 'com.atlauncher.App'
    icon = "${projectDir}/src/main/resources/assets/image/icon.ico"
    version = "${project.version}"
    textVersion = "${project.version}"
    copyright = "2013-${currentYear()} ${project.name}"
    companyName = "${project.name}"
    bundledJrePath = "jre/;%JAVA_HOME%;%PATH%"
    jvmOptions = [
        "-Djna.nosys=true",
        "-Djava.net.preferIPv4Stack=true",
        "-Dawt.useSystemAAFontSettings=on",
        "-Dswing.aatext=true"
    ]
}

artifacts {
    archives shadowJar
    archives file(project.tasks.jar.getArchivePath().getPath().replace('.jar', '.exe').replace('libs', 'launch4j'))
    archives file(project.tasks.jar.getArchivePath().getPath().replace('.jar', '.zip').replace('libs', 'distributions'))
}

task copyArtifacts(type: Copy) {
    dependsOn build
    from shadowJar
    from file(project.tasks.jar.getArchivePath().getPath().replace('.jar', '.exe').replace('libs', 'launch4j'))
    from file(project.tasks.jar.getArchivePath().getPath().replace('.jar', '.zip').replace('libs', 'distributions'))
    into "${projectDir}/dist"
}

task downloadNewerUniversalJavaApplicationStub(type: Download) {
    description 'Downloads newer universalJavaApplicationStub'
    src 'https://raw.githubusercontent.com/tofi86/universalJavaApplicationStub/404f5c1b008d6296065de7a93406b387c9f3dce1/src/universalJavaApplicationStub'
    dest file("$buildDir/macApp/${project.name}.app/Contents/MacOS/universalJavaApplicationStub")
    overwrite true
}

task createTestLauncherDir {
    project.file('testLauncher/dev').mkdirs()
}

task createMacApp(type: Zip) {
    dependsOn createApp, shadowJar, downloadNewerUniversalJavaApplicationStub
    from("$buildDir/macApp") {
        include "${project.name}.app/**"
        exclude "${project.name}.app/Contents/MacOS"
    }
    from("$buildDir/macApp") {
        include "${project.name}.app/Contents/MacOS/**"
        fileMode 0777
    }
    archiveFileName = "${project.name}-${project.version}.zip"
}

task generateThirdPartyLibraries {
    doLast {
        def output = new StringBuilder()
        output.append("<h2>Build Dependencies</h2>\n")
        // Build dependencies
        buildscript.configurations.classpath.dependencies.each { dep ->
            output.append("${dep.group}:${dep.name.replace(".gradle.plugin", "")} version ${dep.version}\n")
        }

        output.append("<h2>Application Dependencies</h2>\n")
        // Application dependencies
        configurations.implementation.dependencies.each { dep ->
            if (dep.group && dep.version) {
                output.append("${dep.group}:${dep.name} version ${dep.version}\n")
            }
        }

        def resourcesDir = new File(projectDir, "src/main/resources")
        new File(resourcesDir, "THIRDPARTYLIBRARIES").text = output.toString()
    }
}

copyArtifacts.finalizedBy {
    println 'ATLauncher has been built. Distribution files are located in the dist directory.'
}

clean.doFirst {
    delete "${projectDir}/dist"
}

project.afterEvaluate {
    tasks.check {
        dependsOn -= tasks.find {
            it.name.equals("checkLicenses")
        }
    }
}

def shouldIgnoreUpdate = { String version -> return ['ALPHA', 'BETA', 'RC', '-M'].any { it -> version.toUpperCase(Locale.ENGLISH).contains(it) } }
tasks.named("dependencyUpdates").configure {
    rejectVersionIf {
        shouldIgnoreUpdate(it.candidate.version)
    }
}

build.finalizedBy copyArtifacts
shadowJar.dependsOn jar
build.dependsOn createExe, createMacApp
startScripts.dependsOn shadowJar
createExe.dependsOn shadowJar
createAppZip.dependsOn downloadNewerUniversalJavaApplicationStub
createDmg.dependsOn downloadNewerUniversalJavaApplicationStub
