
/*
 * Copyright 2010 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import org.gradle.build.docs.UserGuideTransformTask
import org.gradle.build.docs.ExtractSnippetsTask
import org.gradle.build.docs.AssembleSamplesDocTask
import org.gradle.build.docs.dsl.docbook.AssembleDslDocTask
import org.gradle.build.docs.dsl.ExtractDslMetaDataTask
import org.gradle.build.GenerateReleasesXml
import org.gradle.os.OperatingSystem

apply plugin: 'base'

configurations {
    userGuideStyleSheets
    userGuideTask
}

dependencies {
    userGuideTask 'xalan:xalan:2.7.1', 'xerces:xercesImpl:2.9.1'
    userGuideTask module('xhtmlrenderer:xhtmlrenderer:R8rc1') {
        dependency 'itext:itext:2.0.8@jar'
    }
    userGuideTask 'xslthl:xslthl:2.0.1@jar'

    userGuideStyleSheets 'docbook:docbook-xsl:1.75.2@zip'
}

srcDocsDir = file('src/docs')
userguideSrcDir = new File(srcDocsDir, 'userguide')
cssSrcDir = new File(srcDocsDir, 'css')
dslSrcDir = new File(srcDocsDir, 'dsl')
docsDir = file("$buildDir/docs")
userguideDir = new File(docsDir, 'userguide')
distDocsDir = new File(buildDir, 'distDocs')
samplesDir = file("$buildDir/samples")
docbookSrc = new File(project.buildDir, 'src')
samplesSrcDir = file('src/samples')

outputs = [:]
outputs.samples = files(samplesDir) {
    builtBy 'samples'
}
outputs.distDocs = files(distDocsDir) {
    builtBy 'distDocs'
}
outputs.docs = files(docsDir) {
    builtBy 'javadoc', 'groovydoc', 'userguide', 'dslHtml'
}


tasks.withType(Docbook2Xhtml) {
    dependsOn userguideStyleSheets
    classpath = configurations.userGuideTask
    stylesheetsDir = userguideStyleSheets.destinationDir
}
tasks.withType(UserGuideTransformTask) {
    classpath = configurations.userGuideTask
    dependsOn samples, dslDocbook
    snippetsDir = samples.snippetsDir
    linksFile = dslDocbook.linksFile
}
tasks.withType(AssembleDslDocTask) {
    classpath = configurations.userGuideTask
    classDocbookDir = dslSrcDir
}

task samples(type: ExtractSnippetsTask) {
    source samplesSrcDir
    exclude 'userguideOutput/**'
    exclude 'userguide/tutorial/antLoadfileResources/**'
    exclude '**/readme.xml'
    destDir = samplesDir
    snippetsDir = new File(buildDir, 'snippets')
    doLast {
        copy {
            from samplesSrcDir
            into samplesDir
            include 'userguide/tutorial/antLoadfileResources/**'
        }
    }
}

task userguideStyleSheets(type: Copy) {
    File stylesheetsDir = new File(srcDocsDir, 'stylesheets')
    into new File(buildDir, 'stylesheets')
    from(stylesheetsDir) {
        include '*.xsl'
    }
    from(cssSrcDir) {
        include '*.css'
    }
    from(zipTree(configurations.userGuideStyleSheets.singleFile)) {
        // Remove the prefix
        eachFile { fcd -> fcd.path = fcd.path.replaceFirst('^docbook-xsl-[0-9\\.]+/', '') }
    }
}

task samplesDocbook(type: AssembleSamplesDocTask) {
    source samplesSrcDir
    include '**/readme.xml'
    destFile = new File(docbookSrc, 'samplesList.xml')
}

task samplesDocs(type: Docbook2Xhtml, dependsOn: samplesDocbook) {
    source samplesDocbook.destFile
    destFile = new File(samples.destDir, 'readme.html')
    stylesheetName = 'standaloneHtml.xsl'
}

task dslMetaData(type: ExtractDslMetaDataTask) {  //TODO SF: parseSourceCode
    source { groovydoc.source }
    destFile = new File(docbookSrc, 'dsl-meta-data.bin')
}

task dslDocbook(type: AssembleDslDocTask, dependsOn: [dslMetaData]) {
    inputs.files fileTree(dir: dslSrcDir, includes: ['*.xml'])
    sourceFile = new File(dslSrcDir, 'dsl.xml')
    classMetaDataFile = dslMetaData.destFile
    pluginsMetaDataFile = new File(dslSrcDir, 'plugins.xml')
    destFile = new File(docbookSrc, 'dsl.xml')
    linksFile = new File(docbookSrc, 'api-links.bin')
}

task dslStandaloneDocbook(type: UserGuideTransformTask, dependsOn: [dslDocbook]) {
    inputs.files fileTree(dir: userguideSrcDir, includes: ['*.xml'])
    inputs.files fileTree(dir: docbookSrc, includes: ['*.xml'])
    sourceFile = dslDocbook.destFile
    destFile = new File(docbookSrc, 'dsl-standalone.xml')
    javadocUrl = '../javadoc'
    groovydocUrl = '../groovydoc'
    dsldocUrl = '.'
    websiteUrl = 'http://www.gradle.org'
}

task dslHtml(type: Docbook2Xhtml, dependsOn: dslStandaloneDocbook) {
    source dslStandaloneDocbook.destFile
    destDir = new File(docsDir, 'dsl')
    stylesheetName = 'dslHtml.xsl'
    resources = fileTree {
        from cssSrcDir
        include '*.css'
    } + fileTree {
        from dslSrcDir
        include '*.js'
    }
}

task userguideDocbook(type: UserGuideTransformTask, dependsOn: [samples, samplesDocbook]) {
    inputs.files fileTree(dir: userguideSrcDir, includes: ['*.xml'])
    inputs.files fileTree(dir: docbookSrc, includes: ['*.xml'])
    sourceFile = new File(userguideSrcDir, 'userguide.xml')
    destFile = new File(docbookSrc, 'userguide.xml')
    javadocUrl = '../javadoc'
    groovydocUrl = '../groovydoc'
    dsldocUrl = '../dsl'
    websiteUrl = 'http://www.gradle.org'
}

task remoteUserguideDocbook(type: UserGuideTransformTask, dependsOn: samples) {
    inputs.files fileTree(dir: userguideSrcDir, includes: ['*.xml'])
    inputs.files fileTree(dir: docbookSrc, includes: ['*.xml'])
    sourceFile = new File(userguideSrcDir, 'userguide.xml')
    destFile = new File(docbookSrc, 'remoteUserguide.xml')
    javadocUrl = project.version.javadocUrl
    groovydocUrl = project.version.groovydocUrl
    dsldocUrl = project.version.dsldocUrl
    websiteUrl = 'http://www.gradle.org'
}

task userguideHtml(type: Docbook2Xhtml, dependsOn: userguideDocbook) {
    source userguideDocbook.destFile
    destDir = userguideDir
    stylesheetName = 'userGuideHtml.xsl'
    resources = fileTree {
        from userguideSrcDir
        include 'img/*.png'
    }
    resources += fileTree {
        from cssSrcDir
        include '*.css'
    }
}

task userguideSingleHtml(type: Docbook2Xhtml, dependsOn: userguideDocbook) {
    source userguideDocbook.destFile
    destFile = new File(userguideDir, 'userguide_single.html')
    stylesheetName = 'userGuideSingleHtml.xsl'
    resources = fileTree {
        from userguideSrcDir
        include 'img/*.png'
    }
    resources += fileTree {
        from cssSrcDir
        include '*.css'
    }
}

task userguideXhtml(type: Docbook2Xhtml, dependsOn: remoteUserguideDocbook) {
    source remoteUserguideDocbook.destFile
    destFile = new File(buildDir, 'tmp/userguidePdf/userguidePdf.html')
    stylesheetName = 'userGuidePdf.xsl'
    resources = fileTree {
        from userguideSrcDir
        include 'img/*.png'
    }
    resources += fileTree {
        from cssSrcDir
        include '*.css'
    }
}

task userguidePdf(type: Xhtml2Pdf, dependsOn: userguideXhtml) {
    inputs.dir cssSrcDir
    sourceFile = userguideXhtml.destFile
    destFile = new File(userguideDir, 'userguide.pdf')
    classpath = configurations.userGuideTask
}

task javadoc(type: Javadoc) {
    group = 'documentation'
    options.encoding = 'utf-8'
    source groovyProjects().collect {project -> project.sourceSets.main.allJava }
    destinationDir = new File(docsDir, 'javadoc')
    classpath = files(groovyProjects().collect {project -> [project.sourceSets.main.compileClasspath, project.sourceSets.main.output] })
    include 'org/gradle/api/**'
    include 'org/gradle/*'
    include 'org/gradle/external/javadoc/**'
    include 'org/gradle/process/**'
    include 'org/gradle/plugins/**'
    include 'org/gradle/testfixtures/**'
    include 'org/gradle/tooling/**'
    exclude '**/internal/**'
    options.links("http://docs.oracle.com/javase/1.5.0/docs/api/", "http://groovy.codehaus.org/gapi/", "http://maven.apache.org/ref/2.2.1/maven-core/apidocs",
        "http://maven.apache.org/ref/2.2.1/maven-model/apidocs")
    doFirst {
        title = "Gradle API $version"
    }
}

task checkstyleApi(type: Checkstyle) {
    source javadoc.source
    configFile = file("$checkstyleConfigDir/checkstyle-api.xml")
    classpath = files()
    resultFile = file("$checkstyleResultsDir/checkstyle-api.xml")
}

//TODO SF - generates for java as well, rename to codedoc?
task groovydoc(type: Groovydoc) {
    group = 'documentation'
    source groovyProjects().collect {project -> project.sourceSets.main.groovy + project.sourceSets.main.java }
    destinationDir = new File(docsDir, 'groovydoc')
    classpath = javadoc.classpath
    includes = javadoc.includes
    excludes = javadoc.excludes
    doFirst {
        title = "Gradle API $version"
    }
    groovyClasspath = project(':core').configurations.groovy
}

task userguideFragmentSrc(type: UserGuideTransformTask, dependsOn: [userguideStyleSheets, samples]) {
    tags << 'standalone'
    sourceFile = new File(userguideSrcDir, 'installation.xml')
    destFile = new File(docbookSrc, 'installation.xml')
    javadocUrl = project.version.javadocUrl
    groovydocUrl = project.version.groovydocUrl
    dsldocUrl = project.version.dsldocUrl
    websiteUrl = 'http://www.gradle.org'
}

task distDocs(type: Docbook2Xhtml, dependsOn: userguideFragmentSrc) {
    source userguideFragmentSrc.destFile
    destFile = new File(distDocsDir, 'getting-started.html')
    stylesheetName = 'standaloneHtml.xsl'
}

task userguide {
    dependsOn userguideHtml, userguideSingleHtml, userguidePdf
    description = 'Generates the userguide'
    group = 'documentation'
}

task docs {
    dependsOn javadoc, groovydoc, userguide, distDocs, samplesDocs, dslHtml
    description = 'Generates all documentation'
    group = 'documentation'
}

task docsZip(type: Zip) {
    from project.outputs.docs
}


class Docbook2Xhtml extends SourceTask {
    @InputFiles
    FileCollection classpath

    @OutputFile @Optional
    File destFile

    @OutputDirectory @Optional
    File destDir

    @InputDirectory
    File stylesheetsDir

    String stylesheetName

    @InputFiles @Optional
    FileCollection resources

    @TaskAction
    def transform() {
        if (!((destFile != null) ^ (destDir != null))) {
            throw new InvalidUserDataException("Must specify exactly 1 of output file or dir.")
        }

        source.visit { FileVisitDetails fvd ->
            if (fvd.isDirectory()) {
                return
            }

            ant.java(classname: 'org.apache.xalan.xslt.Process', failonerror: true, fork: true) {
                jvmarg(value: '-Xmx256m')
                arg(value: '-in')
                arg(value: fvd.file)
                if (destFile) {
                    arg(value: '-out')
                    arg(value: destFile)
                } else {
                    arg(value: '-out')
                    File outFile = fvd.relativePath.replaceLastName(fvd.file.name.replaceAll('.xml$', '.html')).getFile(destDir)
                    outFile.parentFile.mkdirs()
                    arg(value: outFile)
                }
                arg(value: '-xsl')
                arg(value: new File(stylesheetsDir, stylesheetName))
                if (destDir) {
                    arg(line: "-param base.dir ${destDir}/")
                }
                sysproperty(key: 'xslthl.config', value: new File("$stylesheetsDir/highlighting/xslthl-config.xml").toURI())
                sysproperty(key: 'org.apache.xerces.xni.parser.XMLParserConfiguration', value: 'org.apache.xerces.parsers.XIncludeParserConfiguration')
                classpath {
                    path(path: classpath.asPath)
                    path(location: new File(stylesheetsDir, 'extensions/xalan27.jar'))
                }
            }
        }

        if (resources) {
            project.copy {
                into this.destDir ?: destFile.parentFile
                from resources
            }
        }
    }
}

class Xhtml2Pdf extends DefaultTask {
    @InputFile
    File sourceFile

    @OutputFile
    File destFile

    @InputFiles
    FileCollection classpath

    def Xhtml2Pdf() {
        onlyIf { !OperatingSystem.current().isWindows() }
    }

    @TaskAction
    def transform() {
        def uris = classpath.files.collect {it.toURI().toURL()}
        def classloader = new URLClassLoader(uris as URL[], getClass().classLoader)
        def renderer = classloader.loadClass('org.xhtmlrenderer.pdf.ITextRenderer').newInstance()
        renderer.setDocument(sourceFile)
        renderer.layout()
        destFile.withOutputStream {
            renderer.createPDF(it)
        }
    }
}
