/*
 * 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 com.github.vlsi.gradle.crlf.CrLfSpec
import com.github.vlsi.gradle.crlf.LineEndings
import com.github.vlsi.gradle.git.FindGitAttributes
import com.github.vlsi.gradle.git.dsl.gitignore
import com.github.vlsi.gradle.license.GatherLicenseTask
import com.github.vlsi.gradle.license.api.SpdxLicense
import com.github.vlsi.gradle.release.Apache2LicenseRenderer
import com.github.vlsi.gradle.release.ArtifactType
import com.github.vlsi.gradle.release.ReleaseExtension
import com.github.vlsi.gradle.release.ReleaseParams
import com.github.vlsi.gradle.release.dsl.dependencyLicenses
import com.github.vlsi.gradle.release.dsl.licensesCopySpec

plugins {
    id("com.github.vlsi.stage-vote-release")
}

rootProject.configure<ReleaseExtension> {
    voteText.set { it.voteTextGen() }
}

fun ReleaseParams.voteTextGen(): String = """
Subject: [VOTE] Release $componentName $version (release candidate $rc)

Hi all,

I have created a build for $componentName $version, release
candidate $rc.

Thanks to everyone who has contributed to this release.

You can read the release notes here:
https://github.com/apache/calcite/blob/$tag/site/_docs/history.md

The commit to be voted upon:
https://gitbox.apache.org/repos/asf?p=calcite.git;a=commit;h=$gitSha

Its hash is $gitSha

Tag:
$sourceCodeTagUrl

The artifacts to be voted on are located here:
$svnStagingUri
(revision $svnStagingRevision)

The hashes of the artifacts are as follows:
${artifacts.joinToString(System.lineSeparator()) { it.sha512 + System.lineSeparator() + "*" + it.name }}

A staged Maven repository is available for review at:
$nexusRepositoryUri/org/apache/$tlpUrl/

Release artifacts are signed with the following key:
https://people.apache.org/keys/committer/$committerId.asc
https://www.apache.org/dist/$tlpUrl/KEYS

To create the jars and test $componentName: "gradle build"
(requires an appropriate Gradle/JDK installation)

Please vote on releasing this package as $componentName $version.

The vote is open for the next 72 hours and passes if a majority of at
least three +1 PMC votes are cast.

[ ] +1 Release this package as Apache Calcite $version
[ ]  0 I don't feel strongly about it, but I'm okay with the release
[ ] -1 Do not release this package because...

Here is my vote:

+1 (binding)
""".trimIndent()

val distributionGroup = "distribution"
val baseFolder = "apache-calcite-${rootProject.version}"

// This task scans the project for gitignore / gitattributes, and that is reused for building
// source/binary artifacts with the appropriate eol/executable file flags
val gitProps by tasks.registering(FindGitAttributes::class) {
    // Scanning for .gitignore and .gitattributes files in a task avoids doing that
    // when distribution build is not required (e.g. code is just compiled)
    root.set(rootDir)
}

val getLicenses by tasks.registering(GatherLicenseTask::class) {
    extraLicenseDir.set(file("$rootDir/src/main/config/licenses"))
    // Parts of the web site generated by Jekyll (http://jekyllrb.com/)
    addDependency(":jekyll:", SpdxLicense.MIT)
    addDependency("font-awesome:font-awesome-code:4.2.0", SpdxLicense.MIT)
    // git.io/normalize
    addDependency(":normalize:3.0.2", SpdxLicense.MIT)
    // Gridism: A simple, responsive, and handy CSS grid by @cobyism
    // https://github.com/cobyism/gridism
    addDependency(":gridsim:", SpdxLicense.MIT)
    addDependency("cobyism:html5shiv:3.7.2", SpdxLicense.MIT)
    addDependency(":respond:1.4.2", SpdxLicense.MIT)
}

val license by tasks.registering(Apache2LicenseRenderer::class) {
    group = LifecycleBasePlugin.BUILD_GROUP
    description = "Generates LICENSE file for the source distribution"
    artifactType.set(ArtifactType.SOURCE)
    metadata.from(getLicenses)
    failOnIncompatibleLicense.set(false)
}

val licenseFiles = licensesCopySpec(license)

fun CopySpec.excludeLicenseFromSourceRelease() {
    // Source release has "/licenses" folder with licenses for third-party dependencies
    // It is populated by "dependencyLicenses" above,
    // so we ignore the folder when building source releases
    exclude("licenses/**")
    exclude("LICENSE")
}

fun CopySpec.excludeGradleWrapperFromSourceRelease() {
    // Source distributions must not include binary files (see LEGAL-288).
    // The Gradle wrapper requires gradle-wrapper.jar, so exclude the whole
    // wrapper. Users must install Gradle manually.
    exclude("gradlew")
    exclude("gradlew.bat")
    exclude("gradle/wrapper/**")
}

fun CopySpec.excludeCategoryBLicensedWorksFromSourceRelease() {
    // The source distribution contains "font-awesome:fonts" which is licensed as
    // http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License).
    //
    // OFL 1.1 is "category B" (see LEGAL-112).
    //
    // According to
    // https://www.apache.org/legal/resolved.html#binary-only-inclusion-condition,
    // the source code can not include Category B licensed works.

    // We need to remove "web and desktop font files".
    exclude("site/fonts/**")
}

fun CrLfSpec.sourceLayout() = copySpec {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    gitattributes(gitProps)
    into("$baseFolder-src") {
        // Note: license content is taken from "/build/..", so gitignore should not be used
        // Note: this is a "license + third-party licenses", not just Apache-2.0
        dependencyLicenses(licenseFiles)
        // Include all the source files
        from(rootDir) {
            gitignore(gitProps)
            excludeLicenseFromSourceRelease()
            excludeGradleWrapperFromSourceRelease()
            excludeCategoryBLicensedWorksFromSourceRelease()
        }
    }
}

for (archive in listOf(Tar::class)) {
    val taskName = "dist${archive.simpleName}"
    val archiveTask = tasks.register(taskName, archive) {
        val eol = LineEndings.LF
        group = distributionGroup
        description = "Creates source distribution with $eol line endings for text files"
        if (this is Tar) {
            compression = Compression.GZIP
            archiveExtension.set("tar.gz")
        }
        // Gradle does not track "filters" as archive/copy task dependencies,
        // So a mere change of a file attribute won't trigger re-execution of a task
        // So we add a custom property to re-execute the task in case attributes change
        inputs.property("gitproperties", gitProps.map { it.props.attrs.toString() })

        // Gradle defaults to the following pattern:
        // [baseName]-[appendix]-[version]-[classifier].[extension]
        archiveBaseName.set("apache-calcite")
        archiveClassifier.set("src")

        CrLfSpec(eol).run {
            wa1191SetInputs(gitProps)
            with(sourceLayout())
        }
        doLast {
            logger.lifecycle("Source distribution is created: ${archiveFile.get().asFile}")
        }
    }
    releaseArtifacts {
        artifact(archiveTask)
    }
}
