buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath('com.uwyn:jhighlight:1.0') {
            exclude module: "servlet-api"
        }
    }
}

import org.jsoup.nodes.Element
import org.jsoup.nodes.TextNode
import org.jsoup.select.Elements
import com.uwyn.jhighlight.renderer.XhtmlRendererFactory

def baseStyleFile = project.file("$project.cssFiles.dir/base.css")
def releaseNotesStyleFile = project.file("$project.cssFiles.dir/release-notes.css")
def scriptFile = project.file("src/docs/release/content/script.js")
def incubatingMarker = " (i)"

inputs.files([project.cssFiles, baseStyleFile, releaseNotesStyleFile, project.configurations.jquery, project.configurations.jqueryTipTip, scriptFile])

transformDocument {
    outputSettings().indentAmount(2).prettyPrint(true)

    prependChild(new org.jsoup.nodes.DocumentType("html", "", "", ""))

    head().
            append("<meta charset='utf-8'>").
            append("<title>Gradle @version@ Release Notes</title>")

    head().append("<style>p{}</style>").children().last().childNode(0).attr("data", baseStyleFile.text + releaseNotesStyleFile.text)

    [project.configurations.jquery.singleFile, project.configurations.jqueryTipTip.singleFile, scriptFile].each {
        head().append("<script type='text/javascript'>1;</script>").children().last().childNode(0).attr("data", it.text)
    }
}

// wrap each h2 section in section.topic
transformDocument {
    def heading = body().select("h2").first()
    def inSection = [heading]
    Element next = heading.nextElementSibling()
    while (true) {
        if (next == null || next.tagName() == "h2") {
            def section = heading.before("<section class='topic'/>").previousElementSibling()
            Elements inSectionElements = new Elements(inSection)
            section.html(inSectionElements.outerHtml())
            inSectionElements.remove()

            if (next == null) {
                break
            } else {
                inSection = [next]
                heading = next
            }
        } else {
            inSection << next
        }

        next = next.nextElementSibling()
    }
}

// replace the incubating marker in h3 with class
transformDocument {
    for (heading in body().select(".topic").select("h3")) {
        def textNode = heading.childNodes().last()
        if (textNode instanceof TextNode && textNode.text().endsWith(incubatingMarker)) {
            textNode.text(textNode.text() - incubatingMarker)
            heading.addClass("incubating")
        }
    }
}

// wrap all content after the first element after a h3 (up to the next same level heading)
// in a section.major-detail block
transformDocument {
    for (heading in body().select(".topic").select("h3")) {
        def detail = []

        Element next = heading.nextElementSibling()
        while (next != null && next.tagName() != "h4") {
            next = next.nextElementSibling()
        }

        while (true) {
            if (next == null || next.tagName() ==~ /h[123]/) {
                break
            }
            detail << next
            next = next.nextElementSibling()
        }

        if (detail) {
            def section = detail.first().before("<section class='major-detail'/>").previousElementSibling()
            Elements detailElements = new Elements(detail)
            section.html(detailElements.outerHtml())
            detailElements.remove()
        }
    }
}

// wrap all content after a h4 until the next heading in a section.minor-detail
transformDocument {
    for (heading in body().select("h4")) {
        def detail = []
        Element next = heading.nextElementSibling()
        while (true) {
            if (next == null || next.tagName() ==~ /h[1234]/) {
                break
            }
            detail << next
            next = next.nextElementSibling()
        }

        if (detail) {
            def section = detail.first().before("<section class='minor-detail'/>").previousElementSibling()
            Elements detailElements = new Elements(detail)
            section.html(detailElements.outerHtml())
            detailElements.remove()
        }
    }
}

// add anchors for all of the headings
transformDocument {
    for (heading in body().select("h2,h3")) {
        def anchorName = heading.text().toLowerCase().replaceAll(' ', '-')
        heading.attr("id", anchorName)
    }
}

// Add the TOC
transformDocument {
    def tocSection = body().select("section.topic").first().before("<section class='table-of-contents'/>").previousElementSibling()
    tocSection.append("<h2>Table Of Contents</h2>")
    def toc = tocSection.append("<ul class='toc'/>").children().last()

    for (topic in body().select(".topic")) {
        def topicHeading = topic.select("h2").first()
        def name = topicHeading.text()
        def anchor = topicHeading.attr("id")

        toc.append("<li><a/></li>").children().last().select("a").first().text(name).attr("href", "#$anchor")

        def subs = topic.select("h3")
        if (subs) {
            def sublist = toc.children().last().append("<ul class='toc-sub'/>").children().last()
            subs.each {
                def subName = it.html()
                def subAnchorName = it.attr("id")
                sublist.append("<li><a/></li>").children().last().select("a").first().html(subName).attr("href", "#$subAnchorName")
            }
        }
    }
}

// add a tooltip to all h3 marked incubating
transformDocument {
    for (heading in body().select(".incubating").select("h3")) {
        heading.append(" <a class='incubating-marker' href='userguide/feature_lifecycle.html' title='“incubating” features are not yet guaranteed to be backwards compatible<br />(click for more information)'>incubating feature</a>")
    }
}

// Add the heading
transformDocument {
    body().prepend("<h3 class='releaseinfo'>Version @version@</h3>")
    body().prepend("<h1>Gradle Release Notes</h1>")
}

// Add the footer
transformDocument {
    def footer = body().append("<section class='footer'/>").children().last()
    footer.html("Gradle @version@ Release Notes<br />")
}

// Syntax highlighting
transformDocument {
    body().select("code").each { code ->
        def parent = code.parent()
        if (parent.tagName() == "pre") {
            def text = code.text()
            def input = new ByteArrayInputStream(code.text().getBytes("utf-8"))
            def renderer = XhtmlRendererFactory.getRenderer("groovy")
            def out = new ByteArrayOutputStream()
            renderer.highlight("test", input, out, "utf-8", true)
            code.html(new String(out.toByteArray(), "utf-8"))
            code.select("br").remove()
            code.childNodes().findAll { it.nodeName().equals("#comment") }*.remove()
            code.html(code.html().trim())
            parent.addClass("code")
        }
    }
}

// Terminal styling
transformDocument {
    body().select("tt").each { tt ->
        def parent = tt.parent()
        if (parent.tagName() == "pre") {
            tt.select("br").remove()
            tt.childNodes().findAll { it.nodeName().equals("#comment") }*.remove()
            tt.html(tt.html().trim())
            parent.addClass("tt")
        }
    }
}

// Wrap the page in a text container to get the margins
transformDocument {
    def bodyContent = body().children().remove()
    body().prepend("<div class='text-container'/>")
    body().children()[0].html(bodyContent.outerHtml())
}

// Turn Gradle issue numbers into issue links
transformDocument {
    def rewritten = body().html().replaceAll(~/GRADLE-\d+/) {
        "<a href='https://issues.gradle.org/browse/${it}'>${it}</a>"
    }
    body().html(rewritten)
}
