/**
 * 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.
 */
apply plugin: 'org.openapi.generator'
description = 'Fineract Client'

apply from: 'dependencies.gradle'

// TODO: @vidakovic we should publish this lib to Maven Central; do in separate PR

openApiMeta {
    generatorName = 'Fineract'
    packageName = 'org.apache.fineract.client'
    outputFolder = "$buildDir/meta".toString()
    // trick to make sure fineract.json is generated first
}

openApiValidate {
    inputSpec = "file:///$swaggerFile"
    recommend = true
}

task buildJavaSdk(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
    generatorName = 'java'
    verbose = false
    validateSpec = false
    skipValidateSpec = true
    inputSpec = "file:///$swaggerFile"
    outputDir = "$buildDir/generated/temp-java".toString()
    templateDir = "$projectDir/src/main/resources/templates/java"
    groupId = 'org.apache.fineract'
    apiPackage = 'org.apache.fineract.client.services'
    invokerPackage = 'org.apache.fineract.client'
    modelPackage = 'org.apache.fineract.client.models'
    configOptions = [
        dateLibrary: 'java8',
        useRxJava2: 'false',
        library: 'retrofit2',
        hideGenerationTimestamp: 'true',
        containerDefaultToNull: 'true',
        oauth2Implementation: 'none'
    ]
    generateModelTests = false
    generateApiTests = false
    ignoreFileOverride = "$projectDir/.openapi-generator-ignore"
    dependsOn(':fineract-provider:resolve')
}

task buildTypescriptAngularSdk(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask){
    generatorName = 'typescript-angular'
    verbose = false
    validateSpec = false
    skipValidateSpec = true
    inputSpec = "file:///$swaggerFile"
    outputDir = "$buildDir/generated/typescript".toString()
    apiPackage = 'apache-fineract-client/services'
    invokerPackage = 'apache-fineract-client/invoker'
    modelPackage = 'apache-fineract-client/models'
    configOptions = [
        apiModulePrefix: 'apacheFineractClient',
        configurationPrefix: 'apacheFineractClient',
        ngVersion: '12.0.0',
        npmName: '@apache/fineract-client',
        npmRepository: "${npmRepository}"
    ]
    dependsOn(':fineract-provider:resolve')
}

task buildAsciidoc(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask){
    generatorName = 'asciidoc'
    verbose = false
    validateSpec = false
    skipValidateSpec = true
    inputSpec = "file:///$swaggerFile"
    outputDir = "$buildDir/generated/asciidoc".toString()
    apiPackage = 'org.apache.fineract.client.services'
    invokerPackage = 'org.apache.fineract.client'
    modelPackage = 'org.apache.fineract.client.models'
    configOptions = [
        appName: 'Apache Fineract REST API',
        appDescription: '''Apache Fineract is a secure, multi-tenanted microfinance platform.
            The goal of the Apache Fineract API is to empower developers to build apps on top of the Apache Fineract Platform.
            The https://cui.fineract.dev[reference app] (username: mifos, password: password) works on the same demo tenant as the interactive links in this documentation.
            Until we complete the new REST API documentation you still have the legacy documentation available https://fineract.apache.org/legacy-docs/apiLive.htm[here].
            Please check https://fineract.apache.org/docs/current[the Fineract documentation] for more information.''',
        headerAttributes: 'false',
        infoEmail: 'dev@fineract.apache.org',
        infoUrl: 'https://fineract.apache.org',
        licenseInfo: 'Apache 2.0',
        licenseUrl: 'http://www.apache.org/licenses/LICENSE-2.0.html',
        useMethodAndPath: 'true'
    ]
    dependsOn(':fineract-provider:resolve')
}

// Configure source sets with proper output directories
sourceSets {
    main {
        java {
            srcDir new File(buildDir, "generated/java/src/main/java")
            destinationDirectory = layout.buildDirectory.dir('classes/java/main').get().asFile
        }
        output.resourcesDir = layout.buildDirectory.dir('resources/main').get().asFile
    }
    test {
        java {
            destinationDirectory = layout.buildDirectory.dir('classes/java/test').get().asFile
        }
        output.resourcesDir = layout.buildDirectory.dir('resources/test').get().asFile
    }
}

// Configure jar tasks to handle duplicates
tasks.withType(Jar).configureEach {
    // Handle duplicates by using the first occurrence
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

// Improve the cleanup task to track inputs and outputs
task cleanupGeneratedJavaFiles() {
    def tempDir = file("$buildDir/generated/temp-java")
    def targetDir = file("$buildDir/generated/java")
    
    inputs.dir(tempDir)
    outputs.dir(targetDir)

    //TODO: remove harcoded, autogenerated Oltu's OAuthOkHttpClient.java from the generated files
    doFirst {
        delete fileTree(tempDir) {
            include "src/main/java/org/apache/fineract/client/auth/OAuthOkHttpClient.java"
        }
        delete fileTree(targetDir) {
            include "src/main/java/org/apache/fineract/client/auth/OAuthOkHttpClient.java"
        }
    }
    doLast {
        copy {
            from tempDir
            into targetDir
            filter { line ->
                line
                    .replaceAll("import org\\.joda\\.time\\.\\*;", "")
                    .replaceAll(", \\)", ")")
                    .replaceAll(", , @HeaderMap", ", @HeaderMap")
                    .replaceAll("\\(, ", "(")
            }
            // Also set duplicates strategy for the copy task
            duplicatesStrategy = DuplicatesStrategy.EXCLUDE
        }
    }
    dependsOn("buildJavaSdk")
}

// Configure Java compilation
tasks.named('compileJava') {
    outputs.cacheIf { true }
    dependsOn(buildJavaSdk, buildTypescriptAngularSdk, buildAsciidoc, cleanupGeneratedJavaFiles, licenseFormatMain, spotlessMiscApply)
    mustRunAfter(licenseFormatMain, cleanupGeneratedJavaFiles)
}

// Configure sources jar task
tasks.named('sourcesJar') {
    dependsOn(cleanupGeneratedJavaFiles)
    mustRunAfter(cleanupGeneratedJavaFiles)
    
    from(sourceSets.main.java.srcDirs) {
        include "**/*.java"
    }
}

// Configure license formatting
tasks.named('licenseFormatMain') {
    dependsOn(cleanupGeneratedJavaFiles)
    mustRunAfter(cleanupGeneratedJavaFiles)
    source = sourceSets.main.java.srcDirs
}

tasks.named('licenseMain') {
    dependsOn(licenseFormatMain)
    mustRunAfter(licenseFormatMain)
}

java {
    // keep this at Java 8, not 17; see https://issues.apache.org/jira/browse/FINERACT-1214
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

tasks.withType(JavaCompile).configureEach {
    options.errorprone {
        excludedPaths = '.*/build/generated/java/src/main/java/.*'
    }
}

test {
    useJUnitPlatform()
}

configurations {
    generatedCompileClasspath.extendsFrom implementation
    generatedRuntimeClasspath.extendsFrom runtimeClasspath
}
