// For those who want the bleeding edge
buildscript {
    repositories {
        jcenter()
        maven {
            name = "forge"
            url = "https://files.minecraftforge.net/maven"
        }
    }
    dependencies {
        classpath 'com.google.code.gson:gson:2.8.1'
        classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
        classpath 'net.sf.proguard:proguard-gradle:6.1.0beta1'
        classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
    }
}

plugins {
    id "checkstyle"
    id "jacoco"
    id "com.github.hierynomus.license" version "0.15.0"
    id "com.matthewprenger.cursegradle" version "1.3.0"
    id "com.github.breadmoirai.github-release" version "2.2.4"
}

apply plugin: 'net.minecraftforge.gradle.forge'
apply plugin: 'org.ajoberstar.grgit'
apply plugin: 'maven-publish'
apply plugin: 'maven'

version = mod_version

group = "org.squiddev"
archivesBaseName = "cc-tweaked-${mc_version}"

minecraft {
    version = "${mc_version}-${forge_version}"
    runDir = "run"
    replace '${version}', mod_version

    mappings = mappings_version
    makeObfSourceJar = false
}

repositories {
    maven {
        name "SquidDev"
        url "https://squiddev.cc/maven"
    }
    ivy {
        name "Charset"
        artifactPattern "https://asie.pl/files/mods/Charset/LibOnly/[module]-[revision](-[classifier]).[ext]"
    }
    maven {
        name "Amadornes"
        url "https://maven.amadornes.com/"
    }
    maven {
        name "CraftTweaker"
        url "https://maven.blamejared.com/"
    }
}

configurations {
    shade
    compile.extendsFrom shade
    deployerJars
}

dependencies {
    checkstyle "com.puppycrawl.tools:checkstyle:8.25"

    deobfProvided "CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.554"
    deobfProvided "MCMultiPart2:MCMultiPart:2.5.3"
    deobfProvided "mezz.jei:jei_1.12.2:4.15.0.269:api"
    deobfProvided "pl.asie:Charset-Lib:0.5.4.6"

    runtime "mezz.jei:jei_1.12.2:4.15.0.269"

    shade 'org.squiddev:Cobalt:0.5.1-SNAPSHOT'

    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'

    deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0"
}

// Compile tasks

javadoc {
    include "dan200/computercraft/api/**/*.java"
}

jar {
    dependsOn javadoc

    manifest {
        attributes('FMLAT': 'computercraft_at.cfg')
    }

    from (sourceSets.main.allSource) {
        include "dan200/computercraft/api/**/*.java"
    }

    from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
}

[compileJava, compileTestJava].forEach {
    it.configure {
        options.compilerArgs << "-Xlint" << "-Xlint:-processing" << "-Werror"
    }
}



import java.nio.charset.StandardCharsets
import java.nio.file.*
import java.util.zip.*

import com.google.gson.GsonBuilder
import com.google.gson.JsonElement
import com.hierynomus.gradle.license.tasks.LicenseCheck
import com.hierynomus.gradle.license.tasks.LicenseFormat
import org.ajoberstar.grgit.Grgit
import proguard.gradle.ProGuardTask

task proguard(type: ProGuardTask, dependsOn: jar) {
    description "Removes unused shadowed classes from the jar"
    group "compact"

    injars jar.archivePath
    outjars "${jar.archivePath.absolutePath.replace(".jar", "")}-min.jar"

    // Add the main runtime jar and all non-shadowed dependencies
    libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
    libraryjars "${System.getProperty('java.home')}/lib/jce.jar"
    doFirst {
        sourceSets.main.compileClasspath
            .filter { !it.name.contains("Cobalt") }
            .each { libraryjars it }
    }

    // We want to avoid as much obfuscation as possible. We're only doing this to shrink code size.
    dontobfuscate; dontoptimize; keepattributes; keepparameternames

    // Proguard will remove directories by default, but that breaks JarMount.
    keepdirectories 'assets/computercraft/lua**'

    // Preserve ComputerCraft classes - we only want to strip shadowed files.
    keep 'class dan200.computercraft.** { *; }'
}

task proguardMove(dependsOn: proguard) {
    description "Replace the original jar with the minified version"
    group "compact"

    doLast {
        Files.move(
            file("${jar.archivePath.absolutePath.replace(".jar", "")}-min.jar").toPath(),
            file(jar.archivePath).toPath(),
            StandardCopyOption.REPLACE_EXISTING
        )
    }
}

reobfJar.dependsOn proguardMove

processResources {
    inputs.property "version", mod_version
    inputs.property "mcversion", mc_version

    def hash = 'none'
    Set<String> contributors = []
    try {
        def grgit = Grgit.open(dir: '.')
        hash = grgit.head().id

        def blacklist = ['GitHub', 'dan200', 'Daniel Ratcliffe']
        grgit.log().each {
            if (!blacklist.contains(it.author.name)) contributors.add(it.author.name)
            if (!blacklist.contains(it.committer.name)) contributors.add(it.committer.name)
        }
    } catch(Exception ignored) { }

    inputs.property "commithash", hash

    from(sourceSets.main.resources.srcDirs) {
        include 'mcmod.info'
        include 'assets/computercraft/lua/rom/help/credits.txt'

        expand 'version': mod_version,
               'mcversion': mc_version,
               'gitcontributors': contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
    }

    from(sourceSets.main.resources.srcDirs) {
        exclude 'mcmod.info'
        exclude 'assets/computercraft/lua/rom/help/credits.txt'
    }
}

task compressJson(dependsOn: extractAnnotationsJar) {
    group "compact"
    description "Minifies all JSON files, stripping whitespace"

    def jarPath = file(jar.archivePath)

    def tempPath = File.createTempFile("input", ".jar", temporaryDir)
    tempPath.deleteOnExit()

    def gson = new GsonBuilder().create()

    doLast {
        // Copy over all files in the current jar to the new one, running json files from GSON. As pretty printing
        // is turned off, they should be minified.
        new ZipFile(jarPath).withCloseable { inJar ->
            tempPath.getParentFile().mkdirs()
            new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(tempPath))).withCloseable { outJar ->
                inJar.entries().each { entry ->
                    if(entry.directory) {
                        outJar.putNextEntry(entry)
                    } else if(!entry.name.endsWith(".json")) {
                        outJar.putNextEntry(entry)
                        inJar.getInputStream(entry).withCloseable { outJar << it }
                    } else {
                        ZipEntry newEntry = new ZipEntry(entry.name)
                        newEntry.setTime(entry.time)
                        outJar.putNextEntry(newEntry)

                        def element = inJar.getInputStream(entry).withCloseable { gson.fromJson(it.newReader("UTF8"), JsonElement.class) }
                        outJar.write(gson.toJson(element).getBytes(StandardCharsets.UTF_8))
                    }
                }

            }
        }

        // And replace the original jar again
        Files.move(tempPath.toPath(), jarPath.toPath(), StandardCopyOption.REPLACE_EXISTING)
    }
}

assemble.dependsOn compressJson

// Check tasks

test {
    useJUnitPlatform()
    testLogging {
        events "skipped", "failed"
    }
}

jacocoTestReport {
    reports {
        xml.enabled true
        html.enabled true
    }
}

check.dependsOn jacocoTestReport

license {
    mapping("java", "SLASHSTAR_STYLE")
    strictCheck true

    ext.year = Calendar.getInstance().get(Calendar.YEAR)
}

[licenseMain, licenseFormatMain].forEach {
    it.configure {
        include("**/*.java")
        exclude("dan200/computercraft/api/**")
        header rootProject.file('config/license/main.txt')
    }
}

[licenseTest, licenseFormatTest].forEach {
    it.configure {
        include("**/*.java")
        header rootProject.file('config/license/main.txt')
    }
}

gradle.projectsEvaluated {
    tasks.withType(LicenseFormat) {
        outputs.upToDateWhen { false }
    }
}


task licenseAPI(type: LicenseCheck);
task licenseFormatAPI(type: LicenseFormat);
[licenseAPI, licenseFormatAPI].forEach {
    it.configure {
        source = sourceSets.main.java
        include("dan200/computercraft/api/**")
        header rootProject.file('config/license/api.txt')
    }
}

// Upload tasks

task checkRelease {
    group "upload"
    description "Verifies that everything is ready for a release"

    inputs.property "version", mod_version
    inputs.file("src/main/resources/assets/computercraft/lua/rom/help/changelog.txt")
    inputs.file("src/main/resources/assets/computercraft/lua/rom/help/whatsnew.txt")

    doLast {
        def ok = true

        // Check we're targetting the current version
        def whatsnew = new File("src/main/resources/assets/computercraft/lua/rom/help/whatsnew.txt").readLines()
        if (whatsnew[0] != "New features in CC: Tweaked $mod_version") {
            ok = false
            project.logger.error("Expected `whatsnew.txt' to target $mod_version.")
        }

        // Check "read more" exists and trim it
        def idx = whatsnew.findIndexOf { it == 'Type "help changelog" to see the full version history.' }
        if (idx == -1) {
            ok = false
            project.logger.error("Must mention the changelog in whatsnew.txt")
        } else {
            whatsnew = whatsnew.getAt(0 ..< idx)
        }

        // Check whatsnew and changelog match.
        def versionChangelog = "# " + whatsnew.join("\n")
        def changelog = new File("src/main/resources/assets/computercraft/lua/rom/help/changelog.txt").getText()
        if (!changelog.startsWith(versionChangelog)) {
            ok = false
            project.logger.error("whatsnew and changelog are not in sync")
        }

        if (!ok) throw new IllegalStateException("Could not check release")
    }
}
check.dependsOn checkRelease

curseforge {
    apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : ''
    project {
        id = '282001'
        releaseType = 'release'
        changelog = "Release notes can be found on the GitHub repository (https://github.com/SquidDev-CC/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."

        relations {
            incompatible "computercraft"
        }
    }
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
            artifact sourceJar
        }
    }
}

uploadArchives {
    repositories {
        if(project.hasProperty('mavenUploadUrl')) {
            mavenDeployer {
                configuration = configurations.deployerJars

                repository(url: project.property('mavenUploadUrl')) {
                    authentication(
                        userName: project.property('mavenUploadUser'),
                        privateKey: project.property('mavenUploadKey'))
                }

                pom.project {
                    name 'CC: Tweaked'
                    packaging 'jar'
                    description 'CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.'
                    url 'https://github.com/SquidDev-CC/CC-Tweaked'

                    scm {
                        url 'https://github.com/SquidDev-CC/CC-Tweaked.git'
                    }

                    issueManagement {
                        system 'github'
                        url 'https://github.com/SquidDev-CC/CC-Tweaked/issues'
                    }

                    licenses {
                        license {
                            name 'ComputerCraft Public License, Version 1.0'
                            url 'https://github.com/SquidDev-CC/CC-Tweaked/blob/master/LICENSE'
                            distribution 'repo'
                        }
                    }
                }

                pom.whenConfigured { pom ->
                    pom.dependencies.clear()
                }
            }
        }
    }
}

githubRelease {
    token project.hasProperty('githubApiKey') ? project.githubApiKey : ''
    owner 'SquidDev-CC'
    repo 'CC-Tweaked'
    try {
        targetCommitish = Grgit.open(dir: '.').branch.current().name
    } catch(Exception ignored) { }

    tagName "v${mc_version}-${mod_version}"
    releaseName "[${mc_version}] ${mod_version}"
    body {
        "## " + new File("src/main/resources/assets/computercraft/lua/rom/help/whatsnew.txt")
            .readLines()
            .takeWhile { it != 'Type "help changelog" to see the full version history.' }
            .join("\n").trim()
    }
    prerelease false
}

def uploadTasks = ["uploadArchives", "curseforge", "githubRelease"]
uploadTasks.forEach { tasks.getByName(it).dependsOn checkRelease }

task uploadAll(dependsOn: uploadTasks) {
    group "upload"
    description "Uploads to all repositories (Maven, Curse, GitHub release)"
}

runClient.outputs.upToDateWhen { false }
runServer.outputs.upToDateWhen { false }