apply plugin: 'com.android.application'
apply plugin: 'com.bugsnag.android.gradle'
apply plugin: 'kotlin-android'
apply plugin: 'de.undercouch.download'

def getVersionCode = { -> return 2135 }
def getRevision = { -> return "b" }
def getReleaseName = { -> return "Wintonotitan" }
// https://en.wikipedia.org/wiki/List_of_dinosaur_genera

def keystoreProperties = new Properties()
if (rootProject.file("keystore.properties").exists())
    keystoreProperties.load(new FileInputStream(rootProject.file("keystore.properties")))

Properties localProperties = new Properties()
if (rootProject.file("local.properties").exists())
    localProperties.load(new FileInputStream(rootProject.file("local.properties")))

android {
    //compileSdkExtension 4 // https://developer.android.com/guide/sdk-extensions
    namespace 'eu.faircode.email'

    // https://apilevels.com/
    defaultConfig {
        applicationId "eu.faircode.email"
        compileSdk 34
        minSdkVersion 21
        targetSdkVersion 34
        versionCode getVersionCode()
        versionName "1." + getVersionCode()

        manifestPlaceholders = [namespace: applicationId.replace('.debug', '')]

        buildConfigField "String", "REVISION", "\"" + getRevision() + "\""
        buildConfigField "String", "RELEASE_NAME", "\"" + getReleaseName() + "\""

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }

        // https://developer.android.com/guide/topics/graphics/vector-drawable-resources
        vectorDrawables.useSupportLibrary = true

        externalNativeBuild {
            cmake {
                cFlags "-ffile-prefix-map=${rootDir}=."
                cppFlags "-ffile-prefix-map=${rootDir}=."
            }
        }

        // https://developer.android.com/ndk/downloads
        ndkVersion "25.2.9519653" // r25c
        ndk {
            // Bugsnag, sqlite
            // https://developer.android.com/ndk/guides/abis
            abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }

    base {
        archivesName = "FairEmail-v1." + getVersionCode() + getRevision()
    }

    sourceSets {
        github {
            java.srcDirs = ['src/main/java', 'src/play/java', 'src/extra/java']
        }
        large {
            java.srcDirs = ['src/main/java', 'src/play/java', 'src/extra/java']
        }
        fdroid {
            java.srcDirs = ['src/main/java', 'src/fdroid/java', 'src/extra/java']
        }
        play {
            java.srcDirs = ['src/main/java', 'src/play/java', 'src/dummy/java']
        }
        amazon {
            java.srcDirs = ['src/main/java', 'src/amazon/java', 'src/extra/java']
        }
        main.res.srcDirs += 'src/main/resExtra'
    }

    lint {
        // https://developer.android.com/studio/write/lint
        // https://developer.android.com/reference/tools/gradle-api/8.0/com/android/build/api/dsl/LintOptions
        abortOnError true
        checkReleaseBuilds false
        //checkDependencies false
        disable 'MissingTranslation'
        fatal 'StringFormatInvalid', 'StringFormatMatches', 'StringFormatCount'
        checkOnly 'StringFormatInvalid', 'StringFormatMatches', 'StringFormatCount'
    }

    compileOptions {
        // https://developer.android.com/studio/write/java8-support#groovy
        coreLibraryDesugaringEnabled true
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }

    externalNativeBuild {
        cmake {
            version "3.22.1"
            path "CMakeLists.txt"
        }
    }

    dependenciesInfo {
        includeInApk = false
        includeInBundle = false
    }
    packagingOptions {
        jniLibs {
            useLegacyPackaging = true // https://issuetracker.google.com/issues/127691101
            excludes += [
                    'org/apache/**'
            ]
        }
        resources {
            excludes += [
                    'LICENSES',
                    'META-INF/LICENSE.txt',
                    'META-INF/README.md',
                    'META-INF/CHANGES',
                    'META-INF/jersey-module-version',
                    'META-INF/COPYRIGHT.html',
                    'META-INF/LICENSE.gpl.txt',
                    'META-INF/LICENSE.commercial.txt',
                    'LICENSE-2.0.txt',
                    'RELEASE.txt',
                    'DebugProbesKt.bin',
                    'font_metrics.properties'
            ]
        }
    }

    // https://developer.android.com/reference/tools/gradle-api/4.2/com/android/build/api/dsl/SigningConfig
    signingConfigs {
        release {
            if (rootProject.file("keystore.properties").exists()) {
                storeFile file(keystoreProperties['storeFile'])
                storePassword keystoreProperties['storePassword']
                keyAlias keystoreProperties['keyAlias']
                keyPassword keystoreProperties['keyPassword']
                v1SigningEnabled true
                v2SigningEnabled true
            }
        }
    }

    buildFeatures {
        buildConfig = true
        viewBinding = false
        dataBinding = false
        aidl = true
        renderScript = false
        resValues = false
        shaders = false
        compose = false
    }

    buildTypes {
        // https://developer.android.com/studio/build/shrink-code
        release {
            debuggable = false
            minifyEnabled = true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
            buildConfigField "String", "TX_URI", "\"\""
            buildConfigField "String", "GPA_URI", "\"\""
            buildConfigField "String", "INFO_URI", "\"\""
            buildConfigField "String", "BUGSNAG_URI", "\"\""
            buildConfigField "String", "DEV_DOMAIN", "\"\""
        }
        debug {
            applicationIdSuffix '.debug'
            debuggable = true
            minifyEnabled = false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            buildConfigField "String", "TX_URI", localProperties.getProperty("paypal.uri", "\"\"")
            buildConfigField "String", "GPA_URI", localProperties.getProperty("gpa.uri", "\"\"")
            buildConfigField "String", "INFO_URI", localProperties.getProperty("info.uri", "\"\"")
            buildConfigField "String", "BUGSNAG_URI", localProperties.getProperty("bugsnag.uri", "\"\"")
            buildConfigField "String", "DEV_DOMAIN", localProperties.getProperty("dev.domain", "\"\"")
        }
    }

    flavorDimensions += "all"

    productFlavors {
        github {
            dimension "all"
            manifestPlaceholders.largeHeap = false
            manifestPlaceholders.build_uuid = UUID.nameUUIDFromBytes(("github" + getVersionCode() + getRevision()).getBytes()).toString();
            buildConfigField "boolean", "TEST_RELEASE", "false"
            buildConfigField "boolean", "BETA_RELEASE", "true"
            buildConfigField "boolean", "PLAY_STORE_RELEASE", "false"
            buildConfigField "boolean", "FDROID_RELEASE", "false"
            buildConfigField "boolean", "AMAZON_RELEASE", "false"
            buildConfigField "String", "PRO_FEATURES_URI", "\"https://email.faircode.eu/donate/\""
            buildConfigField "String", "CHANGELOG", "\"https://github.com/M66B/FairEmail/releases/\""
            buildConfigField "String", "GITHUB_LATEST_API", "\"https://api.github.com/repos/M66B/FairEmail/releases/latest\""
            buildConfigField "String", "GITHUB_LATEST_URI", "\"https://github.com/M66B/FairEmail/releases\""
            buildConfigField "String", "BITBUCKET_DOWNLOADS_API", "\"https://api.bitbucket.org/2.0/repositories/M66B/fairemail-test/downloads\""
            buildConfigField "String", "BITBUCKET_DOWNLOADS_URI", "\"https://bitbucket.org/M66B/fairemail-test/downloads/\""
            buildConfigField "String", "ANNOUNCEMENT_URI", "\"\""
            buildConfigField "String", "CLOUD_URI", "\"https://api.fairemail.net/sync\""
            buildConfigField "String", "CLOUD_EMAIL", "\"cloud@in.faircode.eu\""
            buildConfigField "String", "OPENAI_ENDPOINT", "\"https://api.openai.com/v1/\""
            buildConfigField "String", "OPENAI_PRIVACY", "\"https://openai.com/policies/privacy-policy\""
            buildConfigField "String", "FDROID", "\"https://f-droid.org/packages/%s/\""
        }
        large {
            dimension "all"
            manifestPlaceholders.largeHeap = true
            manifestPlaceholders.build_uuid = UUID.nameUUIDFromBytes(("large" + getVersionCode() + getRevision()).getBytes()).toString();
            buildConfigField "boolean", "TEST_RELEASE", "false"
            buildConfigField "boolean", "BETA_RELEASE", "true"
            buildConfigField "boolean", "PLAY_STORE_RELEASE", "false"
            buildConfigField "boolean", "FDROID_RELEASE", "false"
            buildConfigField "boolean", "AMAZON_RELEASE", "false"
            buildConfigField "String", "PRO_FEATURES_URI", "\"https://email.faircode.eu/donate/\""
            buildConfigField "String", "CHANGELOG", "\"https://github.com/M66B/FairEmail/releases/\""
            buildConfigField "String", "GITHUB_LATEST_API", "\"https://api.github.com/repos/M66B/FairEmail/releases/latest\""
            buildConfigField "String", "GITHUB_LATEST_URI", "\"https://github.com/M66B/FairEmail/releases\""
            buildConfigField "String", "BITBUCKET_DOWNLOADS_API", "\"https://api.bitbucket.org/2.0/repositories/M66B/fairemail-test/downloads\""
            buildConfigField "String", "BITBUCKET_DOWNLOADS_URI", "\"https://bitbucket.org/M66B/fairemail-test/downloads/\""
            buildConfigField "String", "ANNOUNCEMENT_URI", "\"\""
            buildConfigField "String", "CLOUD_URI", "\"https://api.fairemail.net/sync\""
            buildConfigField "String", "CLOUD_EMAIL", "\"cloud@in.faircode.eu\""
            buildConfigField "String", "OPENAI_ENDPOINT", "\"https://api.openai.com/v1/\""
            buildConfigField "String", "OPENAI_PRIVACY", "\"https://openai.com/policies/privacy-policy\""
            buildConfigField "String", "FDROID", "\"https://f-droid.org/packages/%s/\""
        }
        fdroid {
            dimension "all"
            manifestPlaceholders.largeHeap = false
            manifestPlaceholders.build_uuid = UUID.nameUUIDFromBytes(("fdroid" + getVersionCode() + getRevision()).getBytes()).toString();
            externalNativeBuild {
                cmake {
                    arguments "-DCMAKE_SHARED_LINKER_FLAGS=-Wl,--build-id=none"
                    // https://f-droid.org/docs/Reproducible_Builds/
                    // The build ID is a 160-bit SHA1 string computed over the elf header bits and section contents in the file.
                    // It is bundled in the elf file as an entry in the notes section.
                    //   readelf -n ./app/build/intermediates/stripped_native_libs/xxxRelease/out/lib/armeabi-v7a/libfairemail.so
                }
            }
            buildConfigField "boolean", "TEST_RELEASE", "false"
            buildConfigField "boolean", "BETA_RELEASE", "true"
            buildConfigField "boolean", "PLAY_STORE_RELEASE", "false"
            buildConfigField "boolean", "FDROID_RELEASE", "true"
            buildConfigField "boolean", "AMAZON_RELEASE", "false"
            buildConfigField "String", "PRO_FEATURES_URI", "\"https://email.faircode.eu/donate/\""
            buildConfigField "String", "CHANGELOG", "\"https://github.com/M66B/FairEmail/releases/\""
            buildConfigField "String", "GITHUB_LATEST_API", "\"https://api.github.com/repos/M66B/FairEmail/releases/latest\""
            buildConfigField "String", "GITHUB_LATEST_URI", "\"https://github.com/M66B/FairEmail/releases\""
            buildConfigField "String", "BITBUCKET_DOWNLOADS_API", "\"https://api.bitbucket.org/2.0/repositories/M66B/fairemail-test/downloads\""
            buildConfigField "String", "BITBUCKET_DOWNLOADS_URI", "\"https://bitbucket.org/M66B/fairemail-test/downloads/\""
            buildConfigField "String", "ANNOUNCEMENT_URI", "\"\""
            buildConfigField "String", "CLOUD_URI", "\"https://api.fairemail.net/sync\""
            buildConfigField "String", "CLOUD_EMAIL", "\"cloud@in.faircode.eu\""
            buildConfigField "String", "OPENAI_ENDPOINT", "\"https://api.openai.com/v1/\""
            buildConfigField "String", "OPENAI_PRIVACY", "\"https://openai.com/policies/privacy-policy\""
            buildConfigField "String", "FDROID", "\"https://f-droid.org/packages/%s/\""
        }
        play {
            dimension "all"
            //minSdkVersion 23
            manifestPlaceholders.largeHeap = false
            manifestPlaceholders.build_uuid = UUID.nameUUIDFromBytes(("play" + getVersionCode() + getRevision()).getBytes()).toString();
            buildConfigField "boolean", "TEST_RELEASE", "false"
            buildConfigField "boolean", "BETA_RELEASE", "true"
            buildConfigField "boolean", "PLAY_STORE_RELEASE", "true"
            buildConfigField "boolean", "FDROID_RELEASE", "false"
            buildConfigField "boolean", "AMAZON_RELEASE", "false"
            buildConfigField "String", "PRO_FEATURES_URI", "\"https://email.faircode.eu/#pro\""
            buildConfigField "String", "CHANGELOG", "\"\""
            buildConfigField "String", "GITHUB_LATEST_API", "\"\""
            buildConfigField "String", "GITHUB_LATEST_URI", "\"\""
            buildConfigField "String", "BITBUCKET_DOWNLOADS_API", "\"\""
            buildConfigField "String", "BITBUCKET_DOWNLOADS_URI", "\"\""
            buildConfigField "String", "ANNOUNCEMENT_URI", "\"\""
            buildConfigField "String", "CLOUD_URI", "\"\""
            buildConfigField "String", "CLOUD_EMAIL", "\"\""
            buildConfigField "String", "OPENAI_ENDPOINT", "\"\""
            buildConfigField "String", "OPENAI_PRIVACY", "\"\""
            buildConfigField "String", "FDROID", "\"\""
        }
        amazon {
            dimension "all"
            minSdkVersion 23
            manifestPlaceholders.largeHeap = false
            manifestPlaceholders.build_uuid = UUID.nameUUIDFromBytes(("amazon" + getVersionCode() + getRevision()).getBytes()).toString();
            buildConfigField "boolean", "TEST_RELEASE", "false"
            buildConfigField "boolean", "BETA_RELEASE", "true"
            buildConfigField "boolean", "PLAY_STORE_RELEASE", "false"
            buildConfigField "boolean", "FDROID_RELEASE", "false"
            buildConfigField "boolean", "AMAZON_RELEASE", "true"
            buildConfigField "String", "PRO_FEATURES_URI", "\"https://email.faircode.eu/#pro\""
            buildConfigField "String", "CHANGELOG", "\"\""
            buildConfigField "String", "GITHUB_LATEST_API", "\"\""
            buildConfigField "String", "GITHUB_LATEST_URI", "\"\""
            buildConfigField "String", "BITBUCKET_DOWNLOADS_API", "\"\""
            buildConfigField "String", "BITBUCKET_DOWNLOADS_URI", "\"\""
            buildConfigField "String", "ANNOUNCEMENT_URI", "\"\""
            buildConfigField "String", "CLOUD_URI", "\"\""
            buildConfigField "String", "CLOUD_EMAIL", "\"\""
            buildConfigField "String", "OPENAI_ENDPOINT", "\"\""
            buildConfigField "String", "OPENAI_PRIVACY", "\"\""
            buildConfigField "String", "FDROID", "\"\""
        }
    }

    variantFilter { variant ->
        def flavors = variant.flavors*.name
        // Builds: release, debug
        // Flavors: github, large, fdroid, play
        if (variant.buildType.name == "debug" &&
                (flavors.contains("fdroid") || flavors.contains("play") || flavors.contains("_amazon"))) {
            setIgnore(true)
        }
    }

    // https://stackoverflow.com/questions/28948538/
    applicationVariants.all { variant ->
        if (variant.buildType.name == "debug")
            variant.buildConfigField "String", "MXTOOLBOX_URI", "\"https://mxtoolbox.com\""
        else
            variant.buildConfigField "String", "MXTOOLBOX_URI", "\"\""

        if (variant.getBuildType().isMinifyEnabled())
            variant.assembleProvider.get().doLast {
                for (file in variant.getMappingFileProvider().get().files)
                    if (file != null && file.exists()) {
                        def dir = "${rootDir}/app/schemas/mapping"
                        def name = "$archivesBaseName-$variant.baseName-$file.name"
                        def target = new File(dir, name)
                        if (!target.exists())
                            copy {
                                from file
                                into dir
                                rename { String fileName -> name }
                            }
                    }
            }
    }

    bugsnag {
        // https://docs.bugsnag.com/build-integrations/gradle/
        uploadJvmMappings = false // disables upload of ProGuard/DexGuard/R8 mapping files
        uploadNdkMappings = false // disables upload of NDK mapping files
        reportBuilds = false // disables upload of build metadata
        overwrite = true
        builderName = "M66B"
    }
}

task copyMarkdown(type: Copy) {
    from "${rootDir}"
    into "src/main/assets"
    include "CHANGELOG.md"
    include "SETUP.md"
    include "ATTRIBUTION.md"
}

preBuild.dependsOn copyMarkdown

task copyChangelog(type: Copy) {
    from "${rootDir}"
    into "../metadata/en-US/changelogs"
    include "CHANGELOG.md"
    rename "CHANGELOG.md", getVersionCode() + ".txt"
    filter { String line ->
        line
                .replaceAll(".*Google Translate.*", "--------------------")
                .replaceAll("### ", "")
                .replaceAll("## ", "")
                .replaceAll("<img.*/>", "")
                .replaceAll("\\(https.*\\)", "")
                .replaceAll("\\[", "")
                .replaceAll("\\]", "")
    }
}

preBuild.dependsOn copyChangelog

task updateFAQ(type: Exec) {
    workingDir "${rootDir}"
    commandLine 'sh', '-c', 'pandoc --standalone --metadata title="FAQ FairEmail"  FAQ.md -o index.html'
}

task updatePrivacy(type: Exec) {
    workingDir "${rootDir}"
    commandLine 'sh', '-c', 'pandoc --standalone --metadata title="FairEmail" --css=privacy.css PRIVACY.md -o privacy.html'
}

task updateCrowdin(type: Exec) {
    // https://crowdin.github.io/crowdin-cli/
    // https://developer.crowdin.com/configuration-file/
    workingDir "${rootDir}"
    commandLine 'sh', '-c', 'crowdin download --branch=master'
}

task downloadPSL(type: Download) {
    // https://github.com/michel-kraemer/gradle-download-task
    src "https://raw.githubusercontent.com/publicsuffix/list/master/public_suffix_list.dat"
    dest "src/main/assets"
    overwrite true
}

task extractSignature(type: Exec) {
    workingDir "${rootDir}"
    // sudo apt install apksigcopier
    commandLine 'sh', '-c', 'mkdir -p metadata/eu.faircode.email/signatures/' + getVersionCode() + ' &&' +
            'apksigcopier extract --v1-only=auto app/build/outputs/apk/fdroid/release/FairEmail-v1.' + getVersionCode() + getRevision() + '-fdroid-release.apk metadata/eu.faircode.email/signatures/' + getVersionCode()
}

task upload() {
    // ./gradlew upload -Ptarget=play-preview
    doLast {
        println "\nhttps://bitbucket.org/M66B/fairemail-test/downloads/FairEmail-v1." + getVersionCode() + getRevision() + "-" + target + "-release.apk\n"
        exec {
            workingDir "${buildDir}"
            commandLine 'curl',
                    '-o', '/dev/null',
                    '-X', 'POST', "https://M66B:" + localProperties.getProperty("bb.pwd", "") + "@api.bitbucket.org/2.0/repositories/M66B/fairemail-test/downloads",
                    '--form', "files=@${buildDir}/outputs/apk/" + target.split('-')[0] + "/release/FairEmail-v1." + getVersionCode() + getRevision() + "-" + target.split('-')[0] + "-release.apk;" +
                    "filename=FairEmail-v1." + getVersionCode() + getRevision() + "-" + target + "-release.apk"
        }
    }
}

repositories {
    google()
    mavenCentral()
    maven { url "https://jitpack.io" }
    //maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
    //maven { url "https://jakarta.oss.sonatype.org/content/repositories/snapshots/" }
}

configurations.all {
    // Workaround https://issuetracker.google.com/issues/138441698
    // Support @69c481c39a17d4e1e44a4eb298bb81c48f226eef
    exclude group: "androidx.room", module: "room-runtime"

    // Workaround https://issuetracker.google.com/issues/134685570
    exclude group: "androidx.lifecycle", module: "lifecycle-livedata"
    exclude group: "androidx.lifecycle", module: "lifecycle-livedata-core"

    // lifecycle-livedata: ComputableLiveData, MediatorLiveData, Transformations
    // lifecycle-livedata-core: LiveData, MutableLiveData, Observer
    // paging-runtime: AsyncPagedListDiffer, LivePagedListBuilder, PagedListAdapter, PagedStorageDiffHelper

    exclude group: "androidx.emoji2", module: "emoji2"
}

configurations.all {
    resolutionStrategy.eachDependency { details ->
        if (details.requested.group == "androidx.room") {
            //print("Pinning " + details.requested.group + ":" + details.requested.name + "\n")
            details.useVersion "2.4.3"
        } else if (details.requested.group == "androidx.lifecycle" &&
                details.requested.name != "lifecycle-extensions") {
            //print("Pinning " + details.requested.group + ":" + details.requested.name + "\n")
            details.useVersion "2.6.2"
        } else if (details.requested.group == "org.apache.poi") {
            //print("Pinning " + details.requested.group + ":" + details.requested.name + "\n")
            details.useVersion "3.17"
        } else if (details.requested.group == "org.simplejavamail") {
            //print("Pinning " + details.requested.group + ":" + details.requested.name + "\n")
            details.useVersion "1.7.13"
        } else if (details.requested.group == "com.google.flatbuffers") {
            //print("Pinning " + details.requested.group + ":" + details.requested.name + "\n")
            details.useVersion "2.0.0"
        }
    }
}

dependencies {
    //implementation fileTree(dir: 'libs', include: ['*.jar'])

    def startup_version = "1.1.1" // 1.2.0-alpha02
    def annotation_version_experimental = "1.3.1" // 1.4.0-alpha01
    def core_version = "1.12.0" // 1.13.0-alpha02
    def appcompat_version = "1.6.1" // 1.7.0-alpha03
    def emoji_version = "1.4.0"
    def flatbuffers_version = "2.0.0"
    def activity_version = "1.8.1" // 1.9.0-alpha01
    def fragment_version = "1.6.2" // 1.7.0-alpha07
    def windows_version = "1.2.0" // 1.3.0-alpha01
    def webkit_version = "1.9.0" // 1.10.0-alpha01
    def recyclerview_version = "1.3.2" // 1.4.0-alpha01
    def coordinatorlayout_version = "1.2.0" // 1.3.0-alpha02
    def constraintlayout_version = "2.1.4" // 2.2.0-alpha13
    def material_version = "1.10.0" // 1.11.0-alpha01
    def browser_version = "1.7.0" // 1.8.0-beta01
    def lbm_version = "1.1.0"
    def swiperefresh_version = "1.2.0-alpha01"
    def documentfile_version = "1.1.0-alpha01"
    def lifecycle_version = "2.6.2" // 2.7.0-rc01
    def lifecycle_extensions_version = "2.2.0"
    def room_version = "2.4.3" // 2.5.2/2.6.1
    def sqlite_version = "2.4.0"
    def requery_version = "3.39.2"
    def paging_version = "2.1.2" //  3.2.0
    def preference_version = "1.2.1"
    def work_version = "2.9.0"
    def exif_version = "1.3.6"
    def biometric_version = "1.2.0-alpha05"
    def billingclient_version = "6.0.1"
    def javamail_version = "1.6.7"
    def jsoup_version = "1.16.2"
    def jsonpath_version = "2.8.0"
    def css_version = "0.9.30"
    def jax_version = "2.3.0-jaxb-1.0.6"
    def dnsjava_version = "2.1.9"
    def openpgp_version = "12.0"
    def badge_version = "1.1.22"
    def bugsnag_version = "5.31.3"
    def biweekly_version = "0.6.7"
    def vcard_version = "0.12.1"
    def relinker_version = "1.4.5"
    def markwon_version = "4.6.2"
    def bouncycastle_version = "1.76"
    def colorpicker_version = "0.0.15"
    def overscroll_version = "1.1.1"
    def appauth_version = "0.11.1"
    def jcharset_version = "2.1"
    def apache_poi = "3.17" // Do not update
    def outlook_parser_version = "1.7.13" // Do not update
    def reactivestreams_version = "1.0.3"
    def rxjava2_version = "2.2.21"
    def svg_version = "1.4"
    def compress_version = "1.24.0"
    def ipaddress_version = "5.4.0"
    def canary_version = "2.12"
    def ws_version = "2.14"

    // https://mvnrepository.com/artifact/com.android.tools/desugar_jdk_libs?repo=google
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'

    // https://developer.android.com/jetpack/androidx/releases/startup
    implementation "androidx.startup:startup-runtime:$startup_version"

    // https://developer.android.com/jetpack/androidx/releases/
    fdroidImplementation "com.google.code.findbugs:jsr305:3.0.2"
    implementation "androidx.annotation:annotation-experimental:$annotation_version_experimental"

    // https://mvnrepository.com/artifact/androidx.core/core
    implementation "androidx.core:core:$core_version"

    // https://mvnrepository.com/artifact/androidx.appcompat/appcompat
    // https://mvnrepository.com/artifact/androidx.emoji2/emoji2
    // https://mvnrepository.com/artifact/androidx.activity/activity
    // https://mvnrepository.com/artifact/androidx.fragment/fragment
    // https://mvnrepository.com/artifact/androidx.window/window-java
    implementation "androidx.appcompat:appcompat:$appcompat_version"
    //implementation "androidx.emoji2:emoji2:$emoji_version"
    implementation "com.google.flatbuffers:flatbuffers-java:$flatbuffers_version"
    implementation "androidx.activity:activity:$activity_version"
    implementation "androidx.fragment:fragment:$fragment_version"
    implementation "androidx.window:window-java:$windows_version"

    // https://developer.android.com/jetpack/androidx/releases/webkit
    // https://mvnrepository.com/artifact/androidx.webkit/webkit
    implementation "androidx.webkit:webkit:$webkit_version"

    // https://mvnrepository.com/artifact/androidx.viewpager2/viewpager2
    //implementation "androidx.viewpager2:viewpager2:1.1.0-alpha01"

    // https://mvnrepository.com/artifact/androidx.recyclerview/recyclerview
    // https://mvnrepository.com/artifact/androidx.recyclerview/recyclerview-selection
    implementation "androidx.recyclerview:recyclerview:$recyclerview_version"
    //implementation "androidx.recyclerview:recyclerview-selection:1.1.0" // 1.2.0-alpha01

    // https://mvnrepository.com/artifact/androidx.coordinatorlayout/coordinatorlayout
    implementation "androidx.coordinatorlayout:coordinatorlayout:$coordinatorlayout_version"

    // https://mvnrepository.com/artifact/androidx.constraintlayout/constraintlayout
    implementation "androidx.constraintlayout:constraintlayout:$constraintlayout_version"

    // https://mvnrepository.com/artifact/com.google.android.material/material
    // https://github.com/material-components/material-components-android/releases
    implementation "com.google.android.material:material:$material_version"

    // https://mvnrepository.com/artifact/androidx.browser/browser
    implementation "androidx.browser:browser:$browser_version"

    // https://mvnrepository.com/artifact/androidx.localbroadcastmanager/localbroadcastmanager
    implementation "androidx.localbroadcastmanager:localbroadcastmanager:$lbm_version"

    // https://mvnrepository.com/artifact/androidx.swiperefreshlayout/swiperefreshlayout
    implementation "androidx.swiperefreshlayout:swiperefreshlayout:$swiperefresh_version"

    // https://mvnrepository.com/artifact/androidx.documentfile/documentfile
    implementation "androidx.documentfile:documentfile:$documentfile_version"

    // https://mvnrepository.com/artifact/androidx.lifecycle/lifecycle-runtime
    // https://mvnrepository.com/artifact/androidx.lifecycle/lifecycle-livedata
    // https://mvnrepository.com/artifact/androidx.lifecycle/lifecycle-livedata-core
    // https://mvnrepository.com/artifact/androidx.lifecycle/lifecycle-viewmodel-savedstate
    // https://mvnrepository.com/artifact/androidx.lifecycle/lifecycle-compiler
    implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-livedata-core:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
    annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"

    // https://mvnrepository.com/artifact/androidx.lifecycle/lifecycle-extensions
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_extensions_version"

    // https://mvnrepository.com/artifact/androidx.room/room-runtime
    implementation "androidx.room:room-runtime:$room_version"
    implementation "androidx.room:room-common:$room_version" // because of exclude
    // https://mvnrepository.com/artifact/androidx.sqlite/sqlite-framework
    implementation "androidx.sqlite:sqlite-framework:$sqlite_version" // because of exclude
    annotationProcessor "androidx.room:room-compiler:$room_version"

    // https://www.sqlite.org/changes.html
    // https://github.com/requery/sqlite-android/
    // https://jitpack.io/#requery/sqlite-android
    //implementation "com.github.requery:sqlite-android:$requery_version"
    //implementation project(':sqlite-android')

    // https://mvnrepository.com/artifact/androidx.paging/paging-runtime
    // https://developer.android.com/jetpack/androidx/releases/paging
    //implementation "androidx.paging:paging-runtime:$paging_version"

    // https://mvnrepository.com/artifact/androidx.preference/preference
    implementation("androidx.preference:preference:$preference_version") {
        exclude group: "androidx.fragment", module: "fragment-ktx"
    }

    // https://mvnrepository.com/artifact/androidx.work/work-runtime
    implementation "androidx.work:work-runtime:$work_version"
    // implementation "com.google.guava:listenablefuture:1.0"
    implementation "com.google.guava:guava:31.1-android" // ListenableFuture

    // https://mvnrepository.com/artifact/androidx.exifinterface/exifinterface
    implementation "androidx.exifinterface:exifinterface:$exif_version"

    // https://mvnrepository.com/artifact/androidx.biometric/biometric
    // https://developer.android.com/jetpack/androidx/releases/biometric
    implementation "androidx.biometric:biometric:$biometric_version"

    // https://developer.android.com/google/play/billing/billing_library_releases_notes
    // https://android-developers.googleblog.com/2020/06/meet-google-play-billing-library.html
    githubImplementation "com.android.billingclient:billing:$billingclient_version"
    largeImplementation "com.android.billingclient:billing:$billingclient_version"
    playImplementation "com.android.billingclient:billing:$billingclient_version"

    // https://developer.amazon.com/docs/in-app-purchasing/iap-get-started.html
    amazonImplementation files('lib/in-app-purchasing-2.0.76.jar')

    // https://javaee.github.io/javamail/
    // https://projects.eclipse.org/projects/ee4j.javamail
    // https://mvnrepository.com/artifact/com.sun.mail
    //implementation "com.sun.mail:android-mail:$javamail_version"
    //implementation "com.sun.mail:android-activation:$javamail_version"

    // https://jsoup.org/news/
    // https://mvnrepository.com/artifact/org.jsoup/jsoup
    implementation "org.jsoup:jsoup:$jsoup_version"

    // https://github.com/json-path/JsonPath
    implementation "com.jayway.jsonpath:json-path:$jsonpath_version"

    // http://cssparser.sourceforge.net/
    // https://mvnrepository.com/artifact/net.sourceforge.cssparser/cssparser
    implementation "net.sourceforge.cssparser:cssparser:$css_version"

    // https://github.com/eclipse-ee4j/jaxb-ri
    // https://mvnrepository.com/artifact/org.w3c/dom
    implementation "org.w3c:dom:$jax_version"

    // http://www.dnsjava.org/
    // https://mvnrepository.com/artifact/dnsjava/dnsjava
    implementation "dnsjava:dnsjava:$dnsjava_version"

    // https://github.com/open-keychain/openpgp-api
    // https://mvnrepository.com/artifact/org.sufficientlysecure/openpgp-api
    //implementation "org.sufficientlysecure:openpgp-api:$openpgp_version"
    implementation project(':openpgp-api')

    // https://github.com/leolin310148/ShortcutBadger
    // https://mvnrepository.com/artifact/me.leolin/ShortcutBadger
    implementation "me.leolin:ShortcutBadger:$badge_version"

    // https://github.com/bugsnag/bugsnag-android
    // https://mvnrepository.com/artifact/com.bugsnag/bugsnag-android
    implementation("com.bugsnag:bugsnag-android:$bugsnag_version") {
        exclude group: "com.bugsnag", module: "bugsnag-plugin-android-anr"
        exclude group: "com.bugsnag", module: "bugsnag-plugin-android-ndk"
        exclude group: "com.bugsnag", module: "bugsnag-android-core"
    }

    // https://github.com/mangstadt/biweekly
    // https://mvnrepository.com/artifact/net.sf.biweekly/biweekly
    //implementation("net.sf.biweekly:biweekly:$biweekly_version") {
    //    exclude group: 'com.fasterxml.jackson.core', module: 'jackson-core'
    //    exclude group: 'com.fasterxml.jackson.core', module: 'jackson-databind'
    //}
    api "com.fasterxml.jackson.core:jackson-core:2.14.2"
    api "com.fasterxml.jackson.core:jackson-databind:2.14.2"

    // https://github.com/mangstadt/ez-vcard
    implementation("com.googlecode.ez-vcard:ez-vcard:$vcard_version") {
        exclude group: 'com.fasterxml.jackson.core', module: 'jackson-core'
        exclude group: 'com.fasterxml.jackson.core', module: 'jackson-databind'
    }

    // https://github.com/KeepSafe/ReLinker
    // https://mvnrepository.com/artifact/com.getkeepsafe.relinker/relinker
    //implementation "com.getkeepsafe.relinker:relinker:$relinker_version"

    // https://github.com/noties/Markwon
    // https://mvnrepository.com/artifact/io.noties.markwon/core
    implementation "io.noties.markwon:core:$markwon_version"
    implementation "io.noties.markwon:html:$markwon_version"

    // // https://github.com/QuadFlask/colorpicker
    //implementation "com.github.QuadFlask:colorpicker:$colorpicker_version"
    implementation project(':colorpicker')

    // https://github.com/EverythingMe/overscroll-decor
    // https://search.maven.org/artifact/io.github.everythingme/overscroll-decor-android
    implementation "io.github.everythingme:overscroll-decor-android:$overscroll_version"

    // https://www.bouncycastle.org/latest_releases.html
    // https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on
    implementation "org.bouncycastle:bcpkix-jdk15to18:$bouncycastle_version"
    implementation "org.bouncycastle:bctls-jdk15to18:$bouncycastle_version"

    // https://github.com/openid/AppAuth-Android
    // https://mvnrepository.com/artifact/net.openid/appauth
    implementation "net.openid:appauth:$appauth_version"

    // http://www.freeutils.net/source/jcharset/
    // https://mvnrepository.com/artifact/net.freeutils/jcharset
    implementation "net.freeutils:jcharset:$jcharset_version"

    // https://poi.apache.org/components/hmef/index.html
    // https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad
    implementation "org.apache.poi:poi-scratchpad:$apache_poi"

    // https://github.com/bbottema/outlook-message-parser
    implementation("org.simplejavamail:outlook-message-parser:$outlook_parser_version") {
        exclude group: "com.sun.activation", module: "jakarta.activation"
    }

    // https://mvnrepository.com/artifact/org.reactivestreams/reactive-streams
    // https://mvnrepository.com/artifact/io.reactivex.rxjava2/rxjava
    implementation "org.reactivestreams:reactive-streams:$reactivestreams_version"
    implementation "io.reactivex.rxjava2:rxjava:$rxjava2_version"

    // http://bigbadaboom.github.io/androidsvg/
    implementation "com.caverock:androidsvg:$svg_version"

    // https://commons.apache.org/proper/commons-compress/
    // https://mvnrepository.com/artifact/org.apache.commons/commons-compress
    implementation "org.apache.commons:commons-compress:$compress_version"

    // https://seancfoley.github.io/IPAddress/
    // https://mvnrepository.com/artifact/com.github.seancfoley/ipaddress
    implementation "com.github.seancfoley:ipaddress:$ipaddress_version"

    // https://mvnrepository.com/artifact/androidx.car.app/app?repo=google
    // implementation "androidx.car.app:app:1.4.0-alpha01"

    // https://github.com/square/leakcanary
    // https://square.github.io/leakcanary/getting_started/
    // https://square.github.io/leakcanary/changelog/
    // https://mvnrepository.com/artifact/com.squareup.leakcanary/leakcanary-android
    debugImplementation "com.squareup.leakcanary:leakcanary-android:$canary_version"

    // https://github.com/TakahikoKawasaki/nv-websocket-client
    implementation "com.neovisionaries:nv-websocket-client:$ws_version"
}