
plugins {
  id 'java'
  id 'java-library'
  id 'java-test-fixtures'
  id 'io.freefair.lombok' version '8.14.2'
  id 'eclipse'
  id 'com.diffplug.spotless' version '8.4.0' apply false
  id 'me.champeau.jmh' version '0.6.8'
}

repositories {
  mavenCentral()
}

// Only ratchet if we're in a git repo - this won't be the case for
// containerized worktrees or source zip builds
ext.spotlessRatchet = {
  def dotGit = file("${rootDir}/.git")
  // standard git repo - .git is a dir
  if (dotGit.isDirectory()) {
    return true
  }
  // worktree - .git is a file containing 'gitdir: <path>'
  if (dotGit.isFile()) {
    def content = dotGit.text.trim()
    if (content.startsWith('gitdir:')) {
      return new File(content.substring('gitdir:'.length()).trim()).isDirectory()
    }
  }
  // neither, disable ratcheting
  return false
}()

// give a warning if ractcheting hasn't applied
if (!ext.spotlessRatchet) {
  logger.warn("Spotless ratcheting disabled - no .git directory found")
}

subprojects {

  apply plugin: 'com.diffplug.spotless'

  spotless {
    // makes sure that checks/fixes are only applied to diffs from master
    // even though we have bulk-reformatted the src - Checking and formatting
    // run quicker with this on.
    if (spotlessRatchet) {
      ratchetFrom 'origin/master'
    }

    java {

      // ignore various monkey patches/vendored changes
      target fileTree('.') {
        include "src/main/java/**/*.java"
        include "src/test/java/**/*.java"
        exclude "src/main/java/org/geotools/**/*.java"
        exclude "src/main/java/nz/org/riskscape/picocli/**.java"
        exclude "src/main/java/ucar/nc2/filter/**.java"
      }

      prettier(['prettier': '3.0.3', 'prettier-plugin-java': '2.3.0'])
        .config([
            'parser': 'java',
            'tabWidth': 2,
            // NB this is a goal, not a limit - I think it'll end up looking better than
            // 120, otherwise we get some pretty humongous statements, and prettier will
            // take care of doing the fancy line wrapping for us.
            'printWidth': 100,
            'bracketSpacing': false,
            'plugins': ['prettier-plugin-java']]
        )
    }

  }

  ext {
    riskscapeVersion = rootProject.file('VERSION').text.trim()
    jtsVersion = '1.19.0'
    geotoolsVersion = '31.2'
    jlineVersion = '3.21.0'
    logbackVersion = '1.5.3'
  }

  // not sure why, but these need to be stated like this, instead of in plugins block
  apply plugin: 'java-library'
  apply plugin: 'java-test-fixtures'
  apply plugin: 'io.freefair.lombok'
  apply plugin: 'eclipse'
  apply plugin: 'me.champeau.jmh'

  // we want to build with a JDK17 toolchain
  java.toolchain.languageVersion = JavaLanguageVersion.of(17)
  compileJava.options.release = 17
  compileJava.options.encoding="UTF-8"
  compileTestJava.options.encoding="UTF-8"

  repositories {

    // this needs to go first so that lookups for javax/media go here first, and any repo that is in
    // $HOME/.gradle/init.gradle needs to exclude the javax/media files
    maven {
      url "https://repo.osgeo.org/repository/release/"
    }
    mavenCentral()
    // unidata repository is added for :plugin:netcdf to access snapshot builds
    // of edu.ucar.cdm-core.
    //maven {
    //  url "https://artifacts.unidata.ucar.edu/repository/unidata-all/"
    //  content {
    //    // the unidata repository looks like it is also a mirror. so we use
    //    // include group to limit it to only edu.ucar.
    //    includeGroup "edu.ucar"
    //  }
    //}
  }

  tasks.withType(JavaCompile) {
    options.compilerArgs.addAll(["-Xlint:unchecked"])
  }

  configurations {
    // contains dependencies that we don't want showing up in eclipse's classpath
    // this was introduced to exclude an older version of junit that was being picked
    // up in json-simple's dependencies
    noeclipse
  }

  def parts = []
  def projPtr = project;

  while (projPtr != null) {
    parts.add(projPtr.name)
    projPtr = projPtr.parent
  }

  def fullName = parts.reverse().join("-")
  eclipse {

    classpath {
      downloadSources = true
    }

    project {
      name = fullName

      classpath {
        minusConfigurations += [ configurations.noeclipse ]
      }
    }
  }

  dependencies {
    // TODO need to shift this out of here and find another way to share its use across
    // modules, as a lot of code wants to include guava and we see linking errors when we
    // have different versions
    api group: 'com.google.guava', name: 'guava', version: '33.6.0-jre'
    // jsr305 contains javax.annotation.Nullable
    compileOnly group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2'
    api group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
    api group: 'org.slf4j', name: 'jul-to-slf4j', version: '1.7.25'
    testImplementation group: 'junit', name: 'junit', version: '4.12'
    testImplementation group: 'org.hamcrest', name: 'hamcrest-library', version: '2.1'
    testImplementation "org.mockito:mockito-core:2.+"
    testFixturesImplementation group: 'junit', name: 'junit', version: '4.12'
    testFixturesImplementation group: 'org.hamcrest', name: 'hamcrest-library', version: '2.1'
    testFixturesImplementation "org.mockito:mockito-core:2.+"

    // json-simple declares a test dependency on this - it is missing assertNotEquals, which
    // we rely one
    noeclipse group: 'junit', name: 'junit', version: '4.10'
    // hatbox can cause a conflict when we import java.sql
    noeclipse group: 'net.sourceforge.hatbox', name: 'hatbox', version: '1.0.b10'
  }

  // For running benchmarks, see https://github.com/melix/jmh-gradle-plugin
  // ./gradlew engine:core:jmh # run all benchmarks, will fail if none defined
  jmh {
    warmupIterations = 2
    iterations = 5
    fork = 1
  }

  test {
    useJUnit {

      // don't do SkipTestOnWindows in core (avoid adding a test-shared
      // dependency that leads to eclipse circular dependency).
      if(System.getenv("OS")!=null && project.name != "core") {
        excludeCategories 'nz.org.riskscape.test.SkipTestOnWindows'
      }
    }

    testLogging {
        showStandardStreams = true
    }
  }

  task testNoSkip (type:Test) {
    useJUnit()

    testLogging {
        showStandardStreams = true
    }
  }

  jar {
    // pull the version suffix from the jars - this has been done to simplify some of the
    // classpath logic for windows to avoid #591.  Given the version was always
    // 1.0,  we're not losing anything by doing this.  If in the
    // future we start publishing our api jars then we might need some other solution
    archiveVersion = ''
  }

  // for sub-projects that contain `src/main/java` we want to ensure that javadoc processes
  // delombok'd source code. but this doesn't work if there is no `src/main/java` hence
  // skipping it in that case
  if (file("src/main/java").isDirectory()) {

    task javadocMarkdownToHTML(type: Exec, dependsOn: delombok) {
      workingDir '.'

      commandLine rootProject.file('./bin/javadoc-markdown.rb'), "$buildDir/generated/sources/delombok/java", "$buildDir/demarkdown"

      // always run this, but we *could* base it on delombok being up to date?
      outputs.upToDateWhen { false }
    }

    javadoc {
      dependsOn javadocMarkdownToHTML
      source = "$buildDir/demarkdown"
      failOnError = false
    }
  }
}

// enabling this for the various plugin projects (and maybe cli?) prevents the plugins from appearing in the install
// directory, so limit it to the one's we're likely to want to publish
configure(subprojects.findAll { it.name == 'engine:api' || it.name == 'test:shared' || it.name == 'engine:core'   }) {

  apply plugin: 'maven-publish'

  group = "nz.org.riskscape"
  version = "1.0"

  task sourcesJar(type: Jar, dependsOn: classes) {
    classifier = 'sources'
    from sourceSets.main.allSource
  }

  artifacts {
    archives sourcesJar
  }
}
