/*
 *  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
 *
 *    https://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.
 */

buildscript {
    repositories {
        maven { url "https://repo.grails.org/grails/restricted" }
        maven { url "https://plugins.gradle.org/m2/" }
    }
    dependencies {
        classpath "org.codehaus.groovy.modules.http-builder:http-builder:0.7.2"
        classpath "org.apache.grails:grails-gradle-plugins:$grailsGradlePluginVersion"
        classpath "org.asciidoctor:asciidoctor-gradle-jvm:4.0.2"
        classpath "com.github.erdi:webdriver-binaries-gradle-plugin:3.2"
    }
}

group "org.apache.grails"
version project.projectVersion
println "GORM VERSION = ${project.datastoreVersion}"

ext {
    isCiBuild = System.getenv().get("TRAVIS") == 'true' || System.getenv().get("CI") as Boolean
    hibernatePluginVersion = project.hibernateDatastoreVersion
    
    isCiBuild = project.hasProperty("isCiBuild")
    isBuildSnapshot = version.endsWith("-SNAPSHOT")
    isReleaseVersion = !isBuildSnapshot
    nexusUsername = System.getenv("SONATYPE_USERNAME") ?: project.hasProperty("sonatypeOssUsername") ? project.sonatypeOssUsername : ''
    nexusPassword = System.getenv("SONATYPE_PASSWORD") ?: project.hasProperty("sonatypeOssPassword") ? project.sonatypeOssPassword : ''
}

ext."signing.keyId" = project.hasProperty("signing.keyId") ? project.getProperty('signing.keyId') : System.getenv('SIGNING_KEY')
ext."signing.password" = project.hasProperty("signing.password") ? project.getProperty('signing.password') : System.getenv('SIGNING_PASSPHRASE')
ext."signing.secretKeyRingFile" = project.hasProperty("signing.secretKeyRingFile") ? project.getProperty('signing.secretKeyRingFile') : "${System.properties['user.home']}${File.separator}.gnupg${File.separator}secring.gpg"

if (isReleaseVersion) {
    apply plugin: 'maven-publish'
    apply plugin: "io.github.gradle-nexus.publish-plugin"

    nexusPublishing {
        repositories {
            sonatype {
                def ossUser = System.getenv("SONATYPE_USERNAME") ?: project.hasProperty("sonatypeOssUsername") ? project.sonatypeOssUsername : ''
                def ossPass = System.getenv("SONATYPE_PASSWORD") ?: project.hasProperty("sonatypeOssPassword") ? project.sonatypeOssPassword : ''
                def ossStagingProfileId = System.getenv("SONATYPE_STAGING_PROFILE_ID") ?: project.hasProperty("sonatypeOssStagingProfileId") ? project.sonatypeOssStagingProfileId : ''
                nexusUrl = uri("https://s01.oss.sonatype.org/service/local/")
                username = ossUser
                password = ossPass
                stagingProfileId = ossStagingProfileId
            }
        }
    }
}

subprojects { subproject ->

    ext['gorm.version'] = datastoreVersion
    ext['gorm.hibernate5.version'] = hibernateDatastoreVersion
    ext['h2.version'] = h2Version
    ext['jetty.version'] = subproject.jettyVersion
    ext['spock.version'] = spockVersion
    ext['junit-jupiter.version'] = junitJupiterVersion

    repositories {
        mavenLocal()
        maven { url "https://repo.grails.org/grails/restricted" }
    }

    configurations.all {
        resolutionStrategy {
            cacheDynamicVersionsFor 0, 'hours'
            cacheChangingModulesFor 0, 'hours'
        }
    }

    boolean usesGeb = ["grails3-neo4j", "grails3-neo4j-hibernate"].any { projectName -> subproject.name.contains(projectName) }
    boolean isPluginProject = subproject.name.endsWith("-plugin") && subproject.name.startsWith("grails")
    boolean isGrails3PluginProject = subproject.name.endsWith("-plugin")
    boolean isExample = subproject.name.startsWith("examples-")

    if (isExample) {
        boolean isGrails3Example = subproject.name.startsWith("examples-grails3")
        apply plugin: 'groovy'

        if (isGrails3Example) {
            apply plugin: 'org.apache.grails.gradle.grails-web'
            apply plugin:"org.apache.grails.gradle.grails-gsp"

            if (usesGeb) {
                apply plugin:"com.github.erdi.webdriver-binaries"
            }
        } else if (subproject.name == "examples-test-data-service") {
            apply plugin: 'org.apache.grails.gradle.grails-web'
            apply plugin: 'org.apache.grails.gradle.grails-gson'
        }

        //TODO: Use bom instead
//        configurations.all {
//            resolutionStrategy.eachDependency { DependencyResolveDetails details ->
//                if (details.requested.group == 'org.codehaus.groovy' && details.requested.name.startsWith('groovy')) {
//                    details.useVersion(groovyVersion)
//                } else if (details.requested.group == 'org.springframework') {
//                    details.useVersion(springVersion)
//                } else if (details.requested.group == 'org.springframework.boot') {
//                    details.useVersion(springBootVersion)
//                } else if (details.requested.name in ['grails-testing-support', 'grails-web-testing-support', 'grails-testing-support-datamapping']) {
//                    details.useVersion(testingSupportVersion)
//                }
//            }
//        }

        dependencies {
            testImplementation "org.hibernate:hibernate-validator:$hibernateValidatorVersion"
            testImplementation "org.codehaus.groovy:groovy-test-junit5"
            testImplementation "org.spockframework:spock-core:$spockVersion", { transitive = false }
            testImplementation "org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion"
            testImplementation "org.junit.platform:junit-platform-runner:$junitPlatformVersion"
            testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion"
        }

        tasks.withType(Test) {
            useJUnitPlatform()
            testLogging {
                showStandardStreams = true
                exceptionFormat = 'full'
            }
        }

        tasks.withType(Jar).configureEach {
            duplicatesStrategy = DuplicatesStrategy.INCLUDE
        }

        return
    }

    ext {
        projectInfo = new PublishingConvention(subproject)
        pomInfo = {
            delegate.name projectInfo.projectName
            delegate.description projectInfo.projectDescription
            delegate.url projectInfo.projectURL

            delegate.licenses {
                delegate.license {
                    delegate.name 'The Apache Software License, Version 2.0'
                    delegate.url 'https://www.apache.org/licenses/LICENSE-2.0.txt'
                    delegate.distribution 'repo'
                }
            }

            delegate.scm {
                delegate.url projectInfo.projectVcsUrl
                delegate.connection projectInfo.projectVcsUrl
                delegate.developerConnection projectInfo.projectVcsUrl
            }

            delegate.developers {
                delegate.developer {
                    delegate.id 'graemerocher'
                    delegate.name 'Graeme Rocher'
                }
                delegate.developer {
                    delegate.id 'jeffscottbrown'
                    delegate.name 'Jeff Brown'
                }
                delegate.developer {
                    delegate.id 'burtbeckwith'
                    delegate.name 'Burt Beckwith'
                }
            }
        }         
    }
       
    if (isPluginProject) {
        group "org.apache.grails"
        version( rootProject.version )
    } else {
        group "org.apache.grails.data"
        version rootProject.version
    }

    if(subproject.name == 'docs') {
        return
    }

    apply plugin: "java-library"
    apply plugin: 'maven-publish'
    apply plugin: 'signing'

    if(isGrails3PluginProject) {
        apply plugin: 'org.apache.grails.gradle.grails-plugin'
    } else {
        apply plugin:"groovy"
    }

    sourceCompatibility = "1.11"
    targetCompatibility = "1.11"

    java {
        withJavadocJar()
        withSourcesJar()
    }

    configurations.all {
        resolutionStrategy.eachDependency { DependencyResolveDetails details ->
            def dependencyName = details.requested.name
            if (details.requested.group == 'org.apache.grails.data' &&
                    details.requested.name in ['grails-datastore-core',
                                               'grails-datastore-async',
                                               'grails-datamapping-core',
                                               'grails-datamapping-async',
                                               'grails-datamapping-rx',
                                               'grails-datamapping-support',
                                               'grails-datamapping-tck-tests',
                                               'grails-datamapping-tck-base',
                                               'grails-datamapping-tck-domains',
                                               'grails-datamapping-core-test',
                                               'grails-datamapping-validation',
                                               'grails-datastore-web']
            ) {
                details.useVersion(datastoreVersion)
            } else if(details.requested.group == 'org.springframework') {
                details.useVersion(springVersion)
            } else if (details.requested.group == 'org.springframework.boot') {
                details.useVersion(springBootVersion)
            }
        }
    }


    dependencies {
        api "org.codehaus.groovy:groovy"
        testImplementation "org.codehaus.groovy:groovy-test-junit5"
        testImplementation "org.spockframework:spock-core:$spockVersion", { transitive = false }
        testImplementation "org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion"
        testImplementation "org.junit.platform:junit-platform-runner:$junitPlatformVersion"
        testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion"
    }

    tasks.withType(Test) {
        configure {
            retry {
                maxRetries = 2
                maxFailures = 20
                failOnPassedAfterRetry = true
            }
        }
    }

    publishing {

        if (isBuildSnapshot) {
            repositories {
                maven {
                    credentials {
                        def u = System.getenv("ARTIFACTORY_USERNAME") ?: subproject.hasProperty("artifactoryPublishUsername") ? subproject.artifactoryPublishUsername : ''
                        def p = System.getenv("ARTIFACTORY_PASSWORD") ?: subproject.hasProperty("artifactoryPublishPassword") ? subproject.artifactoryPublishPassword : ''
                        username = u
                        password = p
                    }
                    if (isGrails3PluginProject) {
                        url "https://repo.grails.org/grails/plugins3-snapshots-local"
                    } else {
                        url "https://repo.grails.org/grails/libs-snapshots-local"
                    }
                }
            }
        }

        publications {
            maven(MavenPublication) {

                pom {
                    name = projectInfo.projectName
                    description = projectInfo.projectDescription
                    url = projectInfo.projectURL

                    licenses {
                        license {
                            name = 'The Apache Software License, Version 2.0'
                            url = 'https://www.apache.org/licenses/LICENSE-2.0.txt'
                            distribution = 'repo'
                        }
                    }

                    scm {
                        url = 'scm:git@github.com:grails/gorm-neo4j.git'
                        connection = 'scm:git@github.com:grails/gorm-neo4j.git'
                        developerConnection = 'scm:git@github.com:grails/gorm-neo4j.git'
                    }

                    developers {
                        developer {
                            id = 'puneetbehl'
                            name = 'Puneet Behl'
                            email = 'behlp@objectcomputing.com'
                        }
                    }
                }

                artifactId projectInfo.projectArtifactId
                from components.java

                afterEvaluate {
                    if (isGrails3PluginProject) {
                        artifact source:"${sourceSets.main.groovy.outputDir}/META-INF/grails-plugin.xml",
                                classifier:"plugin",
                                extension:'xml'
                    }

                }

                pom.withXml {
                    def xml = asNode()
                    def dependency = xml.dependencies.find { dep -> dep.artifactId == 'slf4j-simple' }
                    dependency?.optional = true
                }
            }
        }

        afterEvaluate {
            signing {
                required { isReleaseVersion }
                sign publishing.publications.maven
            }
        }

        tasks.withType(Sign) {
            onlyIf { isReleaseVersion }
        }

        //do not generate extra load on Nexus with new staging repository if signing fails
        tasks.withType(io.github.gradlenexus.publishplugin.InitializeNexusStagingRepository).configureEach {
            shouldRunAfter(tasks.withType(Sign))
        }
    }
}

class PublishingConvention {
    Project project

    String projectArtifactId
    String projectName = 'GORM for Neo4j'
    String projectDescription = 'Provides a GORM Object Mapping implementation for the Neo4j Graph Database'
    String projectURL = 'https://github.com/apache/grails-core/tree/HEAD/grails-data-neo4j'
    String projectIssueTrackerUrl = 'https://github.com/apache/grails-core/issues'
    String projectVcsUrl = 'https://github.com/apache/grails-core'

    PublishingConvention(Project project) {
        this.project = project

        def name = project.name
        if(name.startsWith('grails') && name.endsWith('-plugin')) {
            name = 'neo4j'
        }
        projectArtifactId = name
    }
}
