plugins {
    id 'com.android.library'
    id 'org.jetbrains.kotlin.android'
    id "de.undercouch.download"
}

Properties properties = new Properties()
if (rootProject.file("local.properties").exists()) {
    properties.load(rootProject.file("local.properties").newDataInputStream())
}

ext["keyId"] = properties.getProperty("signing.keyId", System.getenv('SIGNING_KEY_ID'))
ext["password"] = properties.getProperty("signing.password", System.getenv('SIGNING_PASSWORD'))
ext["key"] = properties.getProperty("signing.key", System.getenv('SIGNING_KEY'))
ext["ossrhUsername"] = properties.getProperty("ossrhUsername", System.getenv('OSSRH_USERNAME'))
ext["ossrhPassword"] = properties.getProperty("ossrhPassword", System.getenv('OSSRH_PASSWORD'))
ext["sonatypeStagingProfileId"] = properties.getProperty("sonatypeStagingProfileId", System.getenv('SONATYPE_STAGING_PROFILE_ID'))

ext {
    set("GROUP_ID", "org.kiwix")
    set("ARTIFACT_ID", "libkiwix")
    set("VERSION", "2.2.4")
}

// Replace these versions with the latest available versions of libkiwix and libzim
ext.libkiwix_version = "14.0.0-1"
ext.libzim_version = "9.2.3-2"

apply from: 'publish.gradle'
android {
    compileSdk 34
    namespace = "kiwix.org.kiwixlib"
    defaultConfig {

        minSdk 24
        targetSdk 34
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ''
                arguments "-DANDROID_STL=c++_shared", "-DBUILD_DIR=${buildDir}"
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
            version '3.18.1'
        }
    }
    buildFeatures {
        viewBinding true
    }
    ndkVersion '21.4.7075529'

    // Enabled the lint to avoid potential errors.
    lintOptions {
        abortOnError true
        checkAllWarnings = true
        warningsAsErrors true
        disable("GradleDependency", "UnknownNullness", "OldTargetApi")
    }
}

dependencies {
    implementation 'com.getkeepsafe.relinker:relinker:1.4.5'
    implementation 'androidx.core:core-ktx:1.7.0'
}

ext.libkiwix_base_url = 'https://download.kiwix.org/release/libkiwix/'
ext.libzim_base_url = 'https://download.openzim.org/release/libzim/'

tasks.register('downloadLibzimSoAndHeaderFiles', Download) {
    src([
            libzim_base_url + 'libzim_android-arm-' + libzim_version + '.tar.gz',
            libzim_base_url + 'libzim_android-arm64-' + libzim_version + '.tar.gz',
            libzim_base_url + 'libzim_android-x86-' + libzim_version + '.tar.gz',
            libzim_base_url + 'libzim_android-x86_64-' + libzim_version + '.tar.gz',
            libzim_base_url + 'libzim_linux-x86_64-' + libzim_version + '.tar.gz'
    ])
    dest buildDir
    overwrite true
}

tasks.register('unzipLibzim', Copy) {
    mustRunAfter downloadLibzimSoAndHeaderFiles
    // unzip android arm
    from tarTree(buildDir.path + "/libzim_android-arm-" + libzim_version + ".tar.gz")
    into buildDir
    // unzip android arm64
    from tarTree(buildDir.path + "/libzim_android-arm64-" + libzim_version + ".tar.gz")
    into buildDir
    // unzip android x86
    from tarTree(buildDir.path + "/libzim_android-x86-" + libzim_version + ".tar.gz")
    into buildDir
    // unzip android x86_64
    from tarTree(buildDir.path + "/libzim_android-x86_64-" + libzim_version + ".tar.gz")
    into buildDir
    // unzip linux x86_64
    from tarTree(buildDir.path + "/libzim_linux-x86_64-" + libzim_version + ".tar.gz")
    into buildDir
}

tasks.register('renameLibzimFolders') {
    removeVersionFromFolderName(buildDir.path, "libzim_", libzim_version)
}

tasks.register('copyLibzimHeaderAndSoFiles', Copy) {
    copy {
        // copying header file
        from buildDir.path + "/libzim_android-arm/include/"
        into buildDir.path + "/include/libzim/"
    }

    copy {
        // copying android_arm so file
        from buildDir.path + "/libzim_android-arm/lib/arm-linux-androideabi/"
        into buildDir.path + "/jniLibs/armeabi-v7a/libzim/"
    }

    copy {
        // copying android_arm64 so file
        from buildDir.path + "/libzim_android-arm64/lib/aarch64-linux-android/"
        into buildDir.path + "/jniLibs/arm64-v8a/libzim/"
    }

    copy {
        // copying android_x86 so file
        from buildDir.path + "/libzim_android-x86/lib/i686-linux-android/"
        into buildDir.path + "/jniLibs/x86/libzim/"
    }

    copy {
        // copying android_x86_64 so file
        from buildDir.path + "/libzim_android-x86_64/lib/x86_64-linux-android/"
        into buildDir.path + "/jniLibs/x86_64/libzim/"
    }

    copy {
        // copying linux_x86_64 so file
        from buildDir.path + "/libzim_linux-x86_64/lib/x86_64-linux-gnu/libzim.so." + getActualLibraryVersion(libzim_version)
        into buildDir.path
    }
}

tasks.register('renameLibzimSoFile', Copy) {
    if (libzim_version != null) {
        def finalLibzimVersion = getActualLibraryVersion(libzim_version)

        def sourceFile = file(buildDir.path + "/libzim.so." + finalLibzimVersion)

        if (project.gradle.startParameter.taskNames.contains("renameLibzimSoFile") && !sourceFile.exists()) {
            throw new RuntimeException("Rename Libzim so file task failed, File not found: ${sourceFile}")
        }
        from(buildDir.path)
        include "libzim.so." + finalLibzimVersion
        destinationDir file(buildDir.path)
        rename "libzim.so." + finalLibzimVersion, "libzim.so"
    }
}

tasks.register('downloadLibkiwixSoAndHeaderFiles', Download) {
    src([
            libkiwix_base_url + 'libkiwix_android-arm-' + libkiwix_version + '.tar.gz',
            libkiwix_base_url + 'libkiwix_android-arm64-' + libkiwix_version + '.tar.gz',
            libkiwix_base_url + 'libkiwix_android-x86-' + libkiwix_version + '.tar.gz',
            libkiwix_base_url + 'libkiwix_android-x86_64-' + libkiwix_version + '.tar.gz',
            libkiwix_base_url + 'libkiwix_linux-x86_64-' + libkiwix_version + '.tar.gz'
    ])
    dest buildDir
    overwrite true
}

tasks.register('renameLibkiwixFolders') {
    removeVersionFromFolderName(buildDir.path, "libkiwix_", libkiwix_version)
}

static void removeVersionFromFolderName(String path, String startWith, String version) {
    File directory = new File(path)
    if (directory.exists() && directory.isDirectory()) {
        Arrays.stream(directory.listFiles())
                .filter(folder -> folder.isDirectory() && folder.getName().startsWith(startWith))
                .forEach(file -> {
                    String newName = file.getName().replace("-" + version, "")
                    File newFile = new File(directory, newName)
                    file.renameTo(newFile)
                })
    }
}

tasks.register('unzipLibkiwix', Copy) {
    mustRunAfter downloadLibkiwixSoAndHeaderFiles
    // unzip android arm
    from tarTree(buildDir.path + "/libkiwix_android-arm-" + libkiwix_version + ".tar.gz")
    into buildDir
    // unzip android arm64
    from tarTree(buildDir.path + "/libkiwix_android-arm64-" + libkiwix_version + ".tar.gz")
    into buildDir
    // unzip android x86
    from tarTree(buildDir.path + "/libkiwix_android-x86-" + libkiwix_version + ".tar.gz")
    into buildDir
    // unzip android x86_64
    from tarTree(buildDir.path + "/libkiwix_android-x86_64-" + libkiwix_version + ".tar.gz")
    into buildDir
    // unzip linux x86_64
    from tarTree(buildDir.path + "/libkiwix_linux-x86_64-" + libkiwix_version + ".tar.gz")
    into buildDir
}

tasks.register('copyLibkiwixHeaderAndSoFiles', Copy) {
    copy {
        // copying header file
        from buildDir.path + "/libkiwix_android-arm/include/kiwix/"
        into buildDir.path + "/include/libkiwix/"
    }

    copy {
        // copying android_arm so file
        from buildDir.path + "/libkiwix_android-arm/lib/arm-linux-androideabi/"
        into buildDir.path + "/jniLibs/armeabi-v7a/libkiwix/"
    }

    copy {
        // copying android_arm64 so file
        from buildDir.path + "/libkiwix_android-arm64/lib/aarch64-linux-android/"
        into buildDir.path + "/jniLibs/arm64-v8a/libkiwix/"
    }

    copy {
        // copying android_x86 so file
        from buildDir.path + "/libkiwix_android-x86/lib/i686-linux-android/"
        into buildDir.path + "/jniLibs/x86/libkiwix/"
    }

    copy {
        // copying android_x86_64 so file
        from buildDir.path + "/libkiwix_android-x86_64/lib/x86_64-linux-android/"
        into buildDir.path + "/jniLibs/x86_64/libkiwix/"
    }

    copy {
        // copying linux_x86_64 so file
        from buildDir.path + "/libkiwix_linux-x86_64/lib/x86_64-linux-gnu/libkiwix.so." + getActualLibraryVersion(libkiwix_version)
        into buildDir.path
    }
}

tasks.register('renameLibkiwixSoFile', Copy) {
    if (libkiwix_version != null) {
        def finalLibkiwixVersion = getActualLibraryVersion(libkiwix_version)
        def sourceFile = file(buildDir.path + "/libkiwix.so." + finalLibkiwixVersion)

        if (project.gradle.startParameter.taskNames.contains("renameLibkiwixSoFile") && !sourceFile.exists()) {
            throw new RuntimeException("Rename Libkiwix so file task failed, File not found: ${sourceFile}")
        }
        from(buildDir.path)
        include "libkiwix.so." + finalLibkiwixVersion
        destinationDir file(buildDir.path)
        rename "libkiwix.so." + finalLibkiwixVersion, "libkiwix.so"
    }
}

// Extracting the library version before the "-"
// see https://github.com/kiwix/java-libkiwix/pull/79 for more details
static String getActualLibraryVersion(String libraryVersion) {
    // Find the index of the first occurrence of "-"
    Integer dashIndex = libraryVersion.indexOf('-')

    // Get the substring before the first "-"
    return dashIndex != -1 ? libraryVersion.substring(0, dashIndex) : libraryVersion
}

tasks.register('testSourceJar', Jar) {
    from android.sourceSets.test.java.srcDirs
    archiveBaseName = 'test-sources'
}

tasks.register('compileTestFile', JavaCompile) {
    dependsOn testSourceJar
    source = file('src/test')
    destinationDirectory = file("$buildDir")
    classpath = files("src/test/junit-4.13.jar", "src/test/hamcrest-core-1.4.jar", "build/libs/test-sources-${VERSION}.jar")
}

tasks.register('runTests', JavaExec) {
    workingDir("$projectDir/src/test/")
    dependsOn compileTestFile
    classpath = files("$buildDir", 'src/test/java/', 'src/test/junit-4.13.jar', 'src/test/hamcrest-core-1.3.jar')
    mainClass = 'org.junit.runner.JUnitCore'
    args = ['test']
    jvmArgs = [
            '-Djava.library.path=' + buildDir.path,
            '-javaagent:jacoco-0.8.7/lib/jacocoagent.jar=destfile=../../build/jacoco/jacoco.exec'
    ]
}

tasks.register('createCodeCoverageReport', JavaExec) {
    workingDir "${projectDir}/src/test/"
    dependsOn runTests
    classpath = files('src/test/', 'src/test/java/', 'src/test/junit-4.13.jar', 'src/test/hamcrest-core-1.3.jar', 'src/test/jacoco-0.8.7/lib/*')
    mainClass = 'org.jacoco.cli.internal.Main'
    args = [
            'report', '../../build/jacoco/jacoco.exec',
            '--classfiles', 'java/org/kiwix', '--classfiles', '../../build/org/kiwix',
            '--html', '../../build/coverage-report', '--xml', '../../build/coverage.xml'
    ]
}

tasks.register('checkCurrentJavaVersion') {
    if (JavaVersion.current() != JavaVersion.VERSION_17) {
        throw new RuntimeException("This build must be run with java 17. your current java version is ${JavaVersion.current()}")
    }
}


tasks.register('buildHeaders', Exec) {
    workingDir "${projectDir}/src/main/java/org/kiwix/"
    commandLine 'bash', '-c', "javac -h ${buildDir}/include/javah_generated/ -d ${projectDir}/src/test/java/ ${getLibzimFiles()} ${getLibkiwixFiles()}"
}

String getLibkiwixFiles() {
    return "${projectDir}/src/main/java/org/kiwix/libkiwix/Book.java " +
        "${projectDir}/src/main/java/org/kiwix/libkiwix/Bookmark.java " +
        "${projectDir}/src/main/java/org/kiwix/libkiwix/BookmarkMigrationResult.java " +
        "${projectDir}/src/main/java/org/kiwix/libkiwix/Filter.java " +
        "${projectDir}/src/main/java/org/kiwix/libkiwix/JNIICU.java " +
        "${projectDir}/src/main/java/org/kiwix/libkiwix/Illustration.java " +
        "${projectDir}/src/main/java/org/kiwix/libkiwix/JNIKiwixException.java " +
        "${projectDir}/src/main/java/org/kiwix/libkiwix/Library.java " +
        "${projectDir}/src/main/java/org/kiwix/libkiwix/Manager.java " +
        "${projectDir}/src/main/java/org/kiwix/libkiwix/Server.java"
}

String getLibzimFiles() {
    return "${projectDir}/src/main/java/org/kiwix/libzim/Archive.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/Blob.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/DirectAccessInfo.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/EntryIterator.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/Entry.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/Item.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/Query.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/Searcher.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/SearchIterator.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/Search.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/SuggestionItem.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/SuggestionIterator.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/SuggestionSearcher.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/SuggestionSearch.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/ZimFileFormatException.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/EntryNotFoundException.java " +
        "${projectDir}/src/main/java/org/kiwix/libzim/FdInput.java"
}

tasks.register('buildLinuxBinding', Exec) {
    workingDir "${projectDir}/src/main/cpp/"
    commandLine 'bash', '-c', "cmake . -B ${buildDir} && make -C ${buildDir}"
}

build.dependsOn buildLinuxBinding
