/******************************************************************************
 * Copyright 2009-2021 Exactpro (Exactpro Systems Limited)
 *
 * 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 groovy.transform.CompileStatic
buildscript {
    ext {
        kotlin_version          = '1.5.30'
        sharedDir               = file("${project.rootDir}/shared")

        sailfishVersion         = "${sailfish_version_major}.${sailfish_version_minor}"
        artifactVersion         = build_mode == 'snapshot' ? "${sailfishVersion}-SNAPSHOT" : "${sailfishVersion}.${sailfishCoreArtifactMaintenance}"
        sailfishCoreVersion		= "${sailfishVersion}"
        artifactCoreVersion     = build_mode == 'snapshot' ? "${sailfishCoreVersion}-SNAPSHOT" : "${sailfishCoreVersion}.${sailfishCoreArtifactMaintenance}"

        artifactGroup           = 'com.exactpro.sf'
    }

    repositories {
        maven {
            name 'MavenLocal' // for local builds only
            url sharedDir
        }
        maven {
            url "https://plugins.gradle.org/m2/"
        }
        if (project.hasProperty('repository')) {
            maven {
                name 'UserRepository'
                url project.repository
                if (project.hasProperty('repositoryAccount') && project.hasProperty('repositoryPassword')) {
                    credentials {
                        username project.repositoryAccount
                        password project.repositoryPassword
                    }
                }
            }
        } else {
            maven {
                name 'Artifactory-snapshot'
                url 'https://artifactory5.exactpro.com/artifactory/libs-snapshot'
            }
            maven {
                name 'Artifactory-release'
                url 'https://artifactory5.exactpro.com/artifactory/libs-release'
            }
        }
        mavenCentral()

        configurations.all {

            resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
            resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds'
        }
    }

    dependencies {
        classpath(group: 'org.jfrog.buildinfo',                 name: 'build-info-extractor-gradle',        version: '4.7.2')
        classpath(group: 'com.bmuschko',                        name: 'gradle-tomcat-plugin',               version: '2.5')
        classpath(group: 'com.github.onslip',                   name: 'gradle-one-jar',                     version: '1.0.5')
        classpath(group: 'me.champeau.gradle',                  name: 'jmh-gradle-plugin',                  version: '0.2.0')
        classpath(group: 'com.exactpro.sailfish-gradle-plugin', name: 'sailfish-gradle-plugin',             version: '3.2.22')
        classpath(group: 'javax.xml.bind',                      name: 'jaxb-api',                           version: '2.3.1')
        classpath(group: 'com.sun.xml.bind',                    name: 'jaxb-core',                          version: '2.3.0.1')
        classpath(group: 'com.sun.xml.bind',                    name: 'jaxb-impl',                          version: '2.3.1')
        classpath(group: 'com.github.ben-manes',                name: 'gradle-versions-plugin',             version: '0.20.0')
        classpath(group: 'com.bmuschko',                        name: 'gradle-cargo-plugin',                version: '2.8.0')
        classpath group: 'org.jetbrains.kotlin', name: 'kotlin-gradle-plugin', version: "${kotlin_version}"
        classpath group: "gradle.plugin.com.github.harbby", name: "gradle-serviceloader", version: "1.1.5"
        classpath group:  "com.jfrog.bintray.gradle", name: "gradle-bintray-plugin", version: "1.8.5"
    }
}
plugins {
    id "io.github.gradle-nexus.publish-plugin" version "1.0.0"
    id "org.owasp.dependencycheck" version "6.5.3"
}

if (project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword')) {
    nexusPublishing {
        repositories {
            sonatype {
                nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
                snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
            }
        }
    }
}

group = artifactGroup
version = artifactCoreVersion

allprojects {
    apply plugin: 'eclipse-wtp'
    apply plugin: 'sailfish'
    apply plugin: 'com.github.ben-manes.versions'
    apply plugin: 'com.github.harbby.gradle.serviceloader'

    ext {
        sharedWorkspaceDir      = file("${project.rootDir}/shared_workspace")
        tmpWorkspaceDir         = file("${project.rootDir}/tmp_workspace")

        lightPluginDir          = file("${project.buildDir}/light_plugin")

        srcDir                  = file('src')
        mainDir                 = file("${srcDir}/main")
        testDir                 = file("${srcDir}/test")
        genDir                  = file("${srcDir}/gen")
        extDir                  = file("${srcDir}/external")
        providedDir             = file("${srcDir}/provided")

        mainJavaDir             = file("${mainDir}/java")
        mainResDir              = file("${mainDir}/resources")
        testJavaDir             = file("${testDir}/java")
        testResDir              = file("${testDir}/resources")
        genJavaDir              = file("${genDir}/java")
        genResDir               = file("${genDir}/resources")
        providedResDir          = file("${providedDir}/resources/")

        mainWorkspaceDir        = file("${mainDir}/workspace")
        genWorkspaceDir         = file("${genDir}/workspace")
        externalWorkspaceDir    = file("${extDir}/workspace")
        providedWorkspaceDir    = file("${providedDir}/workspace")

        mainPluginDir           = file("${mainDir}/plugin")
        genPluginDir            = file("${genDir}/plugin")
        externalPluginDir       = file("${extDir}/plugin")
        providedPluginDir       = file("${providedDir}/plugin")

        zipPluginDir            = 'plugins'
        zipPluginLibsDir        = 'libs'

        incremental_build       = project.hasProperty('i')
        silent_check            = project.hasProperty('silentCheck') || project.hasProperty('sC')

        // Set defaults
        if (!project.hasProperty('rootUrl')) {
            rootUrl = 'http://localhost:8080/sfgui/sfapi/'
        }

        //Lib versions
        version_log4j2 = '2.19.0'
        version_slf4j = '1.7.32'
        version_hibernate = '5.4.24.Final'
        netty_version = '4.1.114.Final'
        fasterxml_jackson_version = '2.14.1'
    }

    eclipse {
        project {
            name = "core-${project.name}"

            natures 'org.springsource.ide.eclipse.gradle.core.nature'
            natures 'org.eclipse.jdt.core.javanature'
            natures 'edu.umd.cs.findbugs.plugin.eclipse.findbugsNature'

            buildCommand 'org.eclipse.jdt.core.javabuilder'
        }
        classpath {
            downloadSources = true
            downloadJavadoc = true
        }
    }

	 wrapper {
	    gradleVersion = '6.8'
        distributionType = 'all'
	}

    collectDependencies {
        repository = 'core'
        outputPath = project.properties.dependencyFile
        incrementalBuild = incremental_build
        publishResource = 'build/release'
    }

    configurations.all {
        resolutionStrategy.eachDependency { DependencyResolveDetails details ->
            if (details.requested.group == 'com.fasterxml.jackson') {
                details.useVersion fasterxml_jackson_version
                details.because "To have all jackson libs in same version"
            }
        }
    }
}

tasks.withType(PublishToMavenRepository).all { publishTask ->
    publishTask.enabled = false
}

subprojects {
    apply plugin: 'kotlin'
    apply plugin: 'maven-publish'
    apply plugin: 'java'
    apply plugin: 'jacoco'
    apply plugin: 'signing'
    apply from: "${getRootDir()}/DependencyConflictChecker.gradle"

    group = artifactGroup
    version = artifactCoreVersion

    sourceCompatibility = 1.8 //Java version compatibility to use when compiling Java source.
    targetCompatibility = 1.8 //Java version to generate classes for.
    compileJava.options.debugOptions.debugLevel = "source,lines,vars" // Include debug information

    javadoc {
        failOnError = false
    }

    java {
        withSourcesJar()
        withJavadocJar()
    }

    buildscript { // artifacrory plugin
        repositories {
            maven {
                name 'MavenLocal' // for local builds only
                url sharedDir
            }
            if (project.hasProperty('repository')) {
                maven {
                    name 'UserRepository'
                    url project.repository
                    if (project.hasProperty('repositoryAccount') && project.hasProperty('repositoryPassword')) {
                        credentials {
                            username project.repositoryAccount
                            password project.repositoryPassword
                        }
                    }
                }
            } else {
                maven { // for gradle fast plugin
                    name 'Artifactory-snapshot'
                    url 'https://artifactory5.exactpro.com/artifactory/libs-snapshot'
                }
                maven {
                    name 'Artifactory-release'
                    url 'https://artifactory5.exactpro.com/artifactory/libs-release'
                }
            }
            mavenCentral()
        }

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

    sourceSets {
        main {
            java {
                srcDir genJavaDir
            }
            resources {
                srcDir genResDir
                srcDir providedResDir
            }
        }
    }

    repositories {
        maven {
            name 'MavenLocal' // for local builds only
            url sharedDir
        }
        if (project.hasProperty('repository')) {
            maven {
                name 'UserRepository'
                url project.repository
                if (project.hasProperty('repositoryAccount') && project.hasProperty('repositoryPassword')) {
                    credentials {
                        username project.repositoryAccount
                        password project.repositoryPassword
                    }
                }
            }
        } else {
            maven { // for gradle fast plugin
                name 'Artifactory-snapshot'
                url 'https://artifactory5.exactpro.com/artifactory/libs-snapshot'
            }
            maven {
                name 'Artifactory-release'
                url 'https://artifactory5.exactpro.com/artifactory/libs-release'
            }
            maven {
                name 'Sonatype_snapshots'
                url 'https://central.sonatype.com/repository/maven-snapshots/'
            }
            maven {
                name 'Sonatype_releases'
                url 'https://repo1.maven.org/maven2/'
            }
        }
        mavenCentral()
    }

    configurations {
        testArtifacts
        compile.exclude module: 'avalon-framework-api'
        compile.exclude module: 'guava-jdk5'
        testCompile.extendsFrom(compileOnly) // to fully emulate provided configuration

        all {
            transitive = true
            resolutionStrategy {
                // don't cache changing modules at all
                cacheChangingModulesFor 0, 'seconds'
                cacheDynamicVersionsFor 0, 'seconds'
            }
        }
    }

    configurations {
        force
        force.setCanBeConsumed(false)
    }

    getProject().afterEvaluate {
        configurations.force.incoming.resolutionResult.allDependencies { dep ->
            if (dep instanceof ResolvedDependencyResult && dep.selected.moduleVersion instanceof ModuleVersionIdentifier) {
                ModuleVersionIdentifier id = dep.selected.moduleVersion as ModuleVersionIdentifier
                def patchVersionRange = id.version
                def parts = id.version.split("\\.")
                if (parts.size() == 3) {
                    if (parts[1].isInteger() && parts[2].isInteger()) {
                        def left = "[" + parts[0] + "." + parts[1] + ".0, "
                        def right = parts[0] + "." + ((parts[1] as Integer) + 1) + ".0)"
                        patchVersionRange = left + right
                    }
                }
                getProject().dependencies.constraints.add(
                        "compile",
                        "${id.group}:${id.name}:${id.version}"
                ) {
                    it.version {
                        it.strictly(patchVersionRange)
                        it.prefer(id.version)
                    }
                }
            }
        }

        project.configurations
            .detachedConfiguration(project
                .configurations
                .compileClasspath
                .incoming
                .dependencies
                .toArray() as Dependency[]
            )
            .resolvedConfiguration
            .rethrowFailure()
    }

    generateVersionClass {
        major               = sailfish_version_major.toInteger()
        minor               = sailfish_version_minor.toInteger()
        maintenance         = project.revision.toInteger()
        // Redefined for Core and FrontEnd sub projects
        min_core_revision   = project.min_core_revision.toInteger()
        build               = build_number.toInteger()
        branch              = project.branch
        artifactName        = project.name
    }

    jar {
        manifest {
            attributes('Implementation-Version': "${revision}")
            attributes('Build_Name': "${project.name}")
            attributes('Build_Number': "${build_number}")
            attributes('Git_Hash': "${git_hash}")
            attributes('Project_Name': "${collectDependencies.repository}-${project.name}")
        }
    }

    clean {
        delete genDir
        delete extDir
        delete providedDir
    }

    compileKotlin {
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }
    compileTestKotlin {
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }

    task saveDependencies (type: Copy) {
        from configurations.compile
        into "${project.buildDir}/dependencies"
    }

    task testsJar(type: Jar, dependsOn: classes) {
        classifier = 'tests'
        from sourceSets.test.output
    }

    task zipWorkspaceData(type: Zip) {
        classifier = 'data'
        includeEmptyDirs = false
        duplicatesStrategy = 'EXCLUDE'

        from mainWorkspaceDir
        from genWorkspaceDir
        from externalWorkspaceDir
    }

    test.dependsOn serviceLoaderBuild
    def testArtifact = artifacts.add('testArtifacts', testsJar) {
        classifier 'test-artifact'
    }

    publishing {
        publications {
            MavenJava(MavenPublication) {
                from components.java
                artifact testsJar
                groupId group
                version project.version
                pom {
                    name = project.name
                    packaging = 'jar'
                    description = rootProject.description
                    url = vcs_url
                    scm {
                        url = vcs_url
                    }
                    licenses {
                        license {
                            name = 'The Apache License, Version 2.0'
                            url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                        }
                    }
                    developers {
                        developer {
                            id = 'developer'
                            name = 'developer'
                            email = 'developer@exactpro.com'
                        }
                    }
                    scm {
                        url = vcs_url
                    }
                }
            }
        }

        repositories {
            maven {
                name 'MavenLocal' // for local builds only
                url sharedDir
            }
        }
    }

    tasks.withType(Sign) {
        onlyIf { project.hasProperty('signing.keyId') &&
                project.hasProperty('signing.password')&&
                project.hasProperty('signing.secretKeyRingFile')
        }
    }

    signing {
        sign publishing.publications.MavenJava
    }

    dependencies {
        compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1'
        compile group: 'com.sun.xml.bind', name: 'jaxb-core', version: '2.3.0.1'
        compile group: 'com.sun.xml.bind', name: 'jaxb-impl', version: '2.3.1'
        compile group: 'javax.activation', name: 'activation', version: '1.1.1'
        compile group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: "${kotlin_version}"
        compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: "${kotlin_version}"
        compile group: 'io.github.microutils', name: 'kotlin-logging', version: '1.7.8'
        compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: "${fasterxml_jackson_version}"
        force group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1'
        force group: 'com.sun.xml.bind', name: 'jaxb-core', version: '2.3.0.1'
        force group: 'com.sun.xml.bind', name: 'jaxb-impl', version: '2.3.1'
        force group: 'javax.activation', name: 'activation', version: '1.1.1'
        force group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: "${kotlin_version}"
        force group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: "${kotlin_version}"
        force group: 'io.github.microutils', name: 'kotlin-logging', version: '1.7.8'
        force group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: "${fasterxml_jackson_version}"
        components.all(SailfishCapabilities)
    }

    jacoco {
        toolVersion = '0.8.5'
    }

    task allDeps(type: DependencyReportTask) {}
}

def getDate(String format) {
    def date = new Date()
    def formattedDate = date.format(format)
    return formattedDate
}

@CompileStatic
class SailfishCapabilities implements ComponentMetadataRule {
    final static Map<String, List<String>> SAILFISH_MODULES = [
            "quickfixj-core": ["com.exactpro.quickfixj:quickfixj-core","org.quickfixj:quickfixj-core"],
            "mina-core": ["com.exactpro.mina:apache-mina-core", "org.apache.mina:mina-core"]
    ]

    void execute(ComponentMetadataContext context) {
        SAILFISH_MODULES.each { key, val ->
            context.details.with {
                if(val.contains("${id.group}:${id.name}" as String)) {
                    allVariants {
                        it.withCapabilities {
                            it.addCapability(key,key, id.version)
                        }
                    }
                }
            }
        }
    }
}
dependencyCheck {
    scanProjects = [':BackEnd:Core:sailfish-common', ':BackEnd:Core:sailfish-core', ':BackEnd:Service:service-fix', ':BackEnd:Service:service-itch', ':BackEnd:Service:service-ntg', ':BackEnd:Service:service-fast', ':BackEnd:Service:service-tcpip', ':BackEnd:Service:service-http', ':BackEnd:Service:service-soup']
    format='ALL'
    failBuildOnCVSS=5
}