/*
 * Copyright (c) 2022, 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 org.apache.tools.ant.taskdefs.condition.Os

plugins {
    id 'groovy'
}

description = 'Ballerina - GraphQL Tests'

def packageName = "graphql"
def packageOrg = "ballerina"
def tomlVersion = stripBallerinaExtensionVersion("${project.version}")
def ballerinaTomlFilePlaceHolder = new File("${project.rootDir}/build-config/resources/BallerinaTest.toml")
def testCommonTomlFilePlaceHolder = new File("${project.rootDir}/build-config/resources/BallerinaTestCommon.toml")
def ballerinaDist = "${project.rootDir}/target/ballerina-runtime"
def distributionBinPath =  "${ballerinaDist}/bin"
def testCoverageParam = "--code-coverage --coverage-format=xml --includes=io.ballerina.stdlib.graphql.*:ballerina.graphql*"
def testSuites = [
    "graphql-advanced-test-suite",
    "graphql-client-test-suite",
    "graphql-dataloader-test-suite",
    "graphql-interceptor-test-suite",
    "graphql-security-test-suite",
    "graphql-service-test-suite",
    "graphql-subgraph-test-suite",
    "graphql-subscription-test-suite"
]
def testCommonPackage = "graphql-test-common"

def stripBallerinaExtensionVersion(String extVersion) {
    if (extVersion.matches(project.ext.timestampedVersionRegex)) {
        def splitVersion = extVersion.split('-');
        if (splitVersion.length > 3) {
            def strippedValues = splitVersion[0..-4]
            return strippedValues.join('-')
        } else {
            return extVersion
        }
    } else {
        return extVersion.replace("${project.ext.snapshotVersion}", "")
    }
}

task updateTomlFiles {
     doLast {
        testSuites.each { testPackage ->
            def ballerinaTomlFile =  new File("${project.projectDir}/${testPackage}/Ballerina.toml")
            def newBallerinaToml = ballerinaTomlFilePlaceHolder.text.replace("@project.version@", project.version)
            newBallerinaToml = newBallerinaToml.replace("@toml.version@", tomlVersion)
            newBallerinaToml = newBallerinaToml.replace("@test.common@", testCommonPackage.replaceAll("-", "_"))
            newBallerinaToml = newBallerinaToml.replace("@package.name@", testPackage.replaceAll("-", "_"))
            ballerinaTomlFile.text = newBallerinaToml
        }
    }
    def ballerinaTomlFile =  new File("${project.projectDir}/${testCommonPackage}/Ballerina.toml")
    def newBallerinaToml = testCommonTomlFilePlaceHolder.text.replace("@project.version@", project.version)
    newBallerinaToml = newBallerinaToml.replace("@toml.version@", tomlVersion)
    newBallerinaToml = newBallerinaToml.replace("@package.name@", testCommonPackage.replaceAll("-", "_"))
    ballerinaTomlFile.text = newBallerinaToml
}

task commitTomlFiles {
    doLast {
        def files = "${project.projectDir}/${testCommonPackage}/Ballerina.toml ${project.projectDir}/${testCommonPackage}/Dependencies.toml "
        testSuites.each{ testPackage ->
            files += "${project.projectDir}/${testPackage}/Ballerina.toml ${project.projectDir}/${testPackage}/Dependencies.toml "
        }

        project.exec {
            ignoreExitValue true
            if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                commandLine 'cmd', '/c', "git commit -m \"[Automated] Update the native jar versions\" ${files}"
            } else {
                commandLine 'sh', '-c', "git commit -m '[Automated] Update the native jar versions' ${files}"
            }
        }
    }
}

def groupParams = ""
def disableGroups = ""
def debugParams = ""
def balJavaDebugParam = ""
def graalvmFlag = ""
def testParams = ""
def skipTests = false

task initializeVariables {
    if (project.hasProperty("groups")) {
        groupParams = "--groups ${project.findProperty('groups')}"
    }
    if (project.hasProperty("disable")) {
        disableGroups = "--disable-groups ${project.findProperty("disable")}"
    }
    if (project.hasProperty("debug")) {
        debugParams = "--debug ${project.findProperty("debug")}"
    }
    if (project.hasProperty("balJavaDebug")) {
        balJavaDebugParam = "BAL_JAVA_DEBUG=${project.findProperty("balJavaDebug")}"
    }
    if (project.hasProperty('balGraalVMTest')) {
        graalvmFlag = '--graalvm'
    }

    gradle.taskGraph.whenReady { graph ->
        if (graph.hasTask(":${packageName}-ballerina:test")) {
            if (!project.hasProperty('balGraalVMTest')) {
                testParams = "${testCoverageParam}"
            }
        } else {
            testParams = "--skip-tests"
            skipTests = true
        }
    }
}

task publishTestCommonPackageToLocal {
    dependsOn(":${packageName}-${packageOrg}:build")
    dependsOn(updateTomlFiles)
    doLast {
        if (!skipTests) {
            exec {
                workingDir "${project.projectDir}/${testCommonPackage}"
                if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                    commandLine 'cmd', '/c', "${distributionBinPath}/bal.bat pack && exit  %%ERRORLEVEL%%"
                } else {
                    commandLine 'sh', '-c', "${distributionBinPath}/bal pack"
                }
            }
            exec {
                workingDir "${project.projectDir}/${testCommonPackage}"
                if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                    commandLine 'cmd', '/c', "${distributionBinPath}/bal.bat push --repository=local" +
                            " && exit %%ERRORLEVEL%%"
                } else {
                    commandLine 'sh', '-c', "${distributionBinPath}/bal push --repository=local"
                }
            }
        }
    }
}

task ballerinaTest {
    dependsOn(publishTestCommonPackageToLocal)
    dependsOn(":${packageName}-${packageOrg}:build")
    dependsOn(updateTomlFiles)
    dependsOn(initializeVariables)
    finalizedBy(commitTomlFiles)

    doLast {
        testSuites.each { testPackage ->
            // TODO: Disable the graphql-subscription-test-suite on Linux
            // Check issue: https://github.com/ballerina-platform/ballerina-library/issues/7529
            if (Os.isFamily(Os.FAMILY_UNIX) && testPackage == "graphql-subscription-test-suite") {
                return
            }
            if (!skipTests) {
                exec {
                    workingDir "${project.projectDir}/${testPackage}"
                    environment "JAVA_OPTS", "-DBALLERINA_DEV_COMPILE_BALLERINA_ORG=true"
                    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
                        commandLine 'cmd', '/c', "${balJavaDebugParam} ${distributionBinPath}/bal.bat test ${graalvmFlag} ${testParams} --offline ${groupParams} ${disableGroups} ${debugParams} && exit %%ERRORLEVEL%%"
                    } else {
                        commandLine 'sh', '-c', "BALLERINA_MAX_POOL_SIZE=500 ${balJavaDebugParam} ${distributionBinPath}/bal test ${graalvmFlag} ${testParams} --offline ${groupParams} ${disableGroups} ${debugParams}"
                    }
                }
            }
        }
    }
}

test {
    dependsOn(ballerinaTest)
}

clean {
    delete "${project.projectDir}/${testCommonPackage}/target"

    testSuites.each { testPackage ->
        delete "${project.projectDir}/${testPackage}/target"
    }
}

task deleteDependencyTomlFile {
    if (project.hasProperty("deleteDependencies")) {
        delete "${project.projectDir}/${testCommonPackage}/Dependencies.toml"

        testSuites.each { testPackage ->
            delete "${project.projectDir}/${testPackage}/Dependencies.toml"
        }
    }
}

build.dependsOn ":${packageName}-ballerina:build"
build.dependsOn ":${packageName}-compiler-plugin:build"
test.dependsOn ":${packageName}-ballerina:build"
test.dependsOn ":${packageName}-compiler-plugin:build"

publishToMavenLocal.dependsOn build
publish.dependsOn build
