/*
 * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * 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.json.JsonSlurper
import org.apache.tools.ant.taskdefs.condition.Os

plugins {
    id "de.undercouch.download" version "4.1.1"
    id "net.researchgate.release" version "2.8.0"
    id "maven-publish"
}

def jdkModules = ""

configurations {
    zip
}

def ballerinaJreLinuxZip = file("$buildDir/distributions/ballerina-jre-linux-64-${project.version}.zip")
def ballerinaJreLinuxARMZip = file("$buildDir/distributions/ballerina-jre-linux-arm-64-${project.version}.zip")
def ballerinaJreWindowsZip = file("$buildDir/distributions/ballerina-jre-windows-64-${project.version}.zip")
def ballerinaJreMacOSZip = file("$buildDir/distributions/ballerina-jre-macos-64-${project.version}.zip")
def ballerinaJreMacOSARMZip = file("$buildDir/distributions/ballerina-jre-macos-arm-64-${project.version}.zip")

def targetedOSName = project.hasProperty('targetedOS') ? project.targetedOS : Os.isFamily(Os.FAMILY_MAC) ? "mac" : Os.isFamily(Os.FAMILY_UNIX) ? "linux" : "windows"

task getModuleList {
    // Reads default modules included in AdoptOpenJre 21
    def defaultModuleFile = new File("$projectDir/resources/adoptOpenJre21_modules.json")
    def defaultModules = new JsonSlurper().parseText(defaultModuleFile.text).modules.join(',')

    // Reads additional modules required for ballerina runtime.
    def additionalModuleFile = new File("$projectDir/resources/additional_modules.json")
    def additionalModules = new JsonSlurper().parseText(additionalModuleFile.text).modules.join(',')
    jdkModules = "${defaultModules},${additionalModules}"
}

task downloadJdkforLinux(type: Download) {
    src project.linuxJdkUrl
    dest new File("$buildDir/temp/downloads/", "jdk-linux.tar.gz")
    overwrite false
    onlyIfModified true
}

task downloadJdkforLinuxARM(type: Download) {
    src project.linuxARMJdkUrl
    dest new File("$buildDir/temp/downloads/", "jdk-linux-arm.tar.gz")
    overwrite false
    onlyIfModified true
}

task downloadJdkforWindows(type: Download) {
    src project.windowsJdkUrl
    dest new File("$buildDir/temp/downloads/", "jdk-windows.zip")
    overwrite false
    onlyIfModified true
}

task downloadJdkforMac(type: Download) {
    src project.macJdkUrl
    dest new File("$buildDir/temp/downloads/", "jdk-macOS.tar.gz")
    overwrite false
    onlyIfModified true
}

task downloadJdkforMacARM(type: Download) {
    src project.macARMJdkUrl
    dest new File("$buildDir/temp/downloads/", "jdk-macOS-arm.tar.gz")
    overwrite false
    onlyIfModified true
}

task extractJdkForLinux(type: Copy, dependsOn: downloadJdkforLinux) {
    from tarTree(downloadJdkforLinux.dest)
    into "$buildDir/temp/extracted/jdk-linux"
    includeEmptyDirs = false
}

task extractJdkForLinuxARM(type: Copy, dependsOn: downloadJdkforLinuxARM) {
    from tarTree(downloadJdkforLinuxARM.dest)
    into "$buildDir/temp/extracted/jdk-linux-arm"
    includeEmptyDirs = false
}

task extractJdkForWindows(type: Copy, dependsOn: downloadJdkforWindows) {
    from zipTree(downloadJdkforWindows.dest)
    into "$buildDir/temp/extracted/jdk-windows"
    includeEmptyDirs = false
}

task extractJdkForMac(type: Copy, dependsOn: downloadJdkforMac) {
    from tarTree(downloadJdkforMac.dest)
    into "$buildDir/temp/extracted/jdk-macos"
    includeEmptyDirs = false
}

task extractJdkForMacARM(type: Copy, dependsOn: downloadJdkforMacARM) {
    from tarTree(downloadJdkforMacARM.dest)
    into "$buildDir/temp/extracted/jdk-macos-arm"
    includeEmptyDirs = false
}

task assembleJreForLinux(type: Exec, dependsOn: extractJdkForLinux) {
    workingDir "$buildDir/temp/extracted/jdk-linux/jdk-${project.jdkVersion}/bin"
    commandLine "$buildDir/temp/extracted/jdk-linux/jdk-${project.jdkVersion}/bin/jlink",
            '--module-path', "$buildDir/temp/extracted/jdk-linux/jdk-${project.jdkVersion}/jmods",
            '--add-modules', jdkModules,
            '--output', "$buildDir/temp/generated/ballerina-jre-linux-64/jdk-${project.jdkVersion}-jre"
}

task assembleJreForLinuxARM(type: Exec, dependsOn: extractJdkForLinuxARM) {
    workingDir "$buildDir/temp/extracted/jdk-linux-arm/jdk-${project.jdkVersion}/bin"
    commandLine "$buildDir/temp/extracted/jdk-linux-arm/jdk-${project.jdkVersion}/bin/jlink",
            '--module-path', "$buildDir/temp/extracted/jdk-linux-arm/jdk-${project.jdkVersion}/jmods",
            '--add-modules', jdkModules,
            '--output', "$buildDir/temp/generated/ballerina-jre-linux-arm-64/jdk-${project.jdkVersion}-jre"
}

task assembleJreForWindows(type: Exec, dependsOn: extractJdkForWindows) {
    workingDir "$buildDir/temp/extracted/jdk-windows/jdk-${project.jdkVersion}/bin"
    commandLine "$buildDir/temp/extracted/jdk-windows/jdk-${project.jdkVersion}/bin/jlink",
            '--module-path', "$buildDir/temp/extracted/jdk-windows/jdk-${project.jdkVersion}/jmods",
            '--add-modules', jdkModules,
            '--output', "$buildDir/temp/generated/ballerina-jre-windows-64/jdk-${project.jdkVersion}-jre"
}

task assembleJreForMac(type: Exec, dependsOn: extractJdkForMac) { // Check for Content/Home directory
    workingDir "$buildDir/temp/extracted/jdk-macos/jdk-${project.jdkVersion}/Contents/Home/bin"
    commandLine "$buildDir/temp/extracted/jdk-macos/jdk-${project.jdkVersion}/Contents/Home/bin/jlink",
            '--module-path', "$buildDir/temp/extracted/jdk-macos/jdk-${project.jdkVersion}/jmods",
            '--add-modules', jdkModules,
            '--output', "$buildDir/temp/generated/ballerina-jre-macos-64/jdk-${project.jdkVersion}-jre"
}

task assembleJreForMacARM(type: Exec, dependsOn: extractJdkForMacARM) { // Check for Content/Home directory
    workingDir "$buildDir/temp/extracted/jdk-macos-arm/jdk-${project.jdkVersion}/Contents/Home/bin"
    commandLine "$buildDir/temp/extracted/jdk-macos-arm/jdk-${project.jdkVersion}/Contents/Home/bin/jlink",
            '--module-path', "$buildDir/temp/extracted/jdk-macos-arm/jdk-${project.jdkVersion}/jmods",
            '--add-modules', jdkModules,
            '--output', "$buildDir/temp/generated/ballerina-jre-macos-arm-64/jdk-${project.jdkVersion}-jre"
}

task packageJreForLinux(type: Zip, dependsOn: assembleJreForLinux) {
    from fileTree("$buildDir/temp/generated/ballerina-jre-linux-64/")
    archiveName "ballerina-jre-linux-64-${project.version}.zip"
    destinationDirectory = file("$buildDir/distributions/")
    outputs.file ballerinaJreLinuxZip
}

task packageJreForLinuxARM(type: Zip, dependsOn: assembleJreForLinuxARM) {
    from fileTree("$buildDir/temp/generated/ballerina-jre-linux-arm-64/")
    archiveName "ballerina-jre-linux-arm-64-${project.version}.zip"
    destinationDirectory = file("$buildDir/distributions/")
    outputs.file ballerinaJreLinuxARMZip
}

task packageJreForWindows(type: Zip, dependsOn: assembleJreForWindows) {
    from fileTree("$buildDir/temp/generated/ballerina-jre-windows-64/")
    archiveName "ballerina-jre-windows-64-${project.version}.zip"
    destinationDirectory = file("$buildDir/distributions/")
    outputs.file ballerinaJreWindowsZip
}

task packageJreForMac(type: Zip, dependsOn: assembleJreForMac) {
    from fileTree("$buildDir/temp/generated/ballerina-jre-macos-64/")
    archiveName "ballerina-jre-macos-64-${project.version}.zip"
    destinationDirectory = file("$buildDir/distributions/")
    outputs.file ballerinaJreMacOSZip
}

task packageJreForMacARM(type: Zip, dependsOn: assembleJreForMacARM) {
    from fileTree("$buildDir/temp/generated/ballerina-jre-macos-arm-64/")
    archiveName "ballerina-jre-macos-arm-64-${project.version}.zip"
    destinationDirectory = file("$buildDir/distributions/")
    outputs.file ballerinaJreMacOSARMZip
}

def moduleVersion = project.version
if (moduleVersion.indexOf('-') != -1) {
    moduleVersion = moduleVersion.substring(0, moduleVersion.indexOf('-'))
}

task build {
    println("Building for Operating System: " + targetedOSName)

    if (targetedOSName == Os.FAMILY_MAC || targetedOSName == "macos") {
        dependsOn packageJreForMac
    } else if (targetedOSName == "macos-arm") {
        dependsOn packageJreForMacARM
    } else if (targetedOSName == Os.FAMILY_UNIX || targetedOSName == "linux") {
        dependsOn packageJreForLinux
    } else if (targetedOSName == "linux-arm") {
        dependsOn packageJreForLinuxARM
    } else if (targetedOSName == Os.FAMILY_WINDOWS || targetedOSName == "windows") {
        dependsOn packageJreForWindows
    }
}

artifacts {
    zip file: ballerinaJreLinuxZip, builtBy: packageJreForLinux
    zip file: ballerinaJreLinuxARMZip, builtBy: packageJreForLinuxARM
    zip file: ballerinaJreWindowsZip, builtBy: packageJreForWindows
    zip file: ballerinaJreMacOSZip, builtBy: packageJreForMac
    zip file: ballerinaJreMacOSARMZip, builtBy: packageJreForMacARM
}

release {
    failOnPublishNeeded = false
    failOnUpdateNeeded = false
    failOnUnversionedFiles = false
    failOnCommitNeeded = false
    buildTasks = ['build']
    versionPropertyFile = 'gradle.properties'
    tagTemplate = 'v$version'
    newVersionCommitMessage = "Update to next development version "
    preTagCommitMessage = "Prepare release version "
    tagCommitMessage = "Tag release "

    git {
        requireBranch = "release-${moduleVersion}"
        pushToRemote = 'origin'
    }
}

task cleanGeneratedFiles(type: Delete) {
    delete "$buildDir/temp/generated/"
}

task cleanTemporaryFiles(type: Delete) {
    delete "$buildDir/temp/"
}

assembleJreForLinux.dependsOn getModuleList
assembleJreForLinuxARM.dependsOn getModuleList
assembleJreForWindows.dependsOn getModuleList
assembleJreForMac.dependsOn getModuleList
assembleJreForMacARM.dependsOn getModuleList


assembleJreForLinux.dependsOn cleanGeneratedFiles
assembleJreForLinuxARM.dependsOn cleanGeneratedFiles
assembleJreForWindows.dependsOn cleanGeneratedFiles
assembleJreForMac.dependsOn cleanGeneratedFiles
assembleJreForMacARM.dependsOn cleanGeneratedFiles

