/*
 * Copyright (c) 2008-2015 MongoDB, Inc.
 *
 * Licensed 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 static org.gradle.util.CollectionUtils.single

apply plugin: 'eclipse'
apply plugin: 'idea'

def configDir = new File(rootDir, 'config')
ext.nettyVersion = '4.1.17.Final'
ext.snappyVersion = '1.1.4'

buildscript {
    repositories {
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
        jcenter()
        mavenCentral()
        maven { url "https://plugins.gradle.org/m2/" }
        mavenLocal()
    }
    dependencies {
        classpath 'org.kordamp.gradle:clirr-gradle-plugin:0.2.2'
        classpath 'com.netflix.nebula:gradle-extra-configurations-plugin:1.12.+'
        classpath 'com.bmuschko:gradle-nexus-plugin:2.2'
        classpath "gradle.plugin.com.github.spotbugs:gradlePlugin:1.6.0"
    }
}

//////////////////////////////////////////
// Common behavior                      //
//////////////////////////////////////////

configure(subprojects.findAll { it.name != 'util' }) {
    apply plugin: 'java'
    apply plugin: 'optional-base'

    evaluationDependsOn(':util')

    group = 'org.mongodb'
    version = '3.6.3'
    sourceCompatibility = JavaVersion.VERSION_1_6
    targetCompatibility = JavaVersion.VERSION_1_6

    repositories {
        mavenCentral()
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
        mavenLocal()
    }

    dependencies {
        compile 'org.slf4j:slf4j-api:1.7.6', optional
    }

    /* Compiling */
    tasks.withType(AbstractCompile) {
        options.encoding = 'ISO-8859-1'
        options.fork = true
        options.debug = true
        options.compilerArgs = ['-Xlint:all', '-Xlint:-options']

        onlyIf { JavaVersion.current().isJava7Compatible() }
    }

    project.ext.buildingWith = { propertyName ->
        project.hasProperty(propertyName) && project.property(propertyName).toBoolean()
    }

    tasks.withType(Checkstyle) {
        reports {
            xml.enabled true
            html.enabled true
        }
    }

    /*
        For security we allow the signing-related project properties to be passed in as environment variables, which
        Gradle enables if they are prefixed with "ORG_GRADLE_PROJECT_".  But since environment variables can not contain
        the '.' character and the signing-related properties contain '.', here we map signing-related project properties with '_'
        to ones with '.' that are expected by the signing plugin.
     */
    gradle.taskGraph.whenReady { taskGraph ->
        if (taskGraph.allTasks.any { it instanceof Sign }) {
            if (project.hasProperty("signing_keyId")) {
                allprojects { ext."signing.keyId" = project.property("signing_keyId") }
            }
            if (project.hasProperty("signing_secretKeyRingFile")) {
                allprojects { ext."signing.secretKeyRingFile" = project.property("signing_secretKeyRingFile") }
            }
            if (project.hasProperty("signing_password")) {
                allprojects { ext."signing.password" = project.property("signing_password") }
            }
        }
    }

    javadoc {
        exclude "**/com/mongodb/**/internal/**"
        exclude "**/org/bson/**/internal/**"

        dependsOn project(':util').compileJava //We need taglets to be compiled

        options.author = true
        options.version = true
        options.links 'http://docs.oracle.com/javase/7/docs/api/'
        options.tagletPath single(project(':util').sourceSets.main.output.classesDirs)
        options.taglets 'ManualTaglet'
        options.taglets 'DochubTaglet'
        options.taglets 'ServerReleaseTaglet'
        options.encoding = 'UTF-8'
        options.charSet 'UTF-8'
        options.docEncoding 'UTF-8'
        options.header = '''
            <script type="text/javascript">
            <!-- Set the location hash in the classFrame -->
            try {
              locationHash = top.location.hash;
              if (window.name == "classFrame" && locationHash != "") {
                window.location.hash = locationHash;
              }
            } catch (error) {}
            <!-- GA Tracking code -->
            if (window.name == "" || window.name == "classFrame") {
                var _elqQ = _elqQ || [];
                _elqQ.push(["elqSetSiteId", "413370795"]);
                _elqQ.push(["elqTrackPageView"]);
                (function () {
                function async_load() { var s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = "//img03.en25.com/i/elqCfg.min.js"; var x = document.getElementsByTagName("script")[0]; x.parentNode.insertBefore(s, x); }
                if (window.addEventListener) window.addEventListener("DOMContentLoaded", async_load, false);
                else if (window.attachEvent) window.attachEvent("onload", async_load);
                })();
            }
            </script>
        '''

        // Add --allow-script-in-comments if available (since 1.8.0_121)
        try {
            if (Class.forName('com.sun.tools.doclets.formats.html.ConfigurationImpl')
                     .newInstance().optionLength('--allow-script-in-comments') > 0) {
                options.addBooleanOption("-allow-script-in-comments", true)
            }
        } catch (ignored) {}
    }
}

def getGitVersion() {
    def outputAsString
    new ByteArrayOutputStream().withStream { os ->
        def result = exec {
            executable 'git'
            args 'describe', '--tags', '--always', '--dirty'
            standardOutput = os
        }
        outputAsString = os.toString().substring(1).trim()
    }
    return outputAsString
}

configure(subprojects.findAll { it.name != 'util' && it.name != 'mongo-java-driver' }) {
    apply plugin: 'checkstyle'
    apply plugin: "com.github.spotbugs"
    apply plugin: 'jacoco'
    apply plugin: 'groovy'
    apply plugin: 'codenarc'

    dependencies {
        testCompile 'org.codehaus.groovy:groovy-all:2.4.12'
        testCompile 'org.spockframework:spock-core:1.1-groovy-2.4'
        testCompile 'cglib:cglib-nodep:2.2.2'
        testCompile 'org.objenesis:objenesis:1.3'
        testCompile 'org.hamcrest:hamcrest-all:1.3'
        testCompile 'ch.qos.logback:logback-classic:1.1.1'
        testCompile project(':util') //Adding categories to classpath
    }

    sourceSets {
        main {
            java.srcDirs = ['src/main']
        }
        test {
            groovy.srcDirs = ['src/test/functional', 'src/test/unit']
        }
    }

    /* Testing */
    tasks.withType(Test) {
        maxHeapSize = "3g"
        maxParallelForks = 1

        systemProperties(
                'org.mongodb.test.uri': System.getProperty('org.mongodb.test.uri'),
                'org.mongodb.useSocket': System.getProperty('org.mongodb.useSocket', 'false'),
                'org.mongodb.disableAsync': System.getProperty('org.mongodb.disableAsync', 'false'),
                'org.mongodb.async.type': System.getProperty('org.mongodb.async.type', 'nio2'),

                'javax.net.ssl.trustStore': System.getProperty('javax.net.ssl.trustStore'),
                'javax.net.ssl.keyStore': System.getProperty('javax.net.ssl.keyStore'),
                'javax.net.ssl.keyStorePassword': System.getProperty('javax.net.ssl.keyStorePassword'),
                'javax.net.ssl.trustStorePassword': System.getProperty('javax.net.ssl.trustStorePassword')
        )

        if (project.buildingWith('ssl.enabled')) {
            systemProperties(
                    'javax.net.ssl.keyStoreType': project.property('ssl.keyStoreType'),
                    'javax.net.ssl.keyStore': project.property('ssl.keyStore'),
                    'javax.net.ssl.keyStorePassword': project.property('ssl.keyStorePassword'),
                    'javax.net.ssl.trustStoreType': project.property('ssl.trustStoreType'),
                    'javax.net.ssl.trustStore': project.property('ssl.trustStore'),
                    'javax.net.ssl.trustStorePassword': project.property('ssl.trustStorePassword')
            )
        }

        if (project.buildingWith('gssapi.enabled')) {
            systemProperties(
                    'sun.security.krb5.debug': project.getProperty('sun.security.krb5.debug'),
                    'javax.security.auth.useSubjectCredsOnly': "false",
                    'java.security.krb5.kdc': project.getProperty('krb5.kdc'),
                    'java.security.krb5.realm': project.getProperty('krb5.realm'),
                    'java.security.auth.login.config': project.getProperty('auth.login.config'),
                    )
        }

        useJUnit {
            if (!project.buildingWith('rs.enabled')) {
                excludeCategories 'category.ReplicaSet'
            }
            if (project.buildingWith('quicktest')) {
                excludeCategories 'category.SlowUnit'
            }
            if (project.buildingWith('travistest')) {
                excludeCategories 'category.SlowUnit', 'category.Slow'
            }
        }

        jacoco { enabled = false }

        testLogging { exceptionFormat = 'full' }
    }

    task testSlowUnit(type: Test) {
        useJUnit {
            includeCategories 'category.SlowUnit'
        }
    }

    gradle.taskGraph.whenReady { taskGraph ->
        if (taskGraph.hasTask(testCoverage)) {
            tasks.withType(Test) { jacoco { enabled = true } }
        }
    }

    task testCoverage(dependsOn: test)

    /* Code quality */

    checkstyle {
        toolVersion = "7.4"
        configFile = new File(configDir, 'checkstyle.xml')
        configProperties.checkstyleConfigDir = configDir
    }

    spotbugs {
        excludeFilter = new File(configDir, 'findbugs-exclude.xml')
        sourceSets = [sourceSets.main]
        toolVersion = '3.1.0'
    }

    codenarc {
        toolVersion = '1.0'
        reportFormat = project.buildingWith('xmlReports.enabled') ? 'xml' : 'html'
    }

    tasks.withType(com.github.spotbugs.SpotBugsTask) {
        reports {
            xml.enabled = project.buildingWith('xmlReports.enabled')
            html.enabled = !project.buildingWith('xmlReports.enabled')
        }
    }

    tasks.withType(Test) {
        def jdkHome = findProperty("jdkHome")
        if (jdkHome) {
            def javaExecutablesPath = new File(jdkHome, 'bin')
            def javaExecutables = [:].withDefault { execName ->
                def executable = new File(javaExecutablesPath, execName)
                assert executable.exists() : "There is no ${execName} executable in ${javaExecutablesPath}"
                executable
            }
            executable = javaExecutables.java
        }
    }
}

task docs(type: Javadoc) {
    source subprojects.grep({ it.name != 'util' }).collect {project -> project.sourceSets.main.allJava }
//    options = subprojects.first().javadoc.options
    dependsOn = subprojects.first().javadoc.dependsOn
    excludes =  subprojects.first().javadoc.excludes
    classpath = files(subprojects.collect {project -> project.sourceSets.main.compileClasspath})
    destinationDir = new File(projectDir, 'build/docs')
}

//////////////////////////////////////////
// Root project configuration           //
//////////////////////////////////////////
task wrapper(type: Wrapper) {
    gradleVersion = '4.0.1'
}

gradle.buildFinished { BuildResult result ->
    if (result.failure && !JavaVersion.current().isJava8Compatible()) {
        gradle.rootProject.logger.error("\nWARNING:\nJDK ${JavaVersion.VERSION_1_8} is required to build the driver: " +
                "you are using JDK ${JavaVersion.current()}.")
    }
}

apply from: 'gradle/deploy.gradle'
apply from: 'gradle/TestColorOutput.gradle'

