/*
 * 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.
 */
buildscript {
    ext.kotlin_version = '1.3.0'

    repositories {
        mavenCentral()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'org.junit.platform:junit-platform-gradle-plugin:1.1.0'
    }
}

plugins {
    id "org.nosphere.apache.rat" version "0.3.1"
    id "org.jetbrains.kotlin.jvm" version "1.3.0"
    id "distribution"
}

apply plugin: 'distribution'
apply plugin: 'kotlin'
apply plugin: 'project-report'
apply plugin: 'org.junit.platform.gradle.plugin'
htmlDependencyReport {
    projects = project.allprojects
}

allprojects {
    group 'org.apache.amaterasu'
    version '0.2.0-incubating-rc4'
}

task copyLegalFiles(type: Copy) {
    from "./DISCLAIMER", "./LICENSE", "./NOTICE"
    into "${buildDir}/amaterasu"
}

task buildHomeDir() {
    dependsOn subprojects.collect { getTasksByName('copyToHome', true) }
    dependsOn copyLegalFiles
}

distributions {
    custom {
        baseName = 'apache-amaterasu'
        version = project.version
        contents {
            from { 'build/amaterasu' }
        }
    }
}

task buildDistribution() {
    delete 'build/amaterasu'
    dependsOn buildHomeDir
    dependsOn customDistTar
}

rat {
    // List of exclude directives, defaults to ['**/.gradle/**']
    excludes = ["**/build/**", '**/.gradle/**', '**/gradle/**', '**/.idea/**', '**/.ruby-version/**', '**/repo/**', '**/resources/**',  '**/*.iml/**']
}

tasks.withType(Test) {
    maxParallelForks = 1
}

repositories {
    mavenCentral()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"


    testCompile(
            'org.junit.jupiter:junit-jupiter-api:5.2.0'
    )
    testRuntime(
            'org.junit.jupiter:junit-jupiter-engine:5.2.0'
    )

    testImplementation(
            'org.junit.jupiter:junit-jupiter-api:5.2.0'
    )
    testRuntimeOnly(
            'org.junit.jupiter:junit-jupiter-engine:5.2.0',
            'org.junit.vintage:junit-vintage-engine:5.2.0',
            'org.junit.platform:junit-platform-launcher:1.1.0',
            'org.junit.platform:junit-platform-runner:1.1.0'
    )


}


compileTestKotlin {
    kotlinOptions {
        freeCompilerArgs = ["-Xjsr305=strict"]
        jvmTarget = "1.8"
    }
}

test {
    useJUnitPlatform()
}