plugins {
    id 'java'
    id 'eclipse'
    id 'idea'
    // id "org.sonarqube" version "3.3"
}

repositories {
    mavenLocal()
    mavenCentral()
}

java {
    sourceCompatibility = JavaVersion.VERSION_21
    targetCompatibility = JavaVersion.VERSION_21
}

// Eclipse and VS Code use bin
buildDir = 'target'

version = '3.0'

project.ext {
    updateDir="$projectDir/build/update"
    updateProperties="$updateDir/update.properties"
    updateLibDir="$projectDir/build/update_lib"
    updateLibProperties="$updateLibDir/update_lib.properties"
    distDir="$projectDir/build/bgerp"
    classesPath="$buildDir/classes/java/main"
    versionPackage='org/bgerp/app/dist/inst/module'
    appJarName='bgerp.jar'
    libJarName='lib.jar'
    distBuildDir="$buildDir/bgerp"
}

eclipse {
    classpath {
        // speed up of initial start, change if needed
        downloadJavadoc = false
        downloadSources = false
    }
}

idea {
    module {}
}

/* sonarqube {
    properties {
        property "sonar.projectKey", "org.bgerp"
        property "sonar.organization", "bgerp"
        property "sonar.host.url", "https://sonarcloud.io"
    }
} */

configurations {
    all {
        transitive = false
    }
    doc {
        transitive = true
    }
    itest.extendsFrom(implementation)
    tool.extendsFrom(implementation)
    // to be compiled inside IDE
    compileClasspath.extendsFrom(implementation, tool, itest)
}

dependencies {
    // add app libraries below with explicitly required dependencies after each of them
    implementation 'log4j:log4j:1.2.17'
    implementation 'org.apache.logging.log4j:log4j-api:2.11.2'

    implementation 'org.apache.tomcat.embed:tomcat-embed-jasper:9.0.50'
    implementation files('build/lib/tomcat-embed-core-9.0.51.bgerp.jar') // also contains Servlet API
    runtimeOnly 'org.apache.tomcat.embed:tomcat-embed-el:9.0.50'
    runtimeOnly 'org.eclipse.jdt:ecj:3.26.0'
    runtimeOnly 'javax.annotation:javax.annotation-api:1.3.2'
    implementation 'javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.2' // there are extended tags in the project
    implementation 'org.apache.taglibs:taglibs-standard-impl:1.2.5' // there are extended tags in the project

    implementation 'org.apache.struts:struts-core:1.3.10' // not more released since 2008, the recommended replacement is struts2-core
    implementation 'org.apache.struts:struts-extras:1.3.10'
    implementation 'org.apache.struts:struts-taglib:1.3.10'
    runtimeOnly 'commons-chain:commons-chain:1.2'
    runtimeOnly 'commons-digester:commons-digester:2.1'

    implementation 'com.sun.mail:jakarta.mail:2.0.2'
    implementation 'com.sun.activation:jakarta.activation:2.0.1'
    implementation 'org.apache.james:apache-mime4j-dom:0.8.11' // version 0.8.12 and newer fails MessageParserTest
    implementation 'org.apache.james:apache-mime4j-core:0.8.11'

    implementation 'commons-beanutils:commons-beanutils:1.11.0' // DynActionForm

    implementation 'org.apache.commons:commons-dbcp2:2.13.0'
    implementation 'org.apache.commons:commons-pool2:2.12.1'
    runtimeOnly 'com.mysql:mysql-connector-j:9.4.0'

    implementation 'commons-fileupload:commons-fileupload:1.6.0'
    implementation 'commons-io:commons-io:2.20.0'

    implementation 'org.apache.commons:commons-jexl3:3.5.0'
    runtimeOnly 'commons-logging:commons-logging:1.2'

    implementation 'org.apache.httpcomponents:fluent-hc:4.5.7'
    implementation 'org.apache.httpcomponents:httpclient:4.5.7'
    implementation 'org.apache.httpcomponents:httpcore:4.4.11'

    implementation 'com.fasterxml.jackson.core:jackson-core:2.20.0'
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.20.0'
    implementation 'com.fasterxml.jackson.core:jackson-annotations:2.20'

    implementation 'ar.com.fdvs:DynamicJasper:5.3.9'
    implementation 'net.sf.jasperreports:jasperreports:6.21.5' // 7.0.3 doesn't work with DynamicJasper:5.3.9
    runtimeOnly 'com.github.librepdf:openpdf:1.3.30'

    implementation 'org.apache.poi:poi:4.0.1' // directly used in Callboard plugin, for making Russian work days table
    // dep 'org.apache.commons:commons-collections4'

    // Asterisk
    implementation 'org.asteriskjava:asterisk-java:3.41.0'
    // dep 'com.google.guava:guava'
    // dep 'org.reflections:reflections'
    // dep 'org.slf4j:slf4j-api'

    // Document, filling out PDF forms
    implementation 'com.itextpdf:itextpdf:5.5.13.4'

    // License check
    implementation 'org.bouncycastle:bcprov-jdk18on:1.82'
    implementation 'org.bouncycastle:bcpkix-jdk18on:1.82'
    implementation 'com.hierynomus:sshj:0.30.0' // version 0.40.0 fails LicenseTest
    implementation 'net.i2p.crypto:eddsa:0.3.0'
    runtimeOnly 'org.slf4j:slf4j-api:2.0.17'
    runtimeOnly 'org.slf4j:slf4j-reload4j:2.0.17'

    // Telegram
    implementation 'org.telegram:telegrambots:6.9.7.1'
    implementation 'org.telegram:telegrambots-meta:6.9.7.1'

    // separated libraries without transitive dependencies should be added the end of the list
    implementation 'org.apache.commons:commons-collections4:4.5.0'
    runtimeOnly 'commons-collections:commons-collections:3.2.2' // delete later
    implementation 'org.apache.commons:commons-lang3:3.18.0'
    implementation 'com.google.guava:guava:33.5.0-jre'
    implementation 'org.jsoup:jsoup:1.21.2'
    implementation 'org.reflections:reflections:0.10.2'
    implementation 'org.javassist:javassist:3.30.2-GA'
    implementation 'org.json:json:20250517'
    implementation 'commons-net:commons-net:3.11.1'
    implementation 'com.cronutils:cron-utils:9.2.1'

    // documentation library
    doc 'org.pzdcdoc:pzdcdoc:2.8'

    // tool libraries
    tool 'org.apache.ant:ant:1.10.12'

    // unit tests of the main code
    testImplementation 'junit:junit:4.13.2' // the recommended replacement is junit-jupiter-api
    testImplementation 'org.hamcrest:hamcrest-core:1.3' // version 3.0 fails

    // integration test
    itest 'org.testng:testng:7.11.0'
    itest 'org.jcommander:jcommander:2.0'
    // Selenium related libs.
    // itest 'org.seleniumhq.selenium:selenium-java:3.141.59'
    // itest 'org.seleniumhq.selenium:selenium-api:3.141.59'
    // itest 'org.seleniumhq.selenium:selenium-remote-driver:3.141.59'
    // itest 'org.seleniumhq.selenium:selenium-support:3.141.59'
    // itest 'org.seleniumhq.selenium:selenium-chrome-driver:3.141.59'
    // itest 'com.squareup.okhttp3:okhttp:3.13.1'
    // itest 'org.jetbrains.kotlin:kotlin-stdlib:1.3.21'
    // itest 'com.squareup.okio:okio:2.2.2'
    // itest 'net.bytebuddy:byte-buddy:1.9.10'
    // itest 'org.apache.commons:commons-exec:1.3'
}

sourceSets {
    main {
        java {
            srcDir 'src'
            srcDir 'dyn'
            srcDir 'custom/src'
        }
        resources {
            srcDir 'src'
            srcDir 'custom/src'
        }
        // makes warning on assigning simple output.classesDir
        output.resourcesDir = "$buildDir/classes/java/main"
    }
    test {
        java {
            srcDir 'srcx/test'
        }
        resources {
            srcDir 'srcx/test'
        }
    }
    tool {
        java {
            srcDir 'buildSrc/src/main/java'
            srcDir 'srcx/tool'
        }
        resources {
            srcDir 'srcx/tool'
        }
        compileClasspath = configurations.tool + sourceSets.main.output
        runtimeClasspath = compileClasspath + output
    }
    itest {
        java {
            srcDir 'srcx/itest'
        }
        resources {
            srcDir 'srcx/itest'
        }
        // makes warning on assigning simple output.classesDir
        output.resourcesDir = "$buildDir/classes/java/itest"
        compileClasspath = configurations.itest + sourceSets.main.output
        runtimeClasspath = compileClasspath + output + configurations.runtimeClasspath
    }
}

// supporting functions, not found if be extracted to a separated .gradle file

def getBranchName() {
    def branchName = 'git rev-parse --abbrev-ref HEAD'.execute().text.trim()
    println "Branch name: $branchName"
    return branchName
}

def getBuild() {
    def buildProperties = new Properties()
    file("$updateProperties").withInputStream { stream -> buildProperties.load(stream) }
    def build = buildProperties.get('build.number')
    println "Build: $build"
    return build
}

/*
    Gets numeric change ID 'NNNNN' from GIT branch name like: 'pNNNNN-some-description'.
    Returns empty string in case of another branch name.
*/
def getChangeId() {
    def branchName = getBranchName()

    def m  = branchName =~ /^p(\d+)\-/
    if (!m) return "";

    def changeId = m[0][1]
    println "Change ID: $changeId"

    return changeId
}

/*
    Gets numeric change ID 'NNNNN' from GIT branch name like: 'pNNNNN-some-description'.
    Throws an exception in case of another branch name.
*/
def getChangeIdOrThrow() {
    def branchName = getBranchName()

    def m  = branchName =~ /^p(\d+)\-/
    if (!m) throw new GradleException("Incorrect branch name: $branchName")

    def changeId = m[0][1]
    println "Change ID: $changeId"

    return changeId
}

/*
    Gets title for doc sites.
*/
def getTitle() {
    def title = version + "." + getBuild()
    def changeId = getChangeId()

    // master release
    if (changeId == '15055') {
        title += '.0'
    }
    // not stable release
    else if (changeId != '11862') {
        title += '.' + changeId
    }

    return title;
}

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

tasks.withType(JavaExec) {
    jvmArgs "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", "--add-opens", "java.base/java.io=ALL-UNNAMED"
}

// 'compileJava' is executed prior to 'classes' from 'dependsOn'
compileJava {
    doFirst {
        println "Checking existance of 'custom' directory"
        def custom = file("custom");
        if (custom.exists()) {
            custom.renameTo("_custom");
            println "Renaming directory 'custom' to '_custom'"
        }
    }
}

task doc(type: JavaExec, description: 'Builds manual') {
    doFirst {
        def title = getTitle()

        args '--attribute'
        args "pzdc-site-title=$title"

        if (file("$buildDir/javadoc").exists()) {
            args '--attribute'
            args 'pzdc-javadoc=../javadoc'
        }

        println "Generator's args: ${args}"
    }
    mustRunAfter 'updateProperties'
    mustRunAfter 'jdoc'
    classpath =  configurations.doc
    mainClass = 'org.pzdcdoc.Generator'
    args '--in', 'srcx/doc', '--out', "$buildDir/doc"
}

task jdoc(type: Javadoc, description: 'Builds JavaDoc API') {
    options.encoding = 'UTF-8'
    failOnError = false
    classpath = configurations.runtimeClasspath
    source = sourceSets.main.allJava
    title = "BGERP ${->getTitle()} API"
    destinationDir = file("$buildDir/javadoc")
}

task zdoc(type: Zip, description: 'Builds documentation zip archive') {
    archiveFileName.set("$buildDir/doc.zip")
    mustRunAfter 'doc', 'jdoc'
    from("$buildDir") {
        include 'doc/**', 'javadoc/**'
    }
}

task touchChanges(description: "Creates file 'build/changes.<PROCESS_ID>.txt' if missing") {
    doFirst {
        def processId = getChangeIdOrThrow()
        def changesFile = file("$projectDir/build/changes.${processId}.txt")
        if (!changesFile.exists())
            changesFile.text = ""
    }
}

task touchChangesLib(description: "Creates file 'build/changes.lib.txt' if missing") {
    doFirst {
        def changesLibFile = file("$projectDir/build/changes.lib.txt")
        if (!changesLibFile.exists())
            changesLibFile.text = ""
    }
}

task checkChanges(description: 'Checks existance of build/changes.<PROCESS_ID>.txt file') {
    doFirst {
        def processId = getChangeIdOrThrow()
        def changesFileName = "build/changes.${processId}.txt"
        def changesFile = file("$projectDir/$changesFileName")
        if (!changesFile.exists() || changesFile.text.isBlank())
            throw new GradleException("Changes file '$changesFileName' not found or blank. Create it using './gradlew touchChanges' and fill out.")
    }
}

apply from: "build/build.gradle"

task changesFile(type: JavaExec, dependsOn: 'compileToolJava', description: 'Concatenates build/changes.*.txt files to build/changes.txt') {
    classpath =  sourceSets.tool.runtimeClasspath
    mainClass = 'org.bgerp.tool.ChangesFile'
    args version, "${->getBuild()}", 'build/changes.txt'
}

task changesRss(type: JavaExec, dependsOn: 'compileToolJava', description: 'Generates build/changes.rss out of build/changes.txt') {
    mustRunAfter 'changesFile'
    classpath =  sourceSets.tool.runtimeClasspath
    mainClass = 'org.bgerp.tool.ChangesRss'
    args version, 'build/changes.txt', 'build/changes.xml'
}

task changesDoc(type: JavaExec, description: "Adjusts changes link for the current build in documentation files") {
    classpath = sourceSets.tool.runtimeClasspath
    mainClass = 'org.bgerp.tool.ChangesDoc'
    args "${->getBuild()}", 'srcx/doc'
}

apply from: "build/publish.gradle"

task startServer(type: JavaExec, dependsOn: 'classes', description: 'Starts server with bgerp.properties') {
    classpath =  sourceSets.main.runtimeClasspath
    mainClass = 'org.bgerp.Server'
    args 'start'
    systemProperties = [
        'bgerp.setup.data': findProperty('bgerp.setup.data') ?: 'bgerp',
        'java.net.preferIPv4Stack': true
    ]
}

apply from: "test.gradle"
