import org.apache.tools.ant.taskdefs.condition.Os

buildscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.17'
        classpath 'com.google.gradle:osdetector-gradle-plugin:1.6.0'
        classpath 'com.github.jengelman.gradle.plugins:shadow:5.2.0'
        classpath 'org.springframework.boot:spring-boot-gradle-plugin:2.6.3'
        classpath 'com.gradle:gradle-enterprise-gradle-plugin:3.7' // added for windows build verfication-metadata.xml error
    }
}

configure(rootProject) {
    // remove the 'haveno-*' scripts and 'lib' dir generated by the 'installDist' task
    task clean {
        doLast {
            delete fileTree(dir: rootProject.projectDir, include: 'haveno-*'), 'lib'
        }
    }
}

configure(subprojects) {
    apply plugin: 'java'
    apply plugin: 'com.google.osdetector'
    // Apply the jacoco plugin to add support for test coverage
    apply plugin: 'jacoco'

    sourceCompatibility = JavaVersion.VERSION_11

    ext { // in alphabetical order
        bcVersion = '1.63'
        bitcoinjVersion = '2a80db4'
        codecVersion = '1.13'
        cowwocVersion = '1.2'
        easybindVersion = '1.0.3'
        easyVersion = '4.0.1'
        findbugsVersion = '3.0.2'
        firebaseVersion = '6.2.0'
        fontawesomefxVersion = '8.0.0'
        fontawesomefxCommonsVersion = '9.1.2'
        fontawesomefxMaterialdesignfontVersion = '2.0.26-9.1.2'
        grpcVersion = '1.42.1'
        gsonVersion = '2.8.5'
        guavaVersion = '30.1.1-jre'
        guiceVersion = '4.2.2'
        moneroJavaVersion = '0.7.8'
        httpclient5Version = '5.0'
        hamcrestVersion = '1.3'
        httpclientVersion = '4.5.12'
        httpcoreVersion = '4.4.13'
        ioVersion = '2.6'
        jacksonVersion = '2.12.1'
        javafxVersion = '16'
        javaxAnnotationVersion = '1.2'
        jcsvVersion = '1.4.0'
        jetbrainsAnnotationsVersion = '13.0'
        jfoenixVersion = '9.0.10'
        joptVersion = '5.0.4'
        jsonsimpleVersion = '1.1.1'
        jsonrpc4jVersion = '1.6.0.bisq.1'
        junitVersion = '4.12'
        jupiterVersion = '5.7.0'
        kotlinVersion = '1.3.41'
        knowmXchangeVersion = '5.0.13'
        langVersion = '3.11'
        logbackVersion = '1.1.11'
        loggingVersion = '1.2'
        lombokVersion = '1.18.24'
        mockitoVersion = '4.0.0'
        netlayerVersion = '6797461310f077bbea4f43a3a509c077b0ed8c34' // Netlayer version 0.7.3 with Tor browser version 11.0.14 and tor binary version: 0.4.7.7
        protobufVersion = '3.19.1'
        protocVersion = protobufVersion
        pushyVersion = '0.13.2'
        qrgenVersion = '1.3'
        slf4jVersion = '1.7.30'
        sparkVersion = '2.5.2'
        springBootVersion = '2.5.6'

        os = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os
    }

    repositories {
        mavenCentral()
        //mavenLocal()
        maven { url 'https://jitpack.io' }
        maven { url 'https://mvnrepository.com' }
    }

    dependencies {
        testImplementation "junit:junit:$junitVersion"
    }

    tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
    }

    jacocoTestReport {
        reports {
            xml.enabled true
            html.enabled false
        }
    }
    // Codacy report generated with every build at assets/build/reports/jacoco/test/jacocoTestReport.xml
    test.finalizedBy jacocoTestReport
}


configure([project(':cli'),
           project(':daemon'),
           project(':desktop'),
           project(':monitor'),
           project(':relay'),
           project(':seednode'),
           project(':statsnode'),
           project(':pricenode'),
           project(':inventory'),
           project(':apitest')]) {

    apply plugin: 'application'

    build.dependsOn installDist
    installDist.destinationDir = file('build/app')
    distZip.enabled = false

    // the 'installDist' and 'startScripts' blocks below configure haveno executables to put
    // generated shell scripts in the root project directory, such that users can easily
    // discover and invoke e.g. ./haveno-desktop, ./haveno-seednode, etc.
    // See https://stackoverflow.com/q/46327736 for details.

    installDist {
        doLast {
            // copy generated shell scripts, e.g. `haveno-desktop` directly to the project
            // root directory for discoverability and ease of use

            copy {
                from "$destinationDir/bin"
                into rootProject.projectDir
            }
            // copy libs required for generated shell script classpaths to 'lib' dir under
            // the project root directory
            copy {
                from "$destinationDir/lib"
                into "${rootProject.projectDir}/lib"
            }

            // edit generated shell scripts such that they expect to be executed in the
            // project root dir as opposed to a 'bin' subdirectory
            def windowsScriptFile = file("${rootProject.projectDir}/haveno-${applicationName}.bat")
            windowsScriptFile.text = windowsScriptFile.text.replace(
                'set APP_HOME=%DIRNAME%..', 'set APP_HOME=%DIRNAME%')

            def unixScriptFile = file("${rootProject.projectDir}/haveno-$applicationName")
            unixScriptFile.text = unixScriptFile.text.replace(
                'APP_HOME=$( cd "${APP_HOME:-./}.." && pwd -P ) || exit', 'APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit')

            if (applicationName == 'desktop') {
                def script = file("${rootProject.projectDir}/haveno-$applicationName")
                script.text = script.text.replace(
                    'DEFAULT_JVM_OPTS=""', 'DEFAULT_JVM_OPTS="-XX:MaxRAM=4g"')
            }

            if (applicationName == 'apitest') {
                // Pass the logback config file as a system property to avoid chatty
                // logback startup due to multiple logback.xml files in the classpath
                // (:daemon & :cli).
                def script = file("${rootProject.projectDir}/haveno-$applicationName")
                script.text = script.text.replace(
                    'DEFAULT_JVM_OPTS=""', 'DEFAULT_JVM_OPTS="' +
                    '-Dlogback.configurationFile=apitest/build/resources/main/logback.xml"')
            }

            if (osdetector.os != 'windows')
                delete fileTree(dir: rootProject.projectDir, include: 'haveno-*.bat')
            else
                delete fileTree(dir: rootProject.projectDir, include: 'haveno-*', exclude: '*.bat')
        }
    }

    startScripts {
        // rename scripts from, e.g. `desktop` to `haveno-desktop`
        applicationName = "haveno-$applicationName"
    }
}

configure(project(':proto')) {
    apply plugin: 'com.google.protobuf'

    dependencies {
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "ch.qos.logback:logback-classic:$logbackVersion"
        implementation "ch.qos.logback:logback-core:$logbackVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "com.google.protobuf:protobuf-java:$protobufVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        implementation("io.grpc:grpc-protobuf:$grpcVersion") {
            exclude(module: 'animal-sniffer-annotations')
            exclude(module: 'guava')
        }
        implementation("io.grpc:grpc-stub:$grpcVersion") {
            exclude(module: 'animal-sniffer-annotations')
            exclude(module: 'guava')
        }
    }

    sourceSets.main.java.srcDirs += [
        'build/generated/source/proto/main/grpc',
        'build/generated/source/proto/main/java'
    ]

    protobuf {
        protoc {
            artifact = "com.google.protobuf:protoc:${protocVersion}"
        }
        plugins {
            grpc {
                artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
            }
        }
        generateProtoTasks {
            all()*.plugins { grpc {} }
        }
    }
}

configure(project(':assets')) {
    dependencies {
        implementation("com.github.bisq-network:bitcoinj:$bitcoinjVersion") {
            exclude(module: 'bcprov-jdk15on')
            exclude(module: 'guava')
            exclude(module: 'jsr305')
            exclude(module: 'okhttp')
            exclude(module: 'okio')
            exclude(module: 'protobuf-java')
            exclude(module: 'slf4j-api')
        }
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "org.apache.commons:commons-lang3:$langVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
    }
}


configure(project(':common')) {
    dependencies {
        implementation project(':proto')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "ch.qos.logback:logback-classic:$logbackVersion"
        implementation "ch.qos.logback:logback-core:$logbackVersion"
        implementation("com.github.bisq-network:bitcoinj:$bitcoinjVersion") {
            exclude(module: 'jsr305')
            exclude(module: 'slf4j-api')
            exclude(module: 'guava')
            exclude(module: 'protobuf-java')
            exclude(module: 'bcprov-jdk15on')
            exclude(module: 'okhttp')
            exclude(module: 'okio')
        }
        implementation "com.google.code.findbugs:jsr305:$findbugsVersion"
        implementation "com.google.code.gson:gson:$gsonVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation("com.google.inject:guice:$guiceVersion") {
            exclude(module: 'guava')
        }
        implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
        implementation "com.google.protobuf:protobuf-java:$protobufVersion"
        implementation "commons-io:commons-io:$ioVersion"
        implementation "net.sf.jopt-simple:jopt-simple:$joptVersion"
        implementation "org.apache.commons:commons-lang3:$langVersion"
        implementation "org.bouncycastle:bcpg-jdk15on:$bcVersion"
        implementation "org.jetbrains:annotations:$jetbrainsAnnotationsVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
        runtimeOnly("io.grpc:grpc-netty-shaded:$grpcVersion") {
            exclude(module: 'guava')
            exclude(module: 'animal-sniffer-annotations')
        }

        // override transitive dependency version from 1.5 to the same version just identified by commit number.
        // Remove this if transitive dependency is changed to something else than 1.5
        implementation(group: 'com.github.JesusMcCloud', name: 'jtorctl') { version { strictly "[9b5ba2036b]" } }
        implementation "org.openjfx:javafx-base:$javafxVersion:$os"
        implementation "org.openjfx:javafx-graphics:$javafxVersion:$os"
    }
}

configure(project(':p2p')) {
    dependencies {
        implementation project(':proto')
        implementation project(':common')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "com.google.protobuf:protobuf-java:$protobufVersion"
        implementation "org.fxmisc.easybind:easybind:$easybindVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        implementation("com.github.bisq-network.netlayer:tor.external:$netlayerVersion") {
            exclude(module: 'slf4j-api')
        }
        implementation("com.github.bisq-network.netlayer:tor.native:$netlayerVersion") {
            exclude(module: 'slf4j-api')
        }
        implementation("com.github.bisq-network:bitcoinj:$bitcoinjVersion") {
            exclude(module: 'bcprov-jdk15on')
            exclude(module: 'guava')
            exclude(module: 'jsr305')
            exclude(module: 'okhttp')
            exclude(module: 'okio')
            exclude(module: 'protobuf-java')
            exclude(module: 'slf4j-api')
        }
        implementation("com.google.inject:guice:$guiceVersion") {
            exclude(module: 'guava')
        }
        implementation("org.apache.httpcomponents:httpclient:$httpclientVersion") {
            exclude(module: 'commons-codec')
        }
        testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
        testCompileOnly "org.projectlombok:lombok:$lombokVersion"
        testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
        testImplementation "ch.qos.logback:logback-core:$logbackVersion"
        testImplementation "org.apache.commons:commons-lang3:$langVersion"
        testImplementation("org.mockito:mockito-core:$mockitoVersion")

        implementation "org.openjfx:javafx-base:$javafxVersion:$os"
        implementation "org.openjfx:javafx-graphics:$javafxVersion:$os"
    }
}

configure(project(':core')) {
    dependencies {
        implementation project(':proto')
        implementation project(':assets')
        implementation project(':common')
        implementation project(':p2p')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "ch.qos.logback:logback-classic:$logbackVersion"
        implementation "ch.qos.logback:logback-core:$logbackVersion"
        implementation "com.fasterxml.jackson.core:jackson-core:$jacksonVersion"
        implementation "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion"
        implementation "com.google.code.findbugs:jsr305:$findbugsVersion"
        implementation "com.google.code.gson:gson:$gsonVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "com.google.protobuf:protobuf-java:$protobufVersion"
        implementation "commons-codec:commons-codec:$codecVersion"
        implementation "commons-io:commons-io:$ioVersion"
        implementation "net.sf.jopt-simple:jopt-simple:$joptVersion"
        implementation "org.apache.commons:commons-lang3:$langVersion"
        implementation "org.apache.httpcomponents:httpcore:$httpcoreVersion"
        implementation "org.fxmisc.easybind:easybind:$easybindVersion"
        implementation "org.jetbrains:annotations:$jetbrainsAnnotationsVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        implementation("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion") {
            exclude(module: 'jackson-annotations')
        }
        implementation("com.github.bisq-network.netlayer:tor.native:$netlayerVersion") {
            exclude(module: 'slf4j-api')
        }
        implementation("com.github.bisq-network.netlayer:tor.external:$netlayerVersion") {
            exclude(module: 'slf4j-api')
        }
        implementation("com.github.bisq-network:bitcoinj:$bitcoinjVersion") {
            exclude(module: 'bcprov-jdk15on')
            exclude(module: 'guava')
            exclude(module: 'jsr305')
            exclude(module: 'okhttp')
            exclude(module: 'okio')
            exclude(module: 'protobuf-java')
            exclude(module: 'slf4j-api')
        }
        implementation("com.github.bisq-network:jsonrpc4j:$jsonrpc4jVersion") {
            exclude(module: 'base64')
            exclude(module: 'httpcore-nio')
        }
        implementation("com.google.inject:guice:$guiceVersion") {
            exclude(module: 'guava')
        }
        implementation("org.apache.httpcomponents:httpclient:$httpclientVersion") {
            exclude(module: 'commons-codec')
        }
        testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
        testCompileOnly "org.projectlombok:lombok:$lombokVersion"
        testImplementation "com.natpryce:make-it-easy:$easyVersion"
        testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
        testImplementation "org.mockito:mockito-core:$mockitoVersion"

        implementation "org.openjfx:javafx-base:$javafxVersion:$os"
        implementation "org.openjfx:javafx-graphics:$javafxVersion:$os"
        implementation("io.github.monero-ecosystem:monero-java:$moneroJavaVersion") {
            exclude(module: 'jackson-core')
            exclude(module: 'jackson-annotations')
            exclude(module: 'jackson-databind')
            exclude(module: 'bcprov-jdk15on')
            exclude(group: 'org.slf4j', module: 'slf4j-simple')
        }
    }

    test {
        systemProperty 'jdk.attach.allowAttachSelf', true
    }

    task havenoDeps {
        doLast {
            // get monero binaries download url
            Map moneroBinaries = [
                'linux'         : 'https://github.com/haveno-dex/monero/releases/download/testing8/monero-bins-haveno-linux.tar.gz',
                'linux-sha256'  : 'a222bdae08e5464d1b751e6301144a904578bef37c75444c46aef762299c0b92',
                'mac'           : 'https://github.com/haveno-dex/monero/releases/download/testing8/monero-bins-haveno-mac.tar.gz',
                'mac-sha256'    : 'fbebd9eb40550cd992bf9e1f946741d5adc564c428b9d4c78981363235c4be89',
                'windows'       : 'https://github.com/haveno-dex/monero/releases/download/testing8/monero-bins-haveno-windows.zip',
                'windows-sha256': 'c9e6150ba9cb8b35b7c63ac8786610e3c37725a973e35c09e6fbbfe20430302a'
            ]

            String osKey
            if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                osKey = 'windows'
            } else if (Os.isFamily(Os.FAMILY_MAC)) {
                osKey = 'mac'
            } else {
                osKey = 'linux'
            }

            String moneroDownloadUrl = moneroBinaries[osKey]
            String moneroSHA256Hash = moneroBinaries[osKey + '-sha256']
            String moneroArchiveFileName = moneroDownloadUrl.tokenize('/').last()
            String localnetDirName = '.localnet'
            File localnetDir = new File(project.rootDir, localnetDirName)
            localnetDir.mkdirs()
            File moneroArchiveFile = new File(localnetDir, moneroArchiveFileName)
            ext.downloadAndVerifyDependencies(moneroDownloadUrl, moneroSHA256Hash, moneroArchiveFile)

            // extract if dependencies are missing or if archive was updated
            File monerodFile
            File moneroRpcFile
            if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                monerodFile = new File(localnetDir, 'monerod.exe')
                moneroRpcFile = new File(localnetDir, 'monero-wallet-rpc.exe')
            } else {
                monerodFile = new File(localnetDir, 'monerod')
                moneroRpcFile = new File(localnetDir, 'monero-wallet-rpc')
            }
            if (ext.dependencyDownloadedAndVerified || !monerodFile.exists() || !moneroRpcFile.exists()) {
                if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                    ext.extractArchiveZip(moneroArchiveFile, localnetDir)
                } else {
                    ext.extractArchiveTarGz(moneroArchiveFile, localnetDir)
                }

                // add the current platform's monero dependencies into the resources folder for installation
                copy {
                    from "${monerodFile}"
                    into "${project(':core').projectDir}/src/main/resources/bin"
                }
                copy {
                    from "${moneroRpcFile}"
                    into "${project(':core').projectDir}/src/main/resources/bin"
                }
            }
        }

        ext.extractArchiveTarGz = { File tarGzFile, File destinationDir ->
            println "Extracting tar.gz ${tarGzFile}"
            // Gradle's tar extraction preserves permissions (crucial for jpackage to function correctly)
            copy {
                from tarTree(resources.gzip(tarGzFile))
                into destinationDir
            }
            println "Extracted to ${destinationDir}"
        }

        ext.extractArchiveZip = { File zipFile, File destinationDir ->
            println "Extracting zip ${zipFile}..."
            ant.unzip(src: zipFile, dest: destinationDir)
            println "Extracted to ${destinationDir}"
        }

        ext.downloadAndVerifyDependencies = { String archiveURL, String archiveSHA256, File destinationArchiveFile ->
            ext.dependencyDownloadedAndVerified = false
            // if archive exists, check to see if its already up to date
            if (destinationArchiveFile.exists()) {
                println "Verifying existing archive ${destinationArchiveFile}"
                ant.archiveHash = archiveSHA256
                ant.checksum(file: destinationArchiveFile, algorithm: 'SHA-256', property: '${archiveHash}', verifyProperty: 'existingHashMatches')
                if (ant.properties['existingHashMatches'] != 'true') {
                    println "Existing archive does not match hash ${archiveSHA256}"
                } else {
                    println "Existing archive matches hash"
                    return
                }
            }

            println "Downloading ${archiveURL}"
            ant.get(src: archiveURL, dest: destinationArchiveFile)
            println 'Download saved to ' + destinationArchiveFile

            println 'Verifying checksum for downloaded binary ...'
            ant.archiveHash = archiveSHA256
            // use a different verifyProperty name from existing verification or it will always fail
            ant.checksum(file: destinationArchiveFile, algorithm: 'SHA-256', property: '${archiveHash}', verifyProperty: 'downloadedHashMatches')
            if (ant.properties['downloadedHashMatches'] != 'true') {
                ant.fail('Checksum mismatch: Downloaded archive has a different checksum than expected')
            }
            println 'Checksum verified'
            ext.dependencyDownloadedAndVerified = true
        }
    }

    processResources.dependsOn havenoDeps // before both test and build
}

configure(project(':cli')) {
    mainClassName = 'bisq.cli.CliMain'

    dependencies {
        implementation project(':proto')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "ch.qos.logback:logback-classic:$logbackVersion"
        implementation "ch.qos.logback:logback-core:$logbackVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "com.google.protobuf:protobuf-java:$protobufVersion"
        implementation "net.sf.jopt-simple:jopt-simple:$joptVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        implementation("io.grpc:grpc-core:$grpcVersion") {
            exclude(module: 'animal-sniffer-annotations')
            exclude(module: 'guava')
        }
        implementation("io.grpc:grpc-stub:$grpcVersion") {
            exclude(module: 'animal-sniffer-annotations')
            exclude(module: 'guava')
        }
        runtimeOnly("io.grpc:grpc-netty-shaded:$grpcVersion") {
            exclude(module: 'animal-sniffer-annotations')
            exclude(module: 'guava')
        }
        testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
        testCompileOnly "org.projectlombok:lombok:$lombokVersion"
        testImplementation "org.bitbucket.cowwoc:diff-match-patch:$cowwocVersion"
        testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
        testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
        testRuntimeOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
        testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")
    }

    test {
        useJUnitPlatform()
    }
}

configure(project(':desktop')) {
    apply plugin: 'com.github.johnrengelman.shadow'
    apply from: 'package/package.gradle'

    version = '1.0.0-SNAPSHOT'

    jar.manifest.attributes(
        "Implementation-Title": project.name,
        "Implementation-Version": version)

    mainClassName = 'bisq.desktop.app.HavenoAppMain'

    tasks.withType(AbstractArchiveTask) {
        preserveFileTimestamps = false
        reproducibleFileOrder = true
    }

    sourceSets.main.resources.srcDirs += ['src/main/java'] // to copy fxml and css files

    dependencies {
        implementation project(':assets')
        implementation project(':common')
        implementation project(':proto')
        implementation project(':p2p')
        implementation project(':core')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "ch.qos.logback:logback-classic:$logbackVersion"
        implementation "ch.qos.logback:logback-core:$logbackVersion"
        implementation "com.google.code.gson:gson:$gsonVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "com.google.protobuf:protobuf-java:$protobufVersion"
        implementation "com.googlecode.jcsv:jcsv:$jcsvVersion"
        implementation "com.jfoenix:jfoenix:$jfoenixVersion"
        implementation "commons-io:commons-io:$ioVersion"
        implementation "de.jensd:fontawesomefx-commons:$fontawesomefxCommonsVersion"
        implementation "de.jensd:fontawesomefx-materialdesignfont:$fontawesomefxMaterialdesignfontVersion"
        implementation "de.jensd:fontawesomefx:$fontawesomefxVersion"
        implementation "net.glxn:qrgen:$qrgenVersion"
        implementation "org.apache.commons:commons-lang3:$langVersion"
        implementation "org.bouncycastle:bcpg-jdk15on:$bcVersion"
        implementation "org.fxmisc.easybind:easybind:$easybindVersion"
        implementation "org.jetbrains:annotations:$jetbrainsAnnotationsVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        implementation("com.github.bisq-network:bitcoinj:$bitcoinjVersion") {
            exclude(module: 'bcprov-jdk15on')
            exclude(module: 'guava')
            exclude(module: 'jsr305')
            exclude(module: 'okhttp')
            exclude(module: 'okio')
            exclude(module: 'protobuf-java')
            exclude(module: 'slf4j-api')
        }
        implementation("com.google.inject:guice:$guiceVersion") {
            exclude(module: 'guava')
        }
        testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
        testCompileOnly "org.projectlombok:lombok:$lombokVersion"
        testImplementation "com.natpryce:make-it-easy:$easyVersion"
        testImplementation "org.mockito:mockito-core:$mockitoVersion"

        implementation("io.github.monero-ecosystem:monero-java:$moneroJavaVersion") {
            exclude(module: 'jackson-core')
            exclude(module: 'jackson-annotations')
            exclude(module: 'jackson-databind')
            exclude(module: 'bcprov-jdk15on')
            exclude(group: 'org.slf4j', module: 'slf4j-simple')
        }
        implementation "org.openjfx:javafx-controls:$javafxVersion:$os"
        implementation "org.openjfx:javafx-fxml:$javafxVersion:$os"
        implementation "org.openjfx:javafx-swing:$javafxVersion:$os"
        implementation "org.openjfx:javafx-base:$javafxVersion:$os"
        implementation "org.openjfx:javafx-graphics:$javafxVersion:$os"
    }

    test {
        systemProperty 'jdk.attach.allowAttachSelf', true
    }
}


configure(project(':monitor')) {
    mainClassName = 'bisq.monitor.Monitor'

    test {
        useJUnitPlatform()
        testLogging {
            events "passed", "skipped", "failed"
        }
    }

    dependencies {
        implementation project(':assets')
        implementation project(':common')
        implementation project(':core')
        implementation project(':p2p')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "ch.qos.logback:logback-classic:$logbackVersion"
        implementation "ch.qos.logback:logback-core:$logbackVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        implementation("com.github.bisq-network.netlayer:tor.external:$netlayerVersion") {
            exclude(module: 'slf4j-api')
        }
        implementation("com.github.bisq-network.netlayer:tor.native:$netlayerVersion") {
            exclude(module: 'slf4j-api')
        }
        implementation("com.google.inject:guice:$guiceVersion") {
            exclude(module: 'guava')
        }
        testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
        testCompileOnly "org.projectlombok:lombok:$lombokVersion"
        testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
        testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
        testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")

        implementation "org.openjfx:javafx-base:$javafxVersion:$os"
        implementation "org.openjfx:javafx-graphics:$javafxVersion:$os"
    }
}


configure(project(':pricenode')) {
    apply plugin: "org.springframework.boot"

    apply plugin: 'io.spring.dependency-management'

    mainClassName = 'bisq.price.Main'

    version = file("src/main/resources/version.txt").text.trim()

    jar.manifest.attributes(
        "Implementation-Title": project.name,
        "Implementation-Version": version)

    ext['log4j2.version'] = '2.17.0'

    dependencies {
        implementation project(":common")
        implementation project(":core")
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "com.google.code.gson:gson:$gsonVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "commons-codec:commons-codec:$codecVersion"
        implementation "org.apache.httpcomponents:httpcore:$httpcoreVersion"
        implementation("org.apache.httpcomponents:httpclient:$httpclientVersion") {
            exclude(module: 'commons-codec')
        }
        implementation("org.knowm.xchange:xchange-binance:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-bitbay:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-bitfinex:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-bitflyer:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-bitstamp:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-btcmarkets:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-cexio:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-coinbasepro:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-coinmarketcap:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-coinmate:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-coinone:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-exmo:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-hitbtc:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-huobi:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-independentreserve:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-kraken:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-luno:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-mercadobitcoin:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-paribu:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-poloniex:$knowmXchangeVersion")
        implementation("org.knowm.xchange:xchange-quoine:$knowmXchangeVersion")
        implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
        testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
        testCompileOnly "org.projectlombok:lombok:$lombokVersion"
        testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
        testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
        testImplementation "org.mockito:mockito-core:$mockitoVersion"
        testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")
    }

    test {
        useJUnitPlatform()

        // Disabled by default, since spot provider tests include connections to external API endpoints
        // Can be enabled by adding -Dtest.pricenode.includeSpotProviderTests=true to the gradle command:
        // ./gradlew test -Dtest.pricenode.includeSpotProviderTests=true
        if (System.properties['test.pricenode.includeSpotProviderTests'] != 'true') {
            project.logger.lifecycle('Pricenode: Skipping spot provider tests')
            exclude 'bisq/price/spot/providers/**'
        }
    }

    task stage {
        dependsOn assemble
    }
}


configure(project(':relay')) {
    mainClassName = 'bisq.relay.RelayMain'

    dependencies {
        implementation project(':common')
        implementation "ch.qos.logback:logback-classic:$logbackVersion"
        implementation "ch.qos.logback:logback-core:$logbackVersion"
        implementation("com.google.firebase:firebase-admin:$firebaseVersion") {
            exclude(module: 'commons-logging')
            exclude(module: 'grpc-auth')
            exclude(module: 'httpclient')
            exclude(module: 'httpcore')
        }
        implementation "com.sparkjava:spark-core:$sparkVersion"
        implementation "com.turo:pushy:$pushyVersion"
        implementation "commons-codec:commons-codec:$codecVersion"
        implementation "io.grpc:grpc-auth:$grpcVersion"
    }
}


configure(project(':seednode')) {
    apply plugin: 'com.github.johnrengelman.shadow'

    mainClassName = 'bisq.seednode.SeedNodeMain'

    dependencies {
        implementation project(':common')
        implementation project(':p2p')
        implementation project(':core')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        implementation("com.google.inject:guice:$guiceVersion") {
            exclude(module: 'guava')
        }
        testImplementation "org.mockito:mockito-core:$mockitoVersion"
    }
}


configure(project(':statsnode')) {
    mainClassName = 'bisq.statistics.StatisticsMain'

    dependencies {
        implementation project(':common')
        implementation project(':p2p')
        implementation project(':core')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        implementation("com.google.inject:guice:$guiceVersion") {
            exclude(module: 'guava')
        }
    }
}

configure(project(':daemon')) {
    mainClassName = 'bisq.daemon.app.HavenoDaemonMain'

    dependencies {
        implementation project(':proto')
        implementation project(':common')
        implementation project(':p2p')
        implementation project(':core')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "ch.qos.logback:logback-classic:$logbackVersion"
        implementation "ch.qos.logback:logback-core:$logbackVersion"
        implementation "com.google.code.gson:gson:$gsonVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "com.google.protobuf:protobuf-java:$protobufVersion"
        implementation "org.apache.commons:commons-lang3:$langVersion"
        implementation "org.jetbrains:annotations:$jetbrainsAnnotationsVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        implementation("com.github.bisq-network:bitcoinj:$bitcoinjVersion") {
            exclude(module: 'bcprov-jdk15on')
            exclude(module: 'guava')
            exclude(module: 'jsr305')
            exclude(module: 'okhttp')
            exclude(module: 'okio')
            exclude(module: 'protobuf-java')
            exclude(module: 'slf4j-api')
        }
        implementation("com.google.inject:guice:$guiceVersion") {
            exclude(module: 'guava')
        }
        implementation("io.grpc:grpc-protobuf:$grpcVersion") {
            exclude(module: 'animal-sniffer-annotations')
            exclude(module: 'guava')
        }
        implementation("io.grpc:grpc-stub:$grpcVersion") {
            exclude(module: 'animal-sniffer-annotations')
            exclude(module: 'guava')
        }
        runtimeOnly("io.grpc:grpc-netty-shaded:$grpcVersion") {
            exclude(module: 'animal-sniffer-annotations')
            exclude(module: 'guava')
        }
        testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
        testCompileOnly "org.projectlombok:lombok:$lombokVersion"
        testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
        testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
        testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")

        implementation("io.github.monero-ecosystem:monero-java:$moneroJavaVersion") {
            exclude(module: 'jackson-core')
            exclude(module: 'jackson-annotations')
            exclude(module: 'jackson-databind')
            exclude(module: 'bcprov-jdk15on')
            exclude(group: 'org.slf4j', module: 'slf4j-simple')
        }
        implementation "org.openjfx:javafx-base:$javafxVersion:$os"
        implementation "org.openjfx:javafx-graphics:$javafxVersion:$os"
    }
}

configure(project(':inventory')) {
    apply plugin: 'com.github.johnrengelman.shadow'

    mainClassName = 'bisq.inventory.InventoryMonitorMain'

    dependencies {
        implementation project(':common')
        implementation project(':p2p')
        implementation project(':core')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "ch.qos.logback:logback-classic:$logbackVersion"
        implementation "ch.qos.logback:logback-core:$logbackVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "com.sparkjava:spark-core:$sparkVersion"
        implementation "org.jetbrains:annotations:$jetbrainsAnnotationsVersion"
        implementation("com.google.inject:guice:$guiceVersion") {
            exclude(module: 'guava')
        }
    }
}

configure(project(':apitest')) {
    mainClassName = 'bisq.apitest.ApiTestMain'

    // We have to disable the :apitest 'test' task by default because we do not want
    // to interfere with normal builds.  To run JUnit tests in this subproject:
    // Run a normal build and install dao-setup files first, then run:
    //              'gradle  :apitest:test -DrunApiTests=true'
    test.enabled = System.getProperty("runApiTests") == "true"

    test {
        useJUnitPlatform()
        outputs.upToDateWhen { false }          // Don't use previously cached test outputs.
        testLogging {
            showStackTraces = true              // Show full stack traces in the console.
            exceptionFormat = "full"
            // Show passed & failed tests, and anything printed to stderr by the tests in the console.
            // Do not show skipped tests in the console;  they are shown in the html report.
            events "passed", "failed", "standardError"
        }

        afterSuite { desc, result ->
            if (!desc.parent) {
                println("${result.resultType} " +
                    "[${result.testCount} tests, " +
                    "${result.successfulTestCount} passed, " +
                    "${result.failedTestCount} failed, " +
                    "${result.skippedTestCount} skipped]  html report contains skipped test info")

                // Show report link if all tests passed in case you want to see more detail, stdout, skipped, etc.
                if (result.resultType == TestResult.ResultType.SUCCESS) {
                    DirectoryReport htmlReport = getReports().getHtml()
                    String reportUrl = new org.gradle.internal.logging.ConsoleRenderer()
                        .asClickableFileUrl(htmlReport.getEntryPoint())
                    println("REPORT  " + reportUrl)
                }
            }
        }
    }

    dependencies {
        implementation project(':proto')
        implementation project(':common')
        implementation project(':core')
        implementation project(':seednode')
        implementation project(':desktop')
        implementation project(':daemon')
        implementation project(':cli')
        annotationProcessor "org.projectlombok:lombok:$lombokVersion"
        compileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
        compileOnly "org.projectlombok:lombok:$lombokVersion"
        implementation "ch.qos.logback:logback-classic:$logbackVersion"
        implementation "ch.qos.logback:logback-core:$logbackVersion"
        implementation "com.google.code.gson:gson:$gsonVersion"
        implementation "com.google.guava:guava:$guavaVersion"
        implementation "com.google.protobuf:protobuf-java:$protobufVersion"
        implementation "net.sf.jopt-simple:jopt-simple:$joptVersion"
        implementation "org.apache.commons:commons-lang3:$langVersion"
        implementation "org.slf4j:slf4j-api:$slf4jVersion"
        implementation("com.github.bisq-network:bitcoinj:$bitcoinjVersion") {
            exclude(module: 'bcprov-jdk15on')
            exclude(module: 'guava')
            exclude(module: 'jsr305')
            exclude(module: 'okhttp')
            exclude(module: 'okio')
            exclude(module: 'protobuf-java')
            exclude(module: 'slf4j-api')
        }
        implementation("io.grpc:grpc-protobuf:$grpcVersion") {
            exclude(module: 'animal-sniffer-annotations')
            exclude(module: 'guava')
        }
        implementation("io.grpc:grpc-stub:$grpcVersion") {
            exclude(module: 'animal-sniffer-annotations')
            exclude(module: 'guava')
        }
        testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
        testCompileOnly "org.projectlombok:lombok:$lombokVersion"
        testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
        testImplementation "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
        testRuntimeOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
        testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")
    }
}