/*
 * 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 {
    id "org.nosphere.apache.rat" version "0.3.0"
    id "com.diffplug.gradle.spotless" version "3.0.0"
    id "de.undercouch.download" version "3.1.2"
}

allprojects {
    repositories {
        if (geodeRepositoryUrl != "") {
            maven {
                url geodeRepositoryUrl
            }
        }
        mavenCentral()
        maven {
            url 'https://storage.googleapis.com/maven.apachegeode-ci.info/snapshots'
        }
    }
}

def installDir = "$buildDir/apache-geode-${geodeVersion}"

configurations {
    geodeDistribution
}

dependencies {
    geodeDistribution("org.apache.geode:apache-geode:$geodeVersion@tgz") {
      if (gradle.usingGeodeCompositeBuild) {
        targetConfiguration = 'compositeTarget'
      }
    }
}

task installGeode(type: Copy) {
    if (gradle.usingGeodeCompositeBuild) {
        dependsOn(gradle.includedBuild('geode').task(':geode-assembly:distTar'))
    }
    from tarTree(configurations.geodeDistribution.singleFile)
    into buildDir
}

subprojects {
    apply plugin: 'java'

    dependencies {
        compile "org.apache.geode:geode-core:$geodeVersion"
        compile "org.apache.geode:geode-cq:$geodeVersion"
        compile "org.apache.geode:geode-logging:$geodeVersion"
        compile 'com.google.guava:guava:25.1-jre'

        testCompile "com.jayway.awaitility:awaitility:$awaitilityVersion"
        testCompile "junit:junit:$junitVersion"
        testCompile "org.mockito:mockito-core:$mockitocoreVersion"
        testCompile "com.github.stefanbirkner:system-rules:$systemrulesVersion"
        testCompile "org.assertj:assertj-core:$assertjVersion"
        compile "org.apache.logging.log4j:log4j-core:$log4jVersion"
        runtime "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion"
    }

    jar {
        archiveName "${baseName}.${extension}"
    }

    task cleanServer {
        doLast {
            delete 'locator'
            delete 'locator-ln'
            delete 'locator-ny'
            delete 'server1'
            delete 'server2'
            delete 'server-ln-1'
            delete 'server-ln-2'
            delete 'server-ny-1'
            delete 'server-ny-2'
        }
    }
    clean.finalizedBy cleanServer

    def geodePath = "${System.env.PATH}${System.getProperty('path.separator')}${installDir}/bin"
    task start(type: Exec, dependsOn: [installGeode, build, cleanServer]) {
        workingDir projectDir
        environment 'GEODE_HOME', installDir
        environment 'PATH', geodePath
        commandLine 'sh', '-c', "gfsh run --file=${projectDir}/scripts/start.gfsh"
    }

    task stop(type: Exec, dependsOn: installGeode) {
        workingDir projectDir
        environment 'GEODE_HOME', installDir
        environment 'PATH', geodePath
        commandLine 'sh', '-c', "gfsh run --file=${projectDir}/scripts/stop.gfsh"
    }

    task run(type: JavaExec, dependsOn: build) {
        description = 'Run example'
        classpath = sourceSets.main.runtimeClasspath
        main = "org.apache.geode_examples.${project.name}.Example"
    }

    task waitForExitingMembers(type: Exec) {
        workingDir projectDir
        environment 'GEODE_HOME', installDir
        environment 'PATH', geodePath
        ignoreExitValue true
        commandLine 'sh', '-c', "" +
                "TIMEOUT=120 ;" +
                "echo \"Waiting at most \$TIMEOUT seconds for all members to shut down...\" ;" +
                "while pgrep -f \"(Server|Locator)Launcher\" > /dev/null ; do" +
                "  printf \".\" ; " +
                "  sleep 1 ;" +
                "  TIMEOUT=\$((\$TIMEOUT - 1)) ;" +
                "  if [ \$TIMEOUT -eq 0 ] ; then" +
                "    echo \"\" ;" +
                "    exit 10 ;" +
                "  fi ;" +
                "done ;" +
                "echo \"\""
        doLast {
            // We use exit code 10 to avoid conflict with pgrep exit codes.
            if (execResult.exitValue == 10) {
                throw new GradleException("A member process persisted beyond permitted timeout.  Aborting.")
            } else if (execResult.exitValue != 0) {
                throw new GradleException("waitForExistingMembers failed with exit code: " + execResult.exitValue)
            }
        }
    }

    task verifyNoMembersRunning(type: Exec) {
        workingDir projectDir
        environment 'GEODE_HOME', installDir
        environment 'PATH', geodePath
        ignoreExitValue true
        commandLine 'sh', '-c', "echo \"Looking for existing member processes...\" ; " +
                "pgrep -f \"(Server|Locator)Launcher\" ; "
        doLast {
            if (execResult.exitValue == 0) {
                throw new GradleException("Existing members detected.  Examples expect a clean environment in which to run.")
            }
        }
    }
    if (gradle.usingGeodeCompositeBuild) {
        tasks.withType(JavaCompile) {
            options.fork = true
            options.forkOptions.jvmArgs += ['-Xmx3g']
        }
    }

    task runAll(dependsOn: [verifyNoMembersRunning, start, run, stop, waitForExitingMembers])
    start.mustRunAfter verifyNoMembersRunning
    run.mustRunAfter start
    stop.mustRunAfter run
    waitForExitingMembers.mustRunAfter stop
}

apply from: "gradle/spotless.gradle"
apply from: "gradle/ide.gradle"
apply from: "gradle/rat.gradle"
apply from: "gradle/release.gradle"
