/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

plugins {
    id 'java'
    id 'distribution'
    id 'signing'
    alias(libs.plugins.nebula)
    alias(libs.plugins.checksum)
    alias(libs.plugins.setupbuilder)
}

apply from: "$rootDir/buildscripts/generate-version-file.gradle"
apply from: "$rootDir/buildscripts/utils.gradle"

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

import org.apache.tools.ant.filters.ReplaceTokens
import org.gradle.crypto.checksum.Checksum

configurations {
    dbArtifacts
    defaultsGenerator.extendsFrom(dbArtifacts)
    dotNetClient
    dbZip {
        canBeConsumed = true
        canBeResolved = false
    }
    dbRelease {
        canBeConsumed = true
        canBeResolved = false
    }
    localDefaults {
        canBeConsumed = true
        canBeResolved = false
    }
}

dependencies {
    dbArtifacts project(':ignite-runner')
    dotNetClient project(path: ":platforms", configuration: "dotNet")
    dbArtifacts libs.slf4j.jdk14

    defaultsGenerator project(path: ':ignite-runner', configuration: 'defaultsGenerator')
}

def tokens = [
        PRODUCT_NAME        : 'ignite3db',
        PACKAGE_NAME        : 'ignite3-db',
        PRODUCT_DISPLAY_NAME: 'Apache Ignite',
        APP_JAR             : "${project(':ignite-runner').name}-${project(':ignite-runner').version}.jar".toString(),
        MAIN_CLASS          : 'org.apache.ignite.internal.app.IgniteRunner',
        ADD_OPENS           : project.addOpens.join(' '),
        CONF_FILE           : 'ignite-config.conf',
]

def tokensLin = tokens + [
        VARS_FILE_NAME      : 'vars.env',
        BOOTSTRAP_FILE_NAME : 'bootstrap-functions.sh',
        SETUP_JAVA_FILE_NAME: 'setup-java.sh'
]

def tokensWin = tokens + [
        VARS_FILE_NAME  : 'vars.bat',
        BOOTSTRAP_FILE_NAME : 'bootstrap-functions.bat'
]

// ZIP packaging

def zipStartScriptTokensCommon = [
        APP_LOG_DIR         : 'log', // java logging does not support env variables, using relative path here
]

def zipStartScriptTokensLin = tokensLin + [
        WORK_DIR            : '${IGNITE_HOME}/work',
        LOG_DIR             : '${IGNITE_HOME}/log',
        LIB_DIR             : '${IGNITE_HOME}/lib',
        CONF_DIR            : '${IGNITE_HOME}/etc',
        INSTALL_DIR         : '${IGNITE_HOME}',
]

def zipStartScriptTokensWin = tokensWin + [
        WORK_DIR        : '%IGNITE_HOME%\\work',
        LOG_DIR         : '%IGNITE_HOME%\\log',
        LIB_DIR         : '%IGNITE_HOME%\\lib',
        CONF_DIR        : '%IGNITE_HOME%\\etc',
        INSTALL_DIR     : '%IGNITE_HOME%',
]

def replaceZipScriptVarsCommon = tasks.register('replaceZipScriptVarsCommon', Copy) {
    from 'zip/ignite.java.util.logging.properties'

    filter(ReplaceTokens, tokens: zipStartScriptTokensCommon)

    into "$buildDir/zip/"
}

def replaceZipScriptVarsLin = tasks.register('replaceZipScriptVarsLin', Copy) {
    from "$rootDir/packaging/common/linux"
    from 'zip/linux'

    filter(ReplaceTokens, tokens: zipStartScriptTokensLin)

    into "$buildDir/zip/"
}

def replaceZipScriptVarsWin = tasks.register('replaceZipScriptVarsWin', Copy) {
    from "$rootDir/packaging/common/windows"
    from 'zip/windows'

    filter(ReplaceTokens, tokens: zipStartScriptTokensWin)

    into "$buildDir/zip/"
}

def replaceZipScriptVars = tasks.register('replaceZipScriptVars') {
    dependsOn replaceZipScriptVarsCommon
    dependsOn replaceZipScriptVarsLin
    dependsOn replaceZipScriptVarsWin
}

def copyConfig = tasks.register('copyConfig', Copy) {
    from "$rootDir/packaging/config/ignite-config.conf"
    into layout.buildDirectory.dir("config")
}

def generateConfigDefaults = tasks.register('generateConfigDefaults', JavaExec) {
    classpath = configurations.defaultsGenerator
    mainClass = "org.apache.ignite.internal.configuration.generator.DefaultsGenerator"
    dependsOn copyConfig
    args layout.buildDirectory.file("config/ignite-config.conf").get()
    outputs.file layout.buildDirectory.file("config/ignite-config.conf")
}

distributions {
    main {
        distributionBaseName = 'ignite3-db'
        contents {
            // create empty dirs that are required to start Ignite
            into('') {
                File.createTempDir().with {
                    ["log", "etc", "work"].each { new File(absolutePath, it).mkdirs() }
                    from(absolutePath) {
                        includeEmptyDirs = true
                    }
                }
            }
            into('') {
                from "$rootDir/LICENSE"
                from "$rootDir/NOTICE"
                from "$rootDir/assembly/README.md"
            }
            into('etc') {
                from "$buildDir/zip/${zipStartScriptTokensLin.VARS_FILE_NAME}"
                from "$buildDir/zip/${zipStartScriptTokensWin.VARS_FILE_NAME}"
                from generateConfigDefaults
                from "$buildDir/zip/ignite.java.util.logging.properties"
                from createVersionFile
            }
            into('bin') {
                fileMode 0755
                from "$buildDir/zip/ignite3db"
                from "$buildDir/zip/ignite3db.bat"
            }
            into('lib') {
                from configurations.dbArtifacts
                from "$buildDir/zip/${zipStartScriptTokensLin.BOOTSTRAP_FILE_NAME}"
                from "$buildDir/zip/${zipStartScriptTokensLin.SETUP_JAVA_FILE_NAME}"
                from "$buildDir/zip/${zipStartScriptTokensWin.BOOTSTRAP_FILE_NAME}"
            }
            into('lib/dotnet') {
                from configurations.dotNetClient
            }
        }
    }
}

distZip.dependsOn replaceZipScriptVars
distTar.dependsOn replaceZipScriptVars
installDist.dependsOn replaceZipScriptVars

def createChecksums = tasks.register('createChecksums', Checksum) {
    inputFiles.from distZip
    checksumAlgorithm = Checksum.Algorithm.SHA512
}

artifacts {
    dbZip(distZip)
    localDefaults generateConfigDefaults
}

// Explicitly create task so that the resulting artifact is not added to the configuration
def signDbZip = tasks.register('signDbZip', Sign) {
    sign configurations.dbZip
}

// RPM/DEB packaging

def packageTokens = tokens + tokensLin + [
        USERNAME            : 'ignite',
        GROUPNAME           : 'ignite',
        INSTALL_DIR         : '/usr/lib/ignite3db',
        WORK_DIR            : '/var/lib/ignite3db',
        LOG_DIR             : '/var/log/ignite3db',
        LIB_DIR             : '/usr/lib/ignite3db/lib',
        CONF_DIR            : '/etc/ignite3db',
        APP_LOG_DIR         : '/var/log/ignite3db',
        PID_DIR             : '/var/run/ignite3db',
]


def replacePackageScriptVars = tasks.register('replacePackageScriptVars', Copy) {
    from 'linux'
    from 'ignite.java.util.logging.properties'
    from "$rootDir/packaging/common/linux"
    filter(ReplaceTokens, tokens: packageTokens)
    into "$buildDir/linux"
}

buildRpm {
    dependsOn replacePackageScriptVars

    installUtils file("$buildDir/linux/service/vars.env")
    installUtils file("$buildDir/linux/common.sh")
    preInstall file("$buildDir/linux/preInstall.sh")
    postInstall file("$buildDir/linux/postInstall.sh")
    preUninstall file("$buildDir/linux/rpm/preUninstall.sh")
    postUninstall file("$buildDir/linux/rpm/postUninstall.sh")
}

buildDeb {
    signingKeyId = project.findProperty("signing.keyId")
    signingKeyPassphrase = project.findProperty("signing.password")
    signingKeyRingFile = project.hasProperty("signing.secretKeyRingFile") ? file(project.property("signing.secretKeyRingFile")) : null
    dependsOn replacePackageScriptVars

    installUtils file("$buildDir/linux/service/vars.env")
    installUtils file("$buildDir/linux/common.sh")
    preInstall file("$buildDir/linux/preInstall.sh")
    postInstall file("$buildDir/linux/postInstall.sh")
    preUninstall file("$buildDir/linux/deb/preUninstall.sh")
    postUninstall file("$buildDir/linux/deb/postUninstall.sh")
}

ospackage {
    license "ASL 2.0"
    packageName packageTokens.PACKAGE_NAME
    packageGroup "System Environment/Daemons"
    url "https://ignite.apache.org"
    user packageTokens.USERNAME
    packageDescription "This package will install Apache Ignite"
    os LINUX
    release getCommitNum()

    into(packageTokens.CONF_DIR) {
        from("$buildDir/linux/service/vars.env")
        from "$buildDir/linux/ignite.java.util.logging.properties"
        from generateConfigDefaults

        fileMode 0660
        fileType CONFIG | NOREPLACE

        // TODO https://github.com/nebula-plugins/gradle-ospackage-plugin/issues/463
        eachFile {
            def configFile = "${packageTokens.CONF_DIR}/${it.getName()}"

            if (!configurationFiles.contains(configFile)) {
                configurationFile(configFile)
            }
        }
    }

    // These are not config files, don't mark them as such so they are overwritten on upgrade
    into(packageTokens.CONF_DIR) {
        from createVersionFile
        from sourceSets.main.resources

        fileMode 0660
    }

    into(packageTokens.INSTALL_DIR) {
        into('') {
            from "$buildDir/linux/service/ignite3db.service"
            from "$buildDir/linux/service/ignite3db.conf"
            from("$buildDir/linux/start.sh") {
                fileMode 0755
            }
        }

        into('lib') {
            from configurations.dbArtifacts
            from "$buildDir/linux/${tokensLin.BOOTSTRAP_FILE_NAME}"
            from "$buildDir/linux/${tokensLin.SETUP_JAVA_FILE_NAME}"
        }
        into('lib/dotnet') {
            from configurations.dotNetClient
        }
    }
}

if (project.hasProperty('prepareRelease')) {
    artifacts {
        dbRelease(file("$buildDir/distributions")) {
            builtBy signDbZip, buildDeb, buildRpm
        }
        dbRelease(file("$buildDir/checksums")) {
            builtBy createChecksums
        }
    }
}

setupBuilder {
    vendor = "Apache Software Foundation"
    application = "Apache Ignite"
    description = "Apache Ignite is a distributed database for high-performance computing with in-memory speed"
    appIdentifier = "ignite3-db"

    // '-SNAPSHOT' is not valid in Windows versions
    version = project.version.toString().replace("-SNAPSHOT", "")

    // Actually a classpath
    mainJar = "lib\\*"
    mainClass = "org.apache.ignite.internal.app.IgniteRunner"

    licenseFile = "$rootDir/LICENSE"

    msi {
        languages = ["en-US"]
    }

    service {
        // The working directory of the service, relative to installation root
        workDir = "."

        jvm = '%JAVA_HOME%\\bin\\server\\jvm.dll'

        javaVMArguments = project.addOpens + [
                "-Dio.netty.tryReflectionSetAccessible=true",
                "-Djava.util.logging.config.file=etc\\ignite.java.util.logging.properties",
                "-Dio.netty.tryReflectionSetAccessible=true"
        ]

        startArguments = "--node-name node1 --work-dir work --config-path etc\\ignite-config.conf"
    }

    into('') {
        into('') {
            from("$rootDir/LICENSE")
            from("$rootDir/NOTICE")
            from("$rootDir/assembly/README.md")
        }
        into('log') {
            from('log')
        }
        into('etc') {
            from generateConfigDefaults
            from createVersionFile
        }
        into('etc') {
            from("ignite.java.util.logging.properties")
            filter(ReplaceTokens, tokens: [LOG_DIR: 'log'])
        }
        into('lib') {
            from configurations.dbArtifacts
        }
        into('lib/dotnet') {
            from configurations.dotNetClient
        }
    }
}

// Disable these tasks as we're using buildDeb/buildRpm tasks from the nebula plugin
tasks.named('deb') {
    onlyIf {
        logger.error("Don't use 'deb' task, use 'buildDeb' instead")
        return false
    }
}

tasks.named('rpm') {
    onlyIf {
        logger.error("Don't use 'rpm' task, use buildRpm instead")
        return false
    }
}
