plugins {
  id 'java'
  id 'com.github.johnrengelman.shadow' version '8.1.1'
  id 'com.github.jk1.dependency-license-report' version '2.5'
  id 'com.diffplug.spotless' version '6.24.0'
}

import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.github.jk1.license.render.TextReportRenderer

java {
  sourceCompatibility = '17'
  targetCompatibility = '17'
}

sourceSets {
  main {
    java {
      srcDirs = ['framework/src']
    }
  }

  grader {
    java {
      srcDirs = ['framework/tst']
    }
    resources {
      srcDirs = ['framework/tst']
      includes = ['**/*.properties']
    }
    compileClasspath += main.compileClasspath + main.output
    annotationProcessorPath += main.annotationProcessorPath
  }

  labs {
    java {
      srcDirs = [ 'labs/lab0-pingpong/src',
                  'labs/lab1-clientserver/src',
                  'labs/lab2-primarybackup/src',
                  'labs/lab3-paxos/src',
                  'labs/lab4-shardedstore/src' ]
    }
    compileClasspath += main.compileClasspath + main.output
    annotationProcessorPath += main.annotationProcessorPath
  }

  labsTests {
    java {
      srcDirs = [ 'labs/lab0-pingpong/tst',
                  'labs/lab1-clientserver/tst',
                  'labs/lab2-primarybackup/tst',
                  'labs/lab3-paxos/tst',
                  'labs/lab4-shardedstore/tst']
    }
    compileClasspath += grader.compileClasspath + grader.output + labs.output
    annotationProcessorPath += grader.annotationProcessorPath
  }

  test {
    java {
      srcDirs = ['framework/tst-self']
    }
    compileClasspath += grader.compileClasspath + grader.output
    runtimeClasspath += grader.runtimeClasspath + labs.runtimeClasspath + labsTests.runtimeClasspath
    annotationProcessorPath += grader.annotationProcessorPath
  }
}

configurations {
  sources {
    transitive = false
  }
  graderImplementation
  graderSources {
    transitive = false
  }
  // Unused configuration, necessary to include google-java-format in license
  // report
  formatter
}

repositories {
  mavenCentral()
}

dependencies {
  implementation      group: 'org.projectlombok', name: 'lombok', version: '1.18.30'
  annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.30'
  sources             group: 'org.projectlombok', name: 'lombok', version: '1.18.30', classifier: 'sources'

  implementation group: 'com.google.guava', name: 'guava', version: '33.0.0-jre'
  sources        group: 'com.google.guava', name: 'guava', version: '33.0.0-jre', classifier: 'sources'
  implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.14.0'
  sources        group: 'org.apache.commons', name: 'commons-lang3', version: '3.14.0', classifier: 'sources'

  graderImplementation group: 'junit', name: 'junit', version: '4.13.2'
  graderSources        group: 'junit', name: 'junit', version: '4.13.2', classifier: 'sources'
  graderImplementation group: 'io.github.kostaskougios', name: 'cloning', version: '1.10.3'
  graderSources        group: 'io.github.kostaskougios', name: 'cloning', version: '1.10.3', classifier: 'sources'

  graderImplementation group: 'commons-cli', name: 'commons-cli', version: '1.6.0'
  graderSources        group: 'commons-cli', name: 'commons-cli', version: '1.6.0', classifier: 'sources'

  graderImplementation group: 'commons-io', name: 'commons-io', version: '2.15.1'
  graderSources        group: 'commons-io', name: 'commons-io', version: '2.15.1', classifier: 'sources'

  graderImplementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.15.2'
  graderSources        group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.15.2', classifier: 'sources'
  graderImplementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.15.2'
  graderImplementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jdk8', version: '2.15.2'

  // Swing stuff
  graderImplementation group: 'com.formdev', name: 'flatlaf', version: '3.3'
  graderImplementation group: 'com.formdev', name: 'flatlaf', version: '3.3', classifier: 'sources'
  graderImplementation group: 'com.formdev', name: 'flatlaf-swingx', version: '3.3'
  graderImplementation group: 'com.formdev', name: 'flatlaf-swingx', version: '3.3', classifier: 'sources'
  graderImplementation group: 'com.github.jiconfont', name: 'jiconfont-font_awesome', version: '4.7.0.1'
  graderImplementation group: 'com.github.jiconfont', name: 'jiconfont-font_awesome', version: '4.7.0.1', classifier: 'sources'
  graderImplementation group: 'com.github.jiconfont', name: 'jiconfont-swing', version: '1.0.1'
  graderImplementation group: 'com.github.jiconfont', name: 'jiconfont-swing', version: '1.0.1', classifier: 'sources'
  graderImplementation group: 'com.miglayout', name: 'miglayout-swing', version: '11.3'
  graderImplementation group: 'com.miglayout', name: 'miglayout-swing', version: '11.3', classifier: 'sources'
  graderImplementation group: 'org.swinglabs.swingx', name: 'swingx-core', version: '1.6.5-1'
  graderImplementation group: 'org.swinglabs.swingx', name: 'swingx-core', version: '1.6.5-1', classifier: 'sources'

  formatter group:'com.google.googlejavaformat', name: 'google-java-format', version: '1.19.2'
}

// Create reproducible jars
tasks.withType(AbstractArchiveTask) {
  preserveFileTimestamps = false
  reproducibleFileOrder = true
}

task scaffoldingJar(type: ShadowJar) {
  archiveBaseName = 'framework'
  from sourceSets.main.output
}

task graderJar(type: ShadowJar) {
  archiveBaseName = 'grader'
  from sourceSets.grader.output
}

task scaffoldingSourcesJar(type: ShadowJar) {
  archiveBaseName = 'framework'
  archiveClassifier = 'sources'
  from sourceSets.main.java
}

task graderSourcesJar(type: ShadowJar) {
  archiveBaseName = 'grader'
  archiveClassifier = 'sources'
  from sourceSets.grader.java
}

task scaffoldingDependenciesJar(type: ShadowJar) {
  archiveBaseName = 'framework'
  archiveClassifier = 'deps'
  configurations = [ project.configurations.runtimeClasspath ]
}

task graderDependenciesJar(type: ShadowJar) {
  archiveBaseName = 'grader'
  archiveClassifier = 'deps'
  configurations = [ project.configurations.graderRuntimeClasspath ]
}

task scaffoldingDependenciesSourcesJar(type: ShadowJar) {
  archiveBaseName = 'framework'
  archiveClassifier = 'deps-sources'
  configurations = [ project.configurations.sources ]
}


jar.enabled = false

javadoc {
  title = 'Distributed Systems Labs Framework'
  destinationDir = file("$buildDir/doc")
  options.noTimestamp(true)
  options.noIndex(true)
  options.noDeprecatedList(true)
  options.noHelp(true)
  options.setOutputLevel(JavadocOutputLevel.QUIET)
}

tasks.assemble.dependsOn tasks.scaffoldingJar
tasks.assemble.dependsOn tasks.graderJar
tasks.assemble.dependsOn tasks.scaffoldingSourcesJar
tasks.assemble.dependsOn tasks.graderSourcesJar
tasks.assemble.dependsOn tasks.scaffoldingDependenciesJar
tasks.assemble.dependsOn tasks.graderDependenciesJar
tasks.assemble.dependsOn tasks.scaffoldingDependenciesSourcesJar

// copy dependencies into directories that IntelliJ can find
task copyDependencies {
  doLast {
    copy {
      from configurations.runtimeClasspath,
           configurations.sources
      into "deps/compile"
    }
    copy {
      from configurations.graderRuntimeClasspath,
           configurations.graderSources
      into "deps/test"
    }
  }
}

// Put gradle wrapper in a hidden folder
wrapper {
  jarFile = file('.gradle-wrapper/gradle-wrapper.jar')
}

// Run tests with illegal-access=deny to ensure that these warnings are caught
test.jvmArgs(['-ea',
              '--add-opens', 'java.base/java.lang=ALL-UNNAMED',
              '--add-opens', 'java.base/java.math=ALL-UNNAMED',
              '--add-opens', 'java.base/java.time=ALL-UNNAMED',
              '--add-opens', 'java.base/java.util.concurrent.atomic=ALL-UNNAMED',
              '--add-opens', 'java.base/java.util=ALL-UNNAMED',
              '--add-opens', 'java.base/jdk.internal.reflect=ALL-UNNAMED'])

licenseReport {
  configurations = ALL
  outputDir = "${project.buildDir}/reports/licenses"
  renderers = [ new TextReportRenderer() ]
}

// Spotless auto-formatter config
spotless {
  java {
    removeUnusedImports()
    cleanthat()
    googleJavaFormat()
  }
}
