import javax.inject.Inject

/*
 *  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.
 */
plugins {
    id "geb.groovy-module"
    id "geb.manuals"
    id "geb.spock-2-module"
    id 'org.ajoberstar.grgit' version '5.3.0' // to publish website to asf-git branch
}
repositories {
    mavenCentral()
}

configurations {
    currentManual
    distribution
}

manuals {
    include(
        "2.1", "2.2", "2.3", "2.3.1", "3.0", "3.0.1", "3.1", "3.2", "3.3", "3.4", "3.4.1",
        "4.0", "4.1", "5.0", "5.1", "6.0", "7.0", "8.0.0"
    )
    currentManual.from(configurations.currentManual)
    indexTemplate.set(file("templates/main.html"))
}

dependencies {
    testImplementation libs.spockCoreGroovy25
    testImplementation libs.jsoup
    testImplementation libs.gebSpockGroovy25
    testImplementation libs.htmlUnitDriver
    currentManual project(path: ":doc:manual", configuration: "manual")
    testImplementation(platform(libs.micronaut.bom))
    testCompileOnly(libs.micronaut.inject.groovy)
    testImplementation(libs.micronaut.runtime.groovy)
    testImplementation(libs.micronaut.http.client)
    testImplementation(libs.micronaut.http.server.netty)
    testImplementation(libs.logback.classic)
}

tasks.register("generateResources", Sync) {
    group = "website"
    description = "copy the generated manuals from build/manuls src/main/resource/public/manuals"

    from(tasks.named("gatherManuals")) {
        into 'public/manual'
    }
    from(tasks.named("generateIndex"))
    into 'src/main/resources'
}

tasks.generateIndex {
    group = "website"
    description = "generate an index.html with the template templates/main.html and the manuals configuration extension"
    inputs.files(file("templates/main.html"))
}

tasks.register("replaceAnalyticsWithMatomo") {
    group = "website"
    description = "Replace Google Analytics with Matomo in manuals"
    def rootDir = project.rootDir
    def projectDir = project.projectDir
    dependsOn("generateResources")
    doLast {
        File baseDir = file("${projectDir}/src/main/resources/public/manual")
        baseDir.eachFileRecurse(groovy.io.FileType.FILES) { file ->
            if (file.name == 'index.html') {
                String html = file.text
                String ga = '''
<script type="text/javascript">

    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-15031038-2']);
    _gaq.push(['_trackPageview', location.pathname + location.hash]);

    window.onhashchange = function() {
        _gaq.push(['_trackPageview', location.pathname + location.hash]);
    };

    (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
    })();

</script>
'''
                String matomo = new File("${rootDir}/doc/manual/src/docs/asciidoc/docinfo.html").text
                html = html.replace(ga, matomo)
                List<String> fontAwesomeLinks = [
                    'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.min.css',
                    'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css'
                ]
                for (String link : fontAwesomeLinks) {
                    html = html.replace(link, '../../css/font-awesome.min.css')
                }
                html = html.replace('https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css',
                    '../../css/prettify.min.css')
                html = html.replace('https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js',
                    '../../js/prettify.min.js')
                html = html.replace('http://markmail.org/thread/bu3g56oxz2uqzq43',
                    'https://web.archive.org/web/20120211213811/http://markmail.org/thread/bu3g56oxz2uqzq43')
                file.text = html
            } else if (file.name == 'style.css') {
                String html = file.text
                html = html.replace('@import url(http://fonts.googleapis.com/css?family=Roboto+Slab|Roboto|Source+Code+Pro:500,700);',
                    '@import url(../../../css/ManualFonts.css);')
                file.text = html
            }
        }
    }
}

tasks.register("placeIndex", Copy) {
    group = "website"
    description = "move the generated src/main/resources/index.html to src/main/resources/public/index.html and deletes it from src/main/resources"
    from 'src/main/resources/index.html'
    into 'src/main/resources/public'
    dependsOn("generateResources", "generateIndex")
    doLast {
        delete 'src/main/resources/index.html'
    }
}

tasks.register("copyPublicResources", Copy) {
    group = "website"
    from 'public'
    into 'src/main/resources/public'
    mustRunAfter("generateResources", "generateIndex")
}

tasks.register("generatePublic") {
    group = "website"
    dependsOn("copyPublicResources", "generateResources", "placeIndex", "replaceAnalyticsWithMatomo")
}
processResources.dependsOn("generatePublic")
test.dependsOn("generatePublic")
rat.dependsOn("generatePublic")

tasks.register("deleteResources", Delete) {
    group = "website"
    delete 'src/main/resources'
}
clean.dependsOn("deleteResources")

tasks.register("generateDist", Copy) {
    description = "copy the public static website to build/dist"
    group = "website"
    from 'src/main/resources/public'
    into 'build/dist'
    dependsOn("generatePublic")
}
build.dependsOn("generatePublic")
build.dependsOn("generateDist")

def grgitClass = org.ajoberstar.grgit.Grgit
def commitedChanges = false
def gitboxUrl = project.findProperty('gitPublishRemote') ?: 'https://gitbox.apache.org/repos/asf/groovy-dev-site.git'
def stagingDevSite = project.layout.buildDirectory.dir('staging-dev-site').get().asFile
def gebSite = project.layout.buildDirectory.dir('dist').get().asFile
def gebTarget = new File(stagingDevSite, 'geb')

// Creates a new commit on asf-site branch
tasks.register('commitWebsite') {
    dependsOn generateDist
    def skipClone = project.hasProperty('skipClone')
    doLast {
        assert grgitClass : "git repository not found?"
        assert file("$gebSite/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 (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: ['geb'])
        fileTree(gebTarget).visit { delete it.file }
        assert !file("${gebTarget}/index.html").exists()

        // Copy the built content and add it.
        copy {
            from gebSite
            into gebTarget
        }
        assert file("${gebTarget}/index.html").exists()
        gitout.add(patterns: ['geb'])
        def removedFiles = gitout.status().unstaged.getRemoved()
        if (removedFiles) {
            gitout.remove(patterns: removedFiles)
        }

        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: Updated geb directory of dev website from geb@$latestCommit"
            commitedChanges = true
            gitout.commit(message: message)
        }
    }
}

interface InjectedExecOps {
    @Inject //@javax.inject.Inject
    ExecOperations getExecOps()
}

/*
 * 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.
 */
tasks.register('publishWebsite') {
    dependsOn commitWebsite
    def injected = project.objects.newInstance(InjectedExecOps)
    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'
        def isWindows = System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')
        injected.execOps.exec {
            workingDir stagingDevSite
            if (isWindows) {
                commandLine 'cmd.exe', '/c', cmd
            } else {
                commandLine 'sh', '-c', cmd
            }
        }
    }
}
