// 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
//=============================================================================
plugins {
    id 'java'
    id 'application'
    id "com.google.protobuf" version "0.8.0"
}
apply plugin: 'com.google.protobuf'
apply plugin: 'checkstyle'

//=============================================================================
// Project Level Settings
//=============================================================================
/* Meta Data Info */
def title = 'Apache Wave Server'
def vendor = 'The Apache Software Foundation'
version = "0.4.2"
mainClassName = "org.waveprotocol.box.server.ServerMain"
applicationDefaultJvmArgs = [
        "-Xmx1024M",
        "-Dorg.eclipse.jetty.LEVEL=DEBUG",
        "-Djava.util.logging.config.file=config/wiab-logging.conf",
        "-Djava.security.auth.login.config=config/jaas.config"
]
sourceCompatibility = 1.8
targetCompatibility = 1.8
compileJava {
    options.incremental = true
}

//=============================================================================
// Extra Configurations (used for separation of dependencies)
//=============================================================================
configurations {
    generateMessages
    generateGXP
}

//=============================================================================
// Source's
//=============================================================================
sourceSets {
    main {
        java {
            srcDirs = [
                    'src/main/java',
                    'generated/main/java',
                    'generated/proto/java'
            ]
        }
        resources {
            srcDir 'src/main/resources'
        }
    }
    proto {
        proto {
            srcDir 'src/proto/proto'
            include '**/*.protodevel'
        }
    }
    test {
        java {
            srcDir 'src/test/java'
        }
        resources {
            srcDir 'src/test/resources'
        }
    }
}

//=============================================================================
// Dependencies
// Note: next to each dependency is a review stamp [last review, next review].
//       If a dependency is past its review date pls create a jira issue.
//       https://issues.apache.org/jira/browse/WAVE
//=============================================================================
repositories {
    mavenCentral()
    maven {
        url 'https://oauth.googlecode.com/svn/code/maven/'
    }
    maven {
        url 'https://maven.atlassian.com/3rdparty/'
    }
}
configurations.compile {
    resolutionStrategy {
        //failOnVersionConflict()
    }
}
dependencies {
    compile (
            [group: "com.google.code.gson", name: "gson", version: "2.8.0"],                                    // [11/2016, 1/2018]
            [group: "com.google.guava", name: "guava", version: "20.0"],                                        // [11/2016, 1/2018]
            [group: "com.google.guava", name: "guava-gwt", version: "20.0"],                                    // [11/2016, 1/2018]
            [group: "com.google.gwt", name: "gwt-dev", version: "2.8.0"],                                       // [11/2016, 1/2018]
            [group: "com.google.gwt", name: "gwt-user", version: "2.8.0"],                                      // [11/2016, 1/2018]
            [group: "com.google.gwt", name: "gwt-codeserver", version: "2.8.0"],                                // [11/2016, 1/2018]
            [group: "com.google.gxp", name: "google-gxp", version: "0.2.4-beta"],                               // [?, ?]
            [group: "com.google.protobuf", name: "protobuf-java", version: "2.6.1"],                            // [?, ?]
            [group: "com.google.protobuf", name: "protobuf-java", version: "2.6.1", classifier: 'sources'],     // [?, ?]
            [group: "com.googlecode.protobuf-java-format", name: "protobuf-java-format", version: "1.2"],       // [?, ?]
            [group: "com.typesafe", name: "config", version: "1.2.1"],                                          // [?, ?]
            [group: "commons-codec", name: "commons-codec", version: "1.10"],                                   // [?, ?]
            [group: "commons-io", name: "commons-io", version: "2.4"],                                          // [?, ?]
            [group: "commons-collections", name: "commons-collections", version: "3.2.2"],                      // [?, ?]
            [group: "commons-configuration", name: "commons-configuration", version: "1.6"],                    // [?, ?]
            [group: "commons-httpclient", name: "commons-httpclient", version: "3.1"],                          // [?, ?]
            [group: "commons-lang", name: "commons-lang", version: "2.5"],                                      // [?, ?]
            [group: "commons-fileupload", name: "commons-fileupload", version: "1.3.2"],                        // [11/2016, 6/2017]
            [group: "commons-logging", name: "commons-logging-api", version: "1.1"],                            // [?, ?]
            [group: "commons-logging", name: "commons-logging", version: "1.1.1"],                              // [?, ?]
            [group: "com.google.code.findbugs", name: "jsr305", version: "2.0.1"],                              // [?, ?]
            [group: "com.google.code.gson", name: "gson", version: "2.2.4"],                                    // [?, ?]
            [group: "com.google.guava", name: "guava", version: "20.0"],                                        // [?, ?]
            [group: "com.google.guava", name: "guava-gwt", version: "20.0"],                                    // [?, ?]
            [group: "com.google.gxp", name: "google-gxp", version: "0.2.4-beta"],                               // [?, ?]
            [group: "com.google.inject.extensions", name: "guice-assistedinject", version: "3.0"],              // [?, ?]
            [group: "com.google.inject.extensions", name: "guice-servlet", version: "3.0"],                     // [?, ?]
            [group: "com.google.inject", name: "guice", version: "3.0"],                                        // [?, ?]
            [group: "com.google.protobuf", name: "protobuf-java", version: "2.6.1"],                            // [?, ?]
            [group: "com.google.inject", name: "guice", version:"4.1.0"],					// [?, ?]
            [group: "com.google.inject.extensions", name: "guice-servlet", version:"4.1.0"],			// [?, ?]
            [group: "com.googlecode.protobuf-java-format", name: "protobuf-java-format", version: "1.2"],       // [?, ?]
            [group: "com.typesafe", name: "config", version: "1.2.1"],                                          // [?, ?]
            [group: "dom4j", name: "dom4j", version: "1.6.1"],                                                  // [?, ?]
            [group: "eu.infomas", name: "annotation-detector", version: "3.0.0"],                               // [?, ?]
            [group: "org.antlr", name: "antlr", version: "3.2"],                                                // [?, ?]
            [group: "org.apache.velocity", name: "velocity", version: "1.6.3"],                                 // [?, ?]
            [group: "org.apache.lucene", name: "lucene-core", version: "3.5.0"],                                // [?, ?]
            [group: "org.bouncycastle", name: "bcprov-jdk16", version: "1.45"],                                 // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-annotations", version: "9.2.14.v20151106"],               // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-client", version: "9.2.14.v20151106"],                    // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-continuation", version: "9.2.14.v20151106"],              // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-http", version: "9.2.14.v20151106"],                      // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-io", version: "9.2.14.v20151106"],                        // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-proxy", version: "9.2.14.v20151106"],                     // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-security", version: "9.2.14.v20151106"],                  // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-server", version: "9.2.14.v20151106"],                    // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-servlet", version: "9.2.14.v20151106"],                   // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-servlets", version: "9.2.14.v20151106"],                  // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-util", version: "9.2.14.v20151106"],                      // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-webapp", version: "9.2.14.v20151106"],                    // [?, ?]
            [group: "org.eclipse.jetty", name: "jetty-xml", version: "9.2.14.v20151106"],                       // [?, ?]
            [group: "org.eclipse.jetty.websocket", name: "websocket-api", version: "9.2.14.v20151106"],         // [?, ?]
            [group: "org.eclipse.jetty.websocket", name: "websocket-client", version: "9.2.14.v20151106"],      // [?, ?]
            [group: "org.eclipse.jetty.websocket", name: "websocket-common", version: "9.2.14.v20151106"],      // [?, ?]
            [group: "org.eclipse.jetty.websocket", name: "websocket-server", version: "9.2.14.v20151106"],      // [?, ?]
            [group: "org.eclipse.jetty.websocket", name: "websocket-servlet", version: "9.2.14.v20151106"],     // [?, ?]
            [group: "org.jdom", name: "jdom", version: "1.1.3"],                                                // [?, ?]
            [group: "org.mongodb", name: "mongo-java-driver", version: "2.11.2"],                               // [?, ?]
            [group: "org.slf4j", name: "slf4j-api", version: "1.6.1"],                                          // [?, ?]
            [group: "org.slf4j", name: "slf4j-simple", version: "1.6.1"],                                       // [?, ?]
            [group: "javax.inject", name: "javax.inject", version: "1"],                                        // [?, ?]
            [group: "javax.servlet", name: "javax.servlet-api", version: "3.1.0"],                              // [?, ?]
            [group: "javax.jdo", name: "jdo2-api", version: "2.1"],                                             // [?, ?]
            [group: "net.oauth.core", name: "oauth-provider", version: "20100601-atlassian-2"],                 // [11/2016, depreciate]
            [group: "net.oauth.core", name: "oauth", version: "20100601-atlassian-2"],                          // [11/2016, depreciate]
            [group: "net.oauth.core", name: "oauth-consumer", version: "20100601-atlassian-2"],                 // [11/2016, depreciate]
    )
    compile fileTree(dir: '../pst/build/libs', include: '**/*.jar')                                             // [?, ?]
    generateGXP (
        [group: "com.google.gxp", name: "google-gxp", version: "0.2.4-beta"]                                    // [11/2016, depreciate]
    )
    protoCompile (
        [group: "com.google.protobuf", name: "protobuf-java", version: "2.6.1"],                                // [?, ?]
        fileTree(dir: '../pst/build/libs', include: '**/*.jar')                                                 // [?, ?]
    )
    generateMessages (
         fileTree(dir: '../pst/build/libs', include: '**/*.jar')                                                // [?, ?]
    )
    testCompile(
            [group: 'junit', name: 'junit', version: '4.12'],                                                   // [11/2016, 1/2018]
            [group: "org.hamcrest", name: "hamcrest-junit", version: "2.0.0.0"],                                // [11/2016, 1/2018]
            [group: "org.mockito", name: "mockito-core", version: "2.2.21"],                                    // [11/2016, 1/2018]
    )
}
//=============================================================================
// CheckStyle Config
//=============================================================================
checkstyle {
    toolVersion = "7.6.1"
    configFile = file("/google_checks.xml")
}

checkstyleMain.source = "src/main/java" // only checks the manually written java

//=============================================================================
// Protobuf Config
//=============================================================================
protobuf {
    protoc {
        artifact = 'com.google.protobuf:protoc:2.6.1'
    }
    generatedFilesBaseDir = "$projectDir/generated"
}

//=============================================================================
// Task - Generation Tasks (External Compilers)
//=============================================================================

task generateMessages {
    description = 'Generates source files from Antlr String types and protobuf'
    FileTree inputFiles = fileTree(dir: 'generated/src/main/java', include: '**/*.java')
    inputs.property "files", inputFiles
    File outputDir = file("generated/main/java")
    outputs.dir outputDir
    doLast {
        List<String> proto_classes = [
                "build/classes/proto/org/waveprotocol/box/common/comms/WaveClientRpc.class",
                "build/classes/proto/org/waveprotocol/box/search/SearchProto.class",
                "build/classes/proto/org/waveprotocol/box/profile/ProfilesProto.class",
                "build/classes/proto/org/waveprotocol/box/server/rpc/Rpc.class",
                "build/classes/proto/org/waveprotocol/box/attachment/AttachmentProto.class",
                "build/classes/proto/org/waveprotocol/wave/federation/Proto.class",
                "build/classes/proto/org/waveprotocol/wave/concurrencycontrol/ClientServer.class",
                "build/classes/proto/org/waveprotocol/wave/diff/Diff.class"
        ]
        List<String> templates = [
                "src/main/java/org/waveprotocol/pst/templates/api/api.st",
                "src/main/java/org/waveprotocol/pst/templates/builder/builder.st",
                "src/main/java/org/waveprotocol/pst/templates/pojo/pojo.st",
                "src/main/java/org/waveprotocol/pst/templates/jso/jso.st",
                "src/main/java/org/waveprotocol/pst/templates/util/util.st",
                "src/main/java/org/waveprotocol/pst/templates/gson/gson.st",
                "src/main/java/org/waveprotocol/pst/templates/proto/proto.st"
        ]
        proto_classes.each { proto ->
            javaexec {
                main = "org.apache.wave.pst.PstMain"
                classpath += configurations.generateMessages
                args = [
                        '-s',
                        'pst',
                        '-d',
                        'generated/main/java',
                        '-f',
                        proto
                ]
                args += templates
            }
        }
    }
}

generateMessages.dependsOn ":pst:shadowJar", "compileProtoJava"

task generateGXP {
    description = 'Generate source files from GXP prototypes'
    FileTree inputFiles = fileTree(dir: 'src/main/gxp', include: '**/*.gxp')
    inputs.property "files", inputFiles
    File outputDir = file("generated/main/java")
    outputs.dir outputDir
    doLast {
        javaexec {
            main = "com.google.gxp.compiler.cli.Gxpc"
            classpath += configurations.generateGXP
            args = [
                    "--dir",
                    "generated/main/java",
                    "--source",
                    "src/main/gxp",
                    "--output_language",
                    "java"
            ]
            args += fileTree(dir: 'src/main/gxp', include: '**/*.gxp').getFiles()
        }
    }
}

//=============================================================================
// Gwt Compilation Options
//=============================================================================
task compileGwt {
    description = 'Compiles the GWT sources for production'
    FileTree inputFiles = fileTree(dir: 'generated/src/main/java', include: '**/*.java')
    doLast {
        javaexec {
            main = "com.google.gwt.dev.Compiler"
            classpath {
                [
                        sourceSets.main.java.srcDirs,
                        sourceSets.main.compileClasspath,
                        sourceSets.main.resources.srcDirs
                ]
            }
            jvmArgs = [
                    "-Xmx1024M"
            ]
            args = [
                    "-style", "OBFUSCATED",
                    "-XdisableClassMetadata",
                    "-XdisableCastChecking",
                    "-localWorkers", "4",
                    "org.waveprotocol.box.webclient.WebClientProd"
            ]
        }
    }
}

compileGwt.mustRunAfter compileJava

task compileGwtDemo {
    description = 'Compiles the GWT sources for Demo'
    doLast {
        javaexec {
            main = "com.google.gwt.dev.Compiler"
            classpath {
                [
                        sourceSets.main.java.srcDirs,
                        sourceSets.main.compileClasspath,
                        sourceSets.main.resources.srcDirs
                ]
            }
            args = [
                    "-style", "Pretty",
                    "-ea",
                    "org.waveprotocol.box.webclient.WebClientDemo"
            ]
        }
    }
}

task compileGwtDev {
    description = 'Compiles the GWT sources for Development'
    doLast {
        javaexec {
            main = "com.google.gwt.dev.Compiler"
            classpath {
                [
                        sourceSets.main.java.srcDirs,
                        sourceSets.main.compileClasspath,
                        sourceSets.main.resources.srcDirs
                ]
            }
            args = [
                    "-style", "PRETTY",
                    "-draftCompile",
                    "-ea",
                    "-strict",
                    "org.waveprotocol.box.webclient.WebClientDev"
            ]
        }
    }
}


run.dependsOn compileGwt
compileJava.dependsOn = [generateMessages, generateGXP]

/* Gwt Dev Tasks */

task gwtDev {
    description = 'Runs the hosted mode server, for debugging the Gwt client ' +
            'in a JVM.'
    doFirst {
        println ''
        println '----------------------------------------------'
        println '           Running Gwt Dev mode.              '
        println 'Note: This currently has a classpath conflict.'
        println '----------------------------------------------'
        println ''
    }
    doLast {
        javaexec {
            main = "com.google.gwt.dev.DevMode"
            classpath {
                [
                        sourceSets.main.java.srcDirs,
                        sourceSets.main.compileClasspath,
                        sourceSets.main.resources.srcDirs
                ]
            }
            args = [
                    "-noserver",
                    "-bindAddress", "127.0.0.1",
                    "-startupUrl", "http://localhost:9898",
                    "-logLevel", "DEBUG",
                    "org.waveprotocol.box.webclient.WebClientDev",
            ]
        }
    }
}

//=============================================================================
// Tests
//=============================================================================

test {
    include "**/*Test*"
    exclude "**/*GwtTest*"
    exclude "**/server/persistence/mongodb/**/*Test*"
    exclude "**/*LargeTest*"

    minHeapSize = "512m"
    maxHeapSize = "1024m"

    doFirst {
        println ''
        println '---------------------'
        println ' Running unit tests. '
        println '---------------------'
        println ''
    }
}

task testGwt(type: Test) {
    include "**/*GwtTest*"

    classpath += files('src/main/java/')
    classpath += files('src/test/java/')

    minHeapSize = "512m"
    maxHeapSize = "1024m"
    forkEvery = 1

    jvmArgs '-Dgwt.args=-logLevel WARN'

    doFirst {
        println ''
        println '--------------------'
        println ' Running Gwt tests. '
        println '--------------------'
        println ''
    }
}

testGwt.dependsOn compileGwt

task testMongo(type: Test) {
    include "**/server/persistence/mongodb/**/*Test*"

    doFirst {
        println ''
        println '--------------------------'
        println ' Testing MongoDB backend. '
        println '--------------------------'
        println ''
    }
}

testMongo.dependsOn compileJava

task testLarge(type: Test) {
    include "**/*LargeTest*"

    doFirst {
        println ''
        println '-------------------------------'
        println '     Testing Large Tests.      '
        println 'These tests may take some time.'
        println '-------------------------------'
        println ''
    }
}

testLarge.dependsOn compileJava

task testAll() {
    doFirst {
        println ''
        println '--------------------------'
        println '     Tests completed.     '
        println '--------------------------'
        println ''
    }
}

testAll.dependsOn compileJava, compileGwt
testAll.dependsOn test, testMongo, testLarge, testGwt

testGwt.mustRunAfter compileGwt, testLarge
testMongo.mustRunAfter compileJava, test
testLarge.mustRunAfter test

//=============================================================================
// Dist's
//=============================================================================

jar {
    baseName = 'wave'
    classifier = ''
    manifest {
        attributes "Specification-Vendor": vendor,
                "Specification-Title": title,
                "Specification-Version": version,
                "Implementation-Vendor": vendor,
                "Implementation-Title": title,
                "Implementation-Version": version,
                "Built-By": "No one in particular",
                "Main-Class": mainClassName
    }
    exclude "org/waveprotocol/box/webclient/**/*"
    exclude "org/waveprotocol/box/consoleclient/**/*"
    exclude "org/waveprotocol/box/expimp/**/*"
    exclude "org/waveprotocol/wave/client/*"
    exclude "org/waveprotocol/wave/client/account/**/*"
    exclude "org/waveprotocol/wave/client/autohide/**/*"
    exclude "org/waveprotocol/wave/client/clipboard/**/*"
    exclude "org/waveprotocol/wave/client/common/**/*"
    exclude "org/waveprotocol/wave/client/concurrencycontrol/**/*"
    exclude "org/waveprotocol/wave/client/debug/**/*"
    exclude "org/waveprotocol/wave/client/doodad/**/*"
    exclude "org/waveprotocol/wave/client/paging/**/*"
    exclude "org/waveprotocol/wave/client/render/**/*"
    exclude "org/waveprotocol/wave/client/scheduler/**/*"
    exclude "org/waveprotocol/wave/client/scroll/**/*"
    exclude "org/waveprotocol/wave/client/state/**/*"
    exclude "org/waveprotocol/wave/client/testing/**/*"
    exclude "org/waveprotocol/wave/client/uibuilder/**/*"
    exclude "org/waveprotocol/wave/client/uibuilder/**/*"
    exclude "org/waveprotocol/wave/client/util/**/*"
    exclude "org/waveprotocol/wave/client/wave/**/*"
    exclude "org/waveprotocol/wave/client/wavepanel/**/*"
    exclude "org/waveprotocol/wave/client/widget/**/*"
    exclude "com/google/api/client/**/*"
}
jar.dependsOn compileJava, compileGwt

//=============================================================================
// Binary Distribution
//=============================================================================
tasks.withType(Tar) {
    compression = Compression.BZIP2
}

distributions {
    main {
        contents {
            from('config') {
              into 'config'
            }
            from('war') {
                into 'war'
            }
            from('../THANKS') {
                into ''
            }
            from('../RELEASE-NOTES') {
                into ''
            }
            from('../KEYS') {
                into ''
            }
            from('../DISCLAIMER') {
                into ''
            }
        }
    }
}

// Additional Clean
clean {
    delete "war/WEB-INF"
    delete "war/webclient"
    delete "generated/"
    delete "gwt-unitCache"
}
