// The MIT License (MIT)
//
// Copyright (c) 2007-2018 Broad Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
apply plugin: 'java'
import org.apache.tools.ant.filters.ReplaceTokens

// Define the main class for the application
ext.mainClassName = 'org.broad.igv.ui.Main'

// Set up the ProGuard optimizing task
buildscript {
    repositories {
        flatDir dirs: 'lib_build'
    }
    dependencies {
        classpath ':proguard:'
    }
}

sourceSets {
    main {
        java {
            srcDirs = ['src/main/java', 'src/main/java8']
        }
        resources {
            srcDirs = ['src/main/resources', 'src/main/resources-jlfgr-1_0']
            exclude "**/*LICENSE*", "**/META-INF"
        }
    }
}

configurations {
    jarsToShipUntouched
    compile.extendsFrom jarsToShipUntouched
}

dependencies {
    jarsToShipUntouched fileTree(dir: 'lib', 
                                 include: ['batik-codec-1.10.jar', 'goby-io-igv-1.1.jar', 'log4j-core-2.11.0.jar'])
    compile fileTree(dir: 'lib', include: '*.jar')
    testCompile fileTree(dir: 'test/lib', include: '*.jar')
}

task wrapper(type: Wrapper) {
    gradleVersion = '4.10.1'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

processResources {
    // Set the current timestamp for release builds; pass in a blank property to enable (i.e. -Ptimestamp="" at CLI)
    if (timestamp.equals("")) {
       ext.date = new Date() 
       timestamp = date.format("MM/dd/yyyy hh:mm aa")
       // This is a more filesystem-friendly date format.
       timestamp_fs = date.format("yyyy-MM-dd_HHmmss")
    }

    filesMatching('resources/about.properties') {
        filter (ReplaceTokens,
                tokens: [ VERSION: version, BUILD: buildNumber, DEFAULT_MASTER_RESOURCE_URL: dataServerUrl,
                          TIMESTAMP: timestamp, DEVELOPMENT: development ])
    }
}

jar {
    archiveName = 'igv-minimal.jar'
    manifest {
        attributes(
            "Permissions": "all-permissions",
            "Application-Name": "IGV",
            "Built-By": System.getProperty('user.name'),
            "Main-Class": mainClassName,
            "Class-Path": configurations.compile.collect { it.getName() }.join(' ')
        )
    }
}

task fullJar(type: Jar, dependsOn: jar) {
    // Based on https://discuss.gradle.org/t/removing-dependencies-from-a-jar-file-during-jar-task/5521/3
    archiveName = 'igv.jar'
    from {
        ((configurations.compile - configurations.jarsToShipUntouched) + "${buildDir}/libs/igv-minimal.jar").collect {
            zipTree(it)
        }
    } {
        exclude "META-INF/**"
    }
    
    manifest {
        attributes(
            "Permissions": "all-permissions",
            "Application-Name": "IGV",
            "Built-By": System.getProperty('user.name'),
            "Main-Class": mainClassName,
            "Class-Path": configurations.jarsToShipUntouched.collect { it.getName() }.join(' ')
        )
    }
}

task toolJar(type: Jar, dependsOn: jar) {
    from {
        ((configurations.compile - configurations.jarsToShipUntouched) + "${buildDir}/libs/igv-minimal.jar").collect {
            zipTree(it)
        }
    } {
        exclude "META-INF/**"
    }
    archiveName = 'igvtools.jar'
    manifest {
        attributes(
            "Implementation-Title": "IGVTools",
            "Built-By": System.getProperty('user.name'),
            "Main-Class": "org.broad.igv.tools.IgvTools",
            "Class-Path": configurations.jarsToShipUntouched.collect { it.getName() }.join(' ')
        )
    }
}

task optimizeFullJar(type: proguard.gradle.ProGuardTask, dependsOn: fullJar) {
    // EXPERIMENTAL: Optimize the fullJar to remove unused classes.
    // This still needs tuning for correctness, and as a result we are not distributing the
    // jar it creates.  It is still useful because of the reports it generates, however.
    doFirst { mkdir "proguard_log" }
    
    verbose
    injars "${buildDir}/libs/igv.jar"
    outjars "${buildDir}/libs/igv-OPT.jar"
    // Note that this points to the *JRE* jars.
    libraryjars "${System.getProperty('java.home')}/lib", 
                jarfilter: 'rt.jar,charsets.jar,jce.jar,jfr.jar,jsse.jar,resources.jar,ext/jfxrt.jar'
    libraryjars "lib", jarfilter: 'batik-codec-1.10.jar,goby-io-igv-1.1.jar,log4j-core-2.11.0.jar'
    configuration "lib_build/proguard_full_client.cfg"
    printusage "proguard_log/proguard_full_client_log_${timestamp_fs}.txt"
    printseeds "proguard_log/proguard_full_client_seeds_${timestamp_fs}.txt"
}

task optimizeMinJar(type: proguard.gradle.ProGuardTask, dependsOn: jar) {
    // EXPERIMENTAL: Optimize the minimal jar to remove unused classes (that is, our code base only).
    // As above, needs tuning for correctness.  The IGV-focused report it produces is more useful.
    doFirst { mkdir "proguard_log" }
    
    verbose
    injars "${buildDir}/libs/igv-minimal.jar"
    outjars "${buildDir}/libs/igv-minimal-OPT.jar"
    libraryjars "${System.getProperty('java.home')}/lib", 
                jarfilter: 'rt.jar,charsets.jar,jce.jar,jfr.jar,jsse.jar,resources.jar,ext/jfxrt.jar'
    // This is the difference from the above: consider all dependencies as libraryjars
    libraryjars "lib", filter: '!META-INF/**/module-info.class'
    configuration "lib_build/proguard_min_client.cfg"
    printusage "proguard_log/proguard_min_client_log_${timestamp_fs}.txt"
    printseeds "proguard_log/proguard_min_client_seeds_${timestamp_fs}.txt"
}

tasks.withType(Test) {
    systemProperties = System.getProperties()
    systemProperties['java.awt.headless'] = 'true'
    systemProperties['make.fail'] = 'false'
    systemProperties['include.longrunning'] = 'false'
    systemProperties['ignore.ioexceptions'] = 'false'
    maxHeapSize = '2000m'
    maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
}

task createDist(type: Copy, dependsOn: fullJar)  {
    from ("scripts") {
        include 'igv.bat'
        include 'igv_32.bat'
        include 'igv.command'
        include 'igv.sh'
        include 'readme.txt'
    }
    with copySpec {
            from ("${buildDir}/libs") {
            include 'igv.jar'
        }
        from (configurations.jarsToShipUntouched) { }
        into "lib"
    }

    into "${buildDir}/IGV-dist"
}

task signJars(dependsOn: createDist) {
    doLast {
        // Only sign if the keystoreFile exists 
        ext.keystoreFile = file("${keystore}")
        if (keystoreFile.exists()) {
            ant.jar( update: true, file: "build/IGV-dist/lib/batik-codec-1.10.jar") {
                delegate.manifest { attribute(name: 'Permissions', value: 'all-permissions') }
            }
            ant.jar( update: true, file: "build/IGV-dist/lib/goby-io-igv-1.1.jar") {
                delegate.manifest { attribute(name: 'Permissions', value: 'all-permissions') }
            }
            ant.jar( update: true, file: "build/IGV-dist/lib/log4j-core-2.11.0.jar") {
                delegate.manifest { attribute(name: 'Permissions', value: 'all-permissions') }
            }
            ant.signjar( jar: 'build/IGV-dist/lib/*.jar', keystore:"${keystoreFile.absolutePath}",
                         alias: "${alias}", keypass: "${keyPassword}", storepass: "${storePassword}", tsaurl: "${tsaurl}"
            )
        }
    }
}

task createDistZip(type: Zip, dependsOn: [createDist, signJars]) {
    archiveName = "IGV_${version}.zip"
    destinationDir = file("${buildDir}/distZip")
    baseName = "IGV"
    from "${buildDir}/IGV-dist" exclude "igv.bat"
    into createDistZip.baseName + "_${version}"

    doLast {
        project.exec { commandLine('chmod', '775', createDistZip.archivePath ) }
    }
}

task createMacDist(type: Copy, dependsOn: [createDist, signJars]) {
    with copySpec {
        from ("scripts/mac.app") exclude "Contents/Info.plist.template"
        into "IGV_${version}.app"
    }
    with copySpec {
        from ("scripts/mac.app/Contents/Info.plist.template")
        filter (ReplaceTokens, tokens: [ VERSION: version ])
        rename "Info.plist.template", "Info.plist"
        into "IGV_${version}.app/Contents"
    }
    with copySpec {
        from ("${buildDir}/IGV-dist/lib") include '*.jar'
        into "IGV_${version}.app/Contents/Java"
    }

    into "${buildDir}/IGV-Mac-dist"

    doLast {
        project.exec { commandLine('chmod', '775', "${buildDir}/IGV-Mac-dist/IGV_${version}.app" ) }
    }
}

task createMacDistZip(type: Zip, dependsOn: createMacDist) {
    archiveName = "IGV_${version}.app.zip"
    destinationDir = file("${buildDir}/distZip")
    from "${buildDir}/IGV-Mac-dist"
    
    doLast {
        project.exec { commandLine('chmod', '775', createMacDistZip.archivePath ) }
    }
}

task createWinDistZip(type: Zip, dependsOn: [createDist, signJars]) {
    archiveName = "IGV_Win_${version}.zip"
    destinationDir = file("${buildDir}/distZip")
    baseName = "IGV_Win"
    from("${buildDir}/IGV-dist") {
        exclude "igv.sh"
        exclude "igv.command"
    }
    into createWinDistZip.baseName + "_${version}"

    doLast {
        project.exec { commandLine('chmod', '775', createWinDistZip.archivePath ) }
    }
}

task createToolsDist(type: Copy, dependsOn: toolJar)  {
    from ("scripts") {
        include 'igvtools*'
        include 'igvtools*.bat'
        include 'igvtools*.command'
    }
    with copySpec {
            from ("${buildDir}/libs") {
            include 'igvtools.jar'
        }
        from (configurations.jarsToShipUntouched) { }
        into "lib"
    }
    
    with copySpec { from ("genomes/sizes") { } into "lib/genomes" }

    into "${buildDir}/IGVTools-dist"
}

task createToolsDistZip(type: Zip, dependsOn: createToolsDist) {
    destinationDir = file("${buildDir}/distZip")
    archiveName = "igvtools_${version}.zip"
    baseName = "IGVTools"

    from "${buildDir}/IGVTools-dist"
    into createToolsDistZip.baseName + "_${version}"

    doLast {
        project.exec { commandLine('chmod', '775', createToolsDistZip.archivePath ) }
    }
}

build.dependsOn createDistZip,createMacDistZip,createWinDistZip,createToolsDistZip
