buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.google.guava:guava:27.1-jre'
        classpath 'org.apache.maven:maven-artifact:3.6.1'
    }
}

apply plugin: 'eclipse'
apply plugin: 'idea'

import groovy.json.JsonOutput

def latestVersion = file('version.txt').readLines().first()
def releaseCommit = command('git', 'blame', '-p', '-l', 'version.txt').first().tokenize(' ').first()
if (latestVersion == '2.1.0') { // First version since change from tag-based
    releaseCommit = '35ac26e91689ac9bdf12dbb9902c452464a75108' // git rev-parse 1.12.2-2.1.0
}
def currentCommit = command('git', 'rev-parse', 'HEAD').first()
if (releaseCommit == currentCommit) {
    version = latestVersion
} else {
    def diff = command('git', 'log', '--format=oneline', "$releaseCommit..$currentCommit").size()
    version = "$latestVersion-$diff-g${currentCommit.substring(0, 7)}"
}
if (gitDescribe().endsWith('*')) {
    version = "$version-dirty"
}

group= "com.replaymod"

// Fabric's remapJar task assumes the compile configuration to exist
configurations { compile }

task shadowJar(type: Copy) {
    into "$buildDir/libs"
}

subprojects {
    buildscript {
        repositories {
            maven { url 'https://jitpack.io' }
        }
    }

    // Thanks for wasting my time gradle...
    // Workaround for https://discuss.gradle.org/t/idea-plugin-bug/21525
    apply plugin: 'eclipse'
    apply plugin: 'idea'

    afterEvaluate {
        def shadowJar = project.tasks.findByName('shadowJar')
        if (shadowJar != null && shadowJar.hasProperty('archivePath') && project.name != 'core') {
            def rootTask = rootProject.tasks.shadowJar
            rootTask.dependsOn shadowJar
            rootTask.from shadowJar.archivePath
        }
    }
}

def gitDescribe() {
    try {
        def stdout = new ByteArrayOutputStream()
        exec {
            commandLine 'git', 'describe', '--always', '--dirty=*'
            standardOutput = stdout
        }
        return stdout.toString().trim()
    } catch (e) {
        return "unknown"
    }
}

def command(Object...cmd) {
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine cmd
        standardOutput = stdout
    }
    return stdout.toString().tokenize('\n')
}

def generateVersionsJson() {
    // Find all tag-style releases by listing all tags
    def tagVersions = command 'git', 'for-each-ref', '--sort=taggerdate', '--format=%(refname:short)', 'refs/tags'

    // Find all commit-style releases
    // List all commits
    def releaseCommits =
            command 'git', 'log', '--format=%H', '--date-order', '-E',
                    '--grep', /Pre-release [0-9]+ of [0-9]+\.[0-9]+\.[0-9]+/,
                    '--grep', /Release [0-9]+\.[0-9]+\.[0-9]+/
    // Find version string and MC versions for each commit hash
    def commitVersions = releaseCommits.collect { commit ->
        def version = command('git', 'show', "$commit:version.txt").first()
        def mcVersions = command 'git', 'ls-tree', '-d', '--name-only', "$commit:versions"
        mcVersions.remove('core')
        return mcVersions.collect { "$it-$version" }
    }.flatten()

    def versions = commitVersions + tagVersions.reverse()
    def mcVersions = versions.collect {it.substring(0, it.indexOf('-'))}.unique()
    mcVersions.sort(new OrderBy([0, 1, 2].collect { i -> { it -> (it.tokenize('.')[i] ?: '0') as int } }))

    def root = [
            homepage: 'https://www.replaymod.com/download/',
            promos: [:]
    ]
    mcVersions.forEach { mcVersion ->
        def mcVersionRoot = [:]
        def latest
        def recommended
        versions.forEach {
            def (thisMcVersion, modVersion, preVersion) = it.tokenize('-')
            if (thisMcVersion == mcVersion) {
                mcVersionRoot[it] = tagVersions.contains(it) ?
                        "See https://github.com/ReplayMod/ReplayMod/releases/$it" :
                        'See https://www.replaymod.com/forum/thread/100'
                if (latest == null) latest = it
                if (preVersion == null) {
                    if (recommended == null) recommended = it
                }
            }
        }
        root[mcVersion] = mcVersionRoot
        root.promos[mcVersion + '-latest'] = latest
        if (recommended != null) {
            root.promos[mcVersion + '-recommended'] = recommended
        }
    }
    root
}

task doRelease() {
    doLast {
        // Parse version
        def version = project.releaseVersion as String
        if (gitDescribe().endsWith('*')) {
            throw new InvalidUserDataException('Git working tree is dirty. Make sure to commit all changes.')
        }
        def (modVersion, preVersion) = version.tokenize('-')
        preVersion = preVersion != null && preVersion.startsWith('b') ? preVersion.substring(1) : null

        // Create new commit
        def commitMessage = preVersion != null ?
                "Pre-release $preVersion of $modVersion" :
                "Release $modVersion"
        file('version.txt').write("$version\n")
        command 'git', 'add', 'version.txt'
        command 'git', 'commit', '-m', commitMessage

        // Generate versions.json content
        def versionsRoot = generateVersionsJson()
        def versionsJson = JsonOutput.prettyPrint(JsonOutput.toJson(versionsRoot))

        // Switch to master branch to update versions.json
        command 'git', 'checkout', 'master'

        // Write versions.json
        new File('versions.json').write(versionsJson)

        // Commit changes
        project.exec { commandLine 'git', 'add', 'versions.json' }
        project.exec { commandLine 'git', 'commit', '-m', "Update versions.json for $version" }

        // Return to previous branch
        project.exec { commandLine 'git', 'checkout', '-' }
    }
}

defaultTasks 'shadowJar'
