/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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 groovy.text.markup.MarkupTemplateEngine
import groovy.text.markup.TemplateConfiguration
import org.gradle.internal.logging.ConsoleRenderer
import util.CssFilter
import util.JsFilter
import util.CheckLinks

plugins {
    id 'base'                  // common lifecycle tasks and artifact types
    id 'org.ajoberstar.grgit' version '5.0.0' // to publish website to asf-git branch
}

ext {
    grgitClass = org.ajoberstar.grgit.Grgit
}
ext.watchmode = project.hasProperty('watchmode')?project.getProperty('watchmode'):'false'
// a collection of links which have either been validated or are dummy links
ext.excludeFromChecks = [
        'http://issues.apache.org/jira',
        'https://issues.apache.org/jira',
        'target.html',
        'foo.html',
        'http://www.acme.com/cars',
        'http://localhost:8080/groovy/hello.groovy'
]

def commitedChanges = false
def gitboxUrl = project.findProperty('gitPublishRemote') ?: 'https://gitbox.apache.org/repos/asf/groovy-dev-site.git'
def stagingDevSite = "$project.buildDir/staging-dev-site/"
def generatedDevSite = "$project.buildDir/site/"

task copyAssets(type:Copy) {
    from file('../site/src/site/assets')
    into file("$buildDir/site")
    filesMatching('**/*.css') { f->
        if (!f.name.contains('.min.')) {
            filter(CssFilter)
        }
    }
    filesMatching('**/*.js') { f->
        if (!f.name.contains('.min.')) {
            filter(JsFilter)
        }
    }
}

task copyWikiAssets(type:Copy) {
    from file('../site/src/site/wiki/img')
    into file("$buildDir/site/wiki/img")
}

task copyBlogAssets(type:Copy) {
    from file('../site/src/site/blog/img')
    into file("$buildDir/site/blog/img")
}

task generateSite(type:JavaExec) {

    description = 'Generates the Groovy Dev Website'
    dependsOn copyAssets
    dependsOn copyWikiAssets
    dependsOn copyBlogAssets
    ext.sources = file('../site/src/site')
    ext.outputDir = file("$buildDir/site")

    inputs.files fileTree(sources)
    outputs.files fileTree(outputDir)

    classpath = project(':generator').sourceSets.main.runtimeClasspath
    main = 'generator.SiteGenerator'
    args = [sources, outputDir, 'sitemap-dev.groovy', project.watchmode]
    systemProperties.docs_baseurl = System.getProperty('docs_baseurl')
}

task checkDeadLinks(dependsOn: generateSite) {
    description = "Checks for dead links in the generated Groovy website"

    ext.outputDir = file("$buildDir/reports")
    ext.reportFile = file("$outputDir/deadlinks.html")

    inputs.files fileTree(generateSite.outputDir)
    outputs.file reportFile

    doLast {
        def baseDir = generateSite.outputDir
        def checkLinks = new CheckLinks(baseDir: baseDir,
                excludeFromChecks: excludeFromChecks,
                logger: logger)

        file(baseDir).eachFileRecurse {
            if (it.name.endsWith('.html')) {
                checkLinks.checkPage(it)
            }
        }

        outputDir.mkdirs()
        def tplConf = new TemplateConfiguration()
        tplConf.with {
            autoIndent = true
            autoNewLine = true
        }
        def tplEngine = new MarkupTemplateEngine(this.class.classLoader, file('../site/gradle/templates'), tplConf)

        def report = tplEngine.createTemplateByPath("deadlinks.groovy").make(deadLinks: checkLinks.deadLinks).toString()

        reportFile.write(report, 'utf-8')
        def reportURL = new ConsoleRenderer().asClickableFileUrl(reportFile)
        logger.lifecycle "Dead links report written at $reportURL"
    }
}

task webzip(type:Zip, dependsOn: checkDeadLinks) {
    description = "Creates a zip with the generated website and the deadlink report"
    destinationDir = file("$buildDir/distributions")

    baseName = 'groovy'
    appendix = 'website'
    from(generateSite.outputDir) {
        into 'site'
    }
    from (checkDeadLinks.outputDir) {
        into 'reports'
    }
}

// Creates a new commit on asf-site branch
task commitWebsite(dependsOn: webzip) {
    doLast {
        assert grgitClass : "git repository not found?"
        assert file("$generatedDevSite/index.html").exists()
        // get the latest commit on master
        def gitin = grgitClass.open(dir: rootProject.projectDir)
        def latestCommit = gitin.log(maxCommits: 1)[0].abbreviatedId

        def gitout
        if (project.hasProperty('skipClone')) {
            gitout = grgitClass.open(dir: stagingDevSite)
        } else {
            println "Cloning $gitboxUrl to $stagingDevSite. This may take a few minutes ..."
            gitout = grgitClass.clone(dir: stagingDevSite, uri: gitboxUrl)
        }

        gitout.checkout(branch: 'asf-site')

        // Delete the previous content. These are asf-site branch paths.
        gitout.remove(patterns: ['.'])
        fileTree(stagingDevSite).exclude('.git', '.asf.yaml').visit { delete it.file }
        assert !file("${stagingDevSite}/index.html").exists()

        // Copy the built content and add it.
        copy {
            from generatedDevSite
            into stagingDevSite
        }
        assert file("${stagingDevSite}/index.html").exists()
        gitout.add(patterns: ['.'])

        if (!gitout.status().staged.getAllChanges()) {
            println 'No changes to commit'
        } else {
            println 'Creating commit for changes'
            def now = new Date().format('yyyy/MM/dd HH:mm:ss')
            String message = "$now: Generated dev website from groovy-website@$latestCommit"
            commitedChanges = true
            gitout.commit(message: message)
        }
    }
}

/*
 * Pushes the asf-site branch commits.
 *
 * This requires write access to the asf-site branch and can be run on
 * Jenkins executors with the git-websites label.
 *
 * For more details on publishing, see:
 * https://www.apache.org/dev/project-site.html
 * https://github.com/apache/infrastructure-puppet/blob/deployment/modules/gitwcsub/files/config/gitwcsub.cfg
 *
 * You can test this locally with a forked repository by manually adding the
 * website-publish remote pointing to your forked repository, for example:
 *   git remote add website-publish git@github.com:${GITUSER}/groovy-website.git
 * because the remote is only added if it doesn't exist. The remote needs
 * to be added before every execution of the publishing.
 */
task publishWebsite(dependsOn: commitWebsite) {
    doLast {
        assert grgit : "git repository not found?"

        def git = grgit.open(dir: stagingDevSite)
        git.checkout(branch: 'asf-site')
        if (!commitedChanges) {
            println 'No changes to push'
            return
        }

        // Because git.push() fails to authenticate, run git push directly.
        def cmd = 'git push origin asf-site'
        exec {
            workingDir stagingDevSite
            if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
                executable 'cmd.exe'
                args '/c', cmd
            } else {
                executable 'sh'
                args '-c', cmd
            }
        }
    }
}
