// This Gradle script builds the DocBook stylesheet releases.
//
// Note well: there's a little Java tool in this repo, but it is not,
// first and foremost, a Java project.

buildscript {
  repositories {
    mavenLocal()
    mavenCentral()
  }

  // See also: buildSrc/build.gradle
  dependencies {
    classpath files("lib")
    classpath fileTree(dir: 'lib').include("*.jar")
    classpath group: 'com.xmlcalabash', name: 'xmlcalabash1-print', version: '1.1.5'
    classpath group: 'com.xmlcalabash', name: 'xmlcalabash', version: xmlCalabashVersion
    classpath group: 'com.xmlcalabash', name: 'xmlcalabash1-gradle', version: '1.4.0'
    classpath group: 'com.xmlcalabash', name: 'xmlcalabash1-deltaxml', version: '1.1.5'
    classpath group: 'org.docbook', name: 'docbook-schemas', version: '5.1-1'
  }
}

plugins {
  id "java"
  id "groovy"
  id "maven-publish"
  id "signing"
  id "de.undercouch.download" version "4.0.4"
}

defaultTasks 'compileXslt'

apply plugin: 'com.xmlcalabash.task'

import com.xmlcalabash.XMLCalabashTask
import de.undercouch.gradle.tasks.download.Download

repositories {
  mavenLocal()
  mavenCentral()
  maven { url "https://maven.restlet.com" }
}

configurations.all {
  resolutionStrategy {
    force 'xml-apis:xml-apis:1.4.01'
  }
}

configurations {
  pluginApi
  projectImplementationClasspath.extendsFrom(implementation)
  projectRuntimeClasspath.extendsFrom(runtimeOnly)
}

dependencies {
  implementation fileTree(dir: 'lib').include("*.jar")
  implementation (
    [group: 'com.nwalsh', name: 'nwalsh-annotations', version: '1.0.0'],
    [group: 'net.sf.saxon', name: 'Saxon-HE', version: saxonVersion],
    [group: 'org.relaxng', name: 'jing', version: '20181222' ],
    [group: 'org.xmlresolver', name: 'xmlresolver', version: '1.0.5'],
    [group: 'com.xmlcalabash', name: 'xmlcalabash', version: xmlCalabashVersion],
    [group: 'com.xmlcalabash', name: 'xmlcalabash1-gradle', version: '1.3.5'],

    // 1.2 because that's what gradleApi requires :-(
    [group: 'commons-cli', name: 'commons-cli', version: '1.2']
  )

  runtimeOnly (
    [group: 'org.relaxng', name: 'trang', version: '20181222' ],
    [group: 'com.xmlcalabash', name: 'xmlcalabash1-print', version: '1.1.5'],
  )

  pluginApi gradleApi()
}

// Assuming the pattern for Saxon versions is 1.2.3-4
int pos = saxonVersion.indexOf(".")
String major = saxonVersion.substring(0, pos)
String temp = saxonVersion.substring(pos+1)
pos = temp.indexOf(".")
String minor = temp.substring(0, pos)
pos = saxonVersion.indexOf("-")

project.ext.saxonRelease = saxonVersion.substring(0,pos)
project.ext.saxonBranch  = major + minor
project.ext.releaseVersion = relVersion
project.ext.distVersion = relVersion + "-" + saxonBranch + snapshot

if (!hasProperty("sonatypeUsername")) {
  ext.sonatypeUsername=""
}

if (!hasProperty("sonatypePassword")) {
  ext.sonatypePassword=""
}

compileGroovy {
  classpath += configurations.pluginApi
}

compileJava {
  classpath += configurations.pluginApi
  options.compilerArgs += ["-Xlint:unchecked"]
}

sourceSets {
  main {
    resources {
      srcDirs "build/stage/jar"
    }
  }
}

// ======================================================================
// Compile the stylesheets

task compileXslt(dependsOn: [ "compileSchemas",
                              "copyXsltSources", "foParams", "htmlParams",
                              "gentext", "makeVersion" ]) {
  // nop
}

task copyXsltSources(type: Copy) {
  FileTree tree = fileTree(dir: 'xslt', exclude: ['**/param.xml', '/params'])
  from tree
  into 'build/xslt'
  doFirst {
    mkdir("build/xslt")
  }
}

task foParams(type: JavaExec) {
  classpath = configurations.projectRuntimeClasspath

  inputs.file  "tools/mkparam.xsl"
  inputs.files fileTree(dir: "xslt/params/")
  inputs.files fileTree(dir: "xslt/base/fo/").include("param.xml")
  outputs.file "build/xslt/base/fo/param.xsl"

  main = 'net.sf.saxon.Transform'
  args('-xsl:tools/mkparam.xsl',
       '-o:build/xslt/base/fo/param.xsl',
       'xslt/base/fo/param.xml')
}

task htmlParams(type: JavaExec) {
  classpath = configurations.projectRuntimeClasspath

  inputs.file "tools/mkparam.xsl"
  inputs.files fileTree(dir: "xslt/params/")
  inputs.files fileTree(dir: "xslt/base/html/").include("param.xml")
  outputs.file "build/xslt/base/html/param.xsl"

  main = 'net.sf.saxon.Transform'
  args('-xsl:tools/mkparam.xsl',
       '-o:build/xslt/base/html/param.xsl',
       'xslt/base/html/param.xml')
}

task gentext() {
  // just a task to hang dependencies on
}

def locales = fileTree(dir: "src/main/gentext/").include("*.xml")
locales.each { File file ->
  String name = file.getName();
  String in_name = "src/main/gentext/" + name
  String out_name = "build/xslt/base/common/locales/" + name

  Task t = task "gentext_$name"(type: XMLCalabashTask) {
    inputs.file in_name
    inputs.file "tools/gentext.xpl"
    inputs.file "build/schemas/locale.rng"
    inputs.file "tools/build-l10n.xsl"
    outputs.file out_name
    input("source", in_name)
    output("result", out_name)
    pipeline "tools/gentext.xpl"
    doFirst {
      mkdir ("build/xslt/base/common/locales")
    }
  }
  t.dependsOn("compileSchemas")
  gentext.dependsOn "gentext_$name"
}

task makeVersion(type: JavaExec) {
  classpath = configurations.projectRuntimeClasspath

  main = 'net.sf.saxon.Transform'
  args('-it:main',
       '-o:build/xslt/base/VERSION.xsl',
       '-xsl:tools/version.xsl',
       'version=' + relVersion,
       'resourcesVersion=' + resourcesVersion)
}

// ======================================================================
// Compile the schemas

task compileSchemas(dependsOn: [ "copyRnc" ]) {
  // nop
}

task copyRnc(type: Copy) {
  from "src/main/schemas"
  into "build/schemas"
  doFirst {
    mkdir("build/schemas")
  }
}

def schemas = ["docbook.rnc", "i18n.rnc", "locale.rnc", "xslt.rnc"]
schemas.each { String rnc ->
  String rng = rnc.substring(0, rnc.lastIndexOf(".")) + ".rng"

  Task t = task "compile_rng_$rnc"(type: JavaExec) {
    classpath = configurations.projectRuntimeClasspath

    inputs.dir "src/main/schemas"
    outputs.file "build/schemas/" + rng
    main = 'com.thaiopensource.relaxng.translate.Driver'
    args = ["src/main/schemas/" + rnc, "build/schemas/" + rng]
  }
  t.doFirst {
    mkdir("build/schemas")
  }
  compileSchemas.dependsOn "compile_rng_$rnc"
}

// ======================================================================
// Run tests

/*
test {
  systemProperty "log4j.configurationFile", "/Users/ndw/java/log4j2-debug.xml"
}
*/

task test_html() {
  // just a task to hang dependencies on
};
test.dependsOn test_html

task test_print_css() {
  // just a task to hang dependencies on
};
test.dependsOn test_print_css

task test_print_fo() {
  // just a task to hang dependencies on
};
test.dependsOn test_print_fo

def tests = fileTree(dir: "src/test/xml/", exclude: ['**/linkbase.xml']).include(testsrc)
tests.each { File file ->
  String filename = file.getName()
  String testname = filename.substring(0, filename.lastIndexOf("."))

  // For the purpose of the XSLT, just claim we're putting the
  // files in the same directory as the sources; this avoids
  // mangled graphics paths.
  String outputDir = file.getAbsolutePath()
  pos = outputDir.lastIndexOf(File.separator)
  outputDir = outputDir.substring(0, pos+1)

  Task t = task "test_html_$testname"(type: XMLCalabashTask, dependsOn: [ "setupTestResources" ]) {
    inputs.dir "xslt"
    inputs.dir "src/main/gentext"
    inputs.dir "tools/test"
    outputs.file "build/test/actual-html/" + testname + ".html"
    inputs.file "src/test/xml/" + testname + ".xml"
    option("name", testname)
    param("output.dir", outputDir)
    option("preprocess", pre_html)
    option("postprocess", post_html)
    option("ignore-head", ignoreHead)
    option("ignore-prism", ignorePrism)
    pipeline "tools/test/htmltest.xpl"
  }
  t.dependsOn "compileXslt"
  test_html.dependsOn "test_html_$testname"

  t = task "test_print_css_$testname"(type: XMLCalabashTask, dependsOn: [ "setupTestResources" ]) {
    inputs.dir "xslt"
    inputs.dir "src/main/gentext"
    inputs.dir "tools/test"
    outputs.file "build/test/actual-print-css/" + testname + ".pdf"
    option("name", testname)
    option("resultdir", "../../build/test/result-print-css/")
    option("actualdir", "../../build/test/actual-print-css/")
    option("expecteddir", "../../src/test/expected-print-css/")
    option("diffdir", "../../build/test/diff-print-css/")
    option("format", "cssprint")
    option("css", "build/test/resources/css/paged-media.css")
    option("preprocess", pre_print_css)
    option("postprocess", post_print_css)
    param("syntax-highlighter", "false")
    pipeline "tools/test/printtest.xpl"
  }
  t.dependsOn "compileXslt"
  test_print_css.dependsOn "test_print_css_$testname"

  t = task "test_print_fo_$testname"(type: XMLCalabashTask, dependsOn: [ "setupTestResources" ]) {
    inputs.dir "xslt"
    inputs.dir "src/main/gentext"
    inputs.dir "tools/test"
    outputs.file "build/test/actual-print-fo/" + testname + ".pdf"
    option("name", testname)
    option("resultdir", "../../build/test/result-print-fo/")
    option("actualdir", "../../build/test/actual-print-fo/")
    option("expecteddir", "../../src/test/expected-print-fo/")
    option("diffdir", "../../build/test/diff-print-fo/")
    option("format", "foprint")
    option("preprocess", pre_print_fo)
    option("postprocess", post_print_fo)
    pipeline "tools/test/printtest.xpl"
  }
  t.dependsOn "compileXslt"
  test_print_fo.dependsOn "test_print_fo_$testname"
}

task setupResourcesForTest(type: Copy, dependsOn: [ "setupResources" ]) {
  from "build/docbook-xslt20-resources-" + resourcesVersion
  into "build/test/resources"
  rename ("build/test/resources/docbook-xslt20-resources-" + resourcesVersion,
          "build/test/resources")
  doFirst {
    mkdir("build/test/resources")
  }
}

task setupSourcesForTest(type: Copy, dependsOn: [ "setupResources" ]) {
  from "src/test/xml"
  into "build/test/src"
  doFirst {
    mkdir("build/test/src")
  }
}

task setupTestResources(type: Copy, dependsOn: [ "setupResourcesForTest",
                                                 "setupSourcesForTest" ]) {
  from "src/test/resources"
  into "build/test/resources"
}

// ======================================================================
// Make test report(s)

task testReport(type: XMLCalabashTask,
                dependsOn: ["copy_test_css", "copy_test_graphics",
                            "copy_expected_html", "test_html"]) {
  inputs.file  file("tools/test/report.xpl")
  inputs.file  file("tools/test/format-report.xsl")
  inputs.dir   "build/test/actual-html/"
  inputs.dir   "build/test/result-html/"
  outputs.file file("build/test/index.html")

  option("baseline", baseline)
  output("result", "build/test/index.html")
  pipeline("tools/test/report.xpl")
}
// Make the report part of the standard 'test' target build
test.dependsOn testReport

task copy_test_css(type: Copy) {
  from 'src/test/resources'
  include "*.css"
  into 'build/test/css'
  doFirst {
    mkdir("build/test/css")
  }
}

task copy_test_graphics(type: Copy) {
  from 'src/test/graphics'
  into 'build/test/graphics'
  doFirst {
    mkdir("build/test/graphics")
  }
}

task copy_expected_html(type: Copy) {
  from 'src/test/expected-html'
  into 'build/test/expected-html'
  doFirst {
    mkdir("build/test/expected-html")
  }
}

// ======================================================================
// Make ZIP distribution

task stageZip(type: Copy, dependsOn: [ "compileXslt", "copyResources" ]) {
  from 'build/xslt'
  into 'build/stage/zip/xslt'
  doFirst {
    mkdir("build/stage/zip/xslt")
  }
}

task relNotes(type: XMLCalabashTask, dependsOn: [ "compileXslt" ]) {
  option("schema", "https://docbook.org/xml/5.1/rng/docbook.rng")
  param("resource.root", "https://cdn.docbook.org/latest/")
  input("source", "docs/RELEASENOTES.xml")
  output("result", "build/stage/zip/docs/RELEASENOTES.html")
  pipeline "build/xslt/base/pipelines/docbook.xpl"
  doFirst {
    mkdir("build/stage/zip/docs")
  }
}

task copyDocs(type: Copy, dependsOn: [ "relNotes", "copyReadme" ]) {
  from "docs"
  exclude "RELEASENOTES.xml"
  into "build/stage/zip/docs/"
}

task copyReadme(type: Copy) {
  from 'README.md'
  into "build/stage/zip/"
}

task copyResources(dependsOn: [ "copyDocs", "copyVendors", "setupResources" ]) {
  // nop
}

task copyVendors(type: Copy) {
  from "vendor/"
  into "build/stage/zip/vendor"
}

task zip(type: Zip, dependsOn: [ "stageZip" ]) {
  archiveFileName = "docbook-xslt2-" + relVersion + ".zip"
  from('build/stage/zip')
  into 'docbook-xslt2-' + relVersion
}

task zipApp(type: Zip, dependsOn: [ "jar" ]) {
  String jarfn = "docbook-xslt2-" + relVersion + ".jar"
  FileTree tree = fileTree(dir: 'build/libs').include(jarfn).include("lib/*.jar")
  archiveFileName = 'docbook-xslt2-' + relVersion + "-app.zip"
  from tree
  into 'docbook-xslt2-' + relVersion + "-app"
}

// ======================================================================
// Make JAR distribution

task stageJar(type: Copy, dependsOn: [ "compileXslt", "makeUris",
                                       "makeVersionProperties" ]) {
  from "build/xslt"
  into "build/stage/jar/xslt"
  doFirst {
    mkdir ("build/stage/jar/xslt")
  }
}
processResources.dependsOn stageJar

task javadocJar(type: Jar, dependsOn: javadoc) {
  classifier = 'javadoc'
  from javadoc.destinationDir
}

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

task makeVersionProperties() {
  doFirst {
    mkdir("build/stage/jar/etc")
  }
  doLast {
    new File("build/stage/jar/etc/version.properties").text = """version=$relVersion
resourcesVersion=$resourcesVersion
"""
  }
}

task makeUris(type: XMLCalabashTask, dependsOn: [ "compileXslt", "copyResources" ]) {
  inputs.file   "tools/makecat.xpl"
  inputs.files  fileTree(dir: "build/xslt/")
  outputs.file "build/stage/jar/etc/uris.xml"

  output("result", "build/stage/jar/etc/uris.xml")
  pipeline "tools/makecat.xpl"
  doFirst {
    mkdir ("build/stage/jar/etc")
  }
}

task copyLib(type: Copy) {
  FileCollection runtimeOnly  = configurations.projectRuntimeClasspath
  FileCollection implementation  = configurations.projectImplementationClasspath
  FileCollection localLib = fileTree(dir: 'lib').include("*.jar")
  FileCollection lib = implementation + runtimeOnly - localLib
  String path = ""
  lib.each {
    File file -> path += " lib/" + file.name
  }
  project.ext.runtimeClasspath = path.trim()

  from lib
  into { "build/libs/lib" }
}
jar.dependsOn copyLib

task copyJar(type: Copy, dependsOn: [ "jar" ]) {
  from('build/libs')
  include 'docbook-xslt2-' + relVersion + ".jar"
  into 'build/distributions/'
}

jar {
  archiveBaseName = "docbook-xslt2"
  manifest {
    attributes "Built-By": builtBy
    attributes "Implementation-Vendor": "Norman Walsh"
    attributes "Implementation-Title": "DocBook XSLT Stylesheets"
    attributes "Implementation-Version": project.ext.distVersion
    attributes "Main-Class": "org.docbook.Main"
    attributes "Bundle-SymbolicName": "org.docbook"
    attributes "Bundle-RequiredExecutionEnvironment": "J2SE-1.7"
    attributes "Export-Package": "*: etc"
    attributes "Import-Package": "net.sf.saxon.*;version=" + project.ext.saxonRelease + ":\
  javax.xml.*:\
  *;resolution:=optional"
    attributes "DynamicImport-Package": "*"
    // This is a bit of a hack; special case the three most likely
    // commercial jar files for printing with CSS or FO.
    attributes "Class-Path": project.ext.runtimeClasspath \
              + " lib/XfoJavaCtl.jar lib/xep.jar lib/prince.jar"
  }
}

// ======================================================================
// Make JAR ZIP distribution

task stageJarZip(dependsOn: [ "zipJar", "zipLibs", "zipExtra" ]) {
}

task zipJar(type: Copy, dependsOn: [ "jar" ]) {
  from "build/libs"
  include "*.jar"
  into "build/stage/jarzip"
}

task zipLibs(type: Copy, dependsOn: [ "jar" ]) {
  from "build/libs/lib"
  into "build/stage/jarzip/lib"
}

task zipExtra(type: Copy, dependsOn: [ "jar" ]) {
  from "build/stage/zip"
  exclude "xslt"
  into "build/stage/jarzip"
}

task jarZip(type: Zip, dependsOn: [ "stageJarZip" ]) {
  archiveFileName = "docbook-xslt2-" + relVersion + "-" + saxonBranch + "-jar.zip"
  from('build/stage/jarzip')
  into 'docbook-xslt2-' + relVersion + "-" + saxonBranch + "-jar"
}

// ======================================================================
// Make dist

task dist(dependsOn: [ "zip", "zipApp", "copyJar" ]) {
  // nop
}

// ================================================================================
// Setup resources

// Explicitly not into build because it's tedious if 'clean' deletes
// the resources, especially if you're not connected to the internet!
task downloadResources(type: Download) {
  String base = "https://github.com/docbook/xslt20-resources/releases/download/"
  src base + resourcesVersion + "/docbook-xslt20-resources-" + resourcesVersion + ".zip"
  dest new File("lib/resources-" + resourcesVersion + ".zip")
  doFirst {
    mkdir("lib")
  }
}
downloadResources.onlyIf {
  !file("lib/resources-" + resourcesVersion + ".zip").exists()
}

task setupResources(type: Copy, dependsOn: [ "downloadResources" ]) {
  from zipTree(downloadResources.dest)
  into { "build" }
  doFirst {
    mkdir("build/stage/zip")
  }
  doLast {
    copy {
      from "build/docbook-xslt20-resources-" + resourcesVersion
      into "build/stage/zip/resources"
      rename ("build/stage/zip/resources/docbook-xslt20-resources-" + resourcesVersion,
              "build/stage/zip/resources")
    }
  }
}
setupResources.onlyIf {
  !file("build/stage/zip/resources").exists()
}

// ================================================================================
// TestJvm

task runTestJvm(type: JavaExec) {
  classpath = sourceSets.test.runtimeClasspath
  main = "TestJvm"
}

// ================================================================================
// Cleanup

clean {
  doFirst {
    delete "build"
  }
}

// ================================================================================
// Sign, publish, and upload

signing {
  sign publishing.publications
}

publishing {
  publications {
    mavenJava(MavenPublication) {
      pom {
        name = 'DocBook XSLT 2.0 Stylesheets'
        description = 'DocBook XSLT 2.0 stylesheets'
        url = 'https://github.com/docbook/xslt20-stylesheets'

        scm {
          url = 'scm:git@github.com:docbook/xslt20-stylesheets.git'
          connection = 'scm:git@github.com:docbook/xslt20-stylesheets.git'
          developerConnection = 'scm:git@github.com:docbook/xslt20-stylesheets.git'
        }

        licenses {
          license {
            name = 'Apache License version 2.0'
            url = 'https://www.apache.org/licenses/LICENSE-2.0'
            distribution = 'repo'
          }
        }

        developers {
          developer {
            id = 'ndw'
            name = 'Norman Walsh'
          }
        }
      }

      groupId = group
      artifactId = 'docbook-xslt2'
      version = relVersion
      from components.java
      artifact javadocJar
      artifact sourcesJar
    }
  }

  repositories {
    maven {
      url = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
      credentials {
        username = sonatypeUsername
        password = sonatypePassword
      }
    }
    /*
    maven {
      url 'file://tmp/repo'
    }
    */
  }
}
