plugins {
    id "com.android.application"
    id "kotlin-android"
    id "org.jlleitschuh.gradle.ktlint" version "10.2.0"
}

def gitDescribe = { ->
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'git', 'describe', '--always', '--tags', '--dirty=-dirty'
        standardOutput = stdout
    }
    return stdout.toString().trim()
}

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion

    defaultConfig {
        minSdkVersion 29 // leave at 29 for robolectric tests
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionNameSuffix "-$gitDescribe"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        testInstrumentationRunnerArguments disableAnalytics: 'true'
    }

    buildTypes {
        release {
            minifyEnabled false
        }
    }

    lintOptions {
        disable "DialogFragmentCallbacksDetector",
                "InvalidFragmentVersionForActivityResult",
                "CheckedExceptions"
        abortOnError true
    }
    compileOptions {
        targetCompatibility 1.8
        sourceCompatibility 1.8
    }
    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
        languageVersion = "1.4"
    }
    testOptions {
        unitTests.all {
            useJUnitPlatform()
            testLogging {
                events "passed", "skipped", "failed"
            }
        }
        unitTests {
            includeAndroidResources = true
        }
    }

    sourceSets {
        test {
            java.srcDirs += "$projectDir/src/sharedTest/java"
        }
        androidTest {
            java.srcDirs += "$projectDir/src/sharedTest/java"
        }
    }

    signingConfigs {
        aosp {
            // Generated from the AOSP platform key:
            // https://android.googlesource.com/platform/build/+/refs/tags/android-11.0.0_r29/target/product/security/platform.pk8
            keyAlias "platform"
            keyPassword "platform"
            storeFile file("platform.jks")
            storePassword "platform"
        }
    }

    buildTypes.release.signingConfig = signingConfigs.aosp
    buildTypes.debug.signingConfig = signingConfigs.aosp
}

dependencies {
    compileOnly rootProject.ext.aosp_libs

    /**
     * Dependencies in AOSP
     *
     * We try to keep the dependencies in sync with what AOSP ships as Seedvault is meant to be built
     * with the AOSP build system and gradle builds are just for more pleasant development.
     * Using the AOSP versions in gradle builds allows us to spot issues early on.
     */
    implementation rootProject.ext.kotlin_libs.std
    // These coroutine libraries get upgraded otherwise to versions incompatible with kotlin version
    implementation rootProject.ext.kotlin_libs.coroutines

    implementation rootProject.ext.std_libs.androidx_core
    // A newer version gets pulled in with AOSP via core, so we include fragment here explicitly
    implementation rootProject.ext.std_libs.androidx_fragment
    implementation rootProject.ext.std_libs.androidx_activity
    implementation rootProject.ext.std_libs.androidx_preference
    implementation rootProject.ext.std_libs.androidx_lifecycle_viewmodel_ktx
    implementation rootProject.ext.std_libs.androidx_lifecycle_livedata_ktx
    implementation rootProject.ext.std_libs.androidx_constraintlayout
    implementation rootProject.ext.std_libs.androidx_documentfile
    implementation rootProject.ext.std_libs.com_google_android_material

    implementation rootProject.ext.storage_libs.com_google_crypto_tink_android

    /**
     * Storage Dependencies
     */
    implementation project(':storage:lib')

    /**
     * External Dependencies
     *
     * If the dependencies below are updated,
     * please make sure to update the prebuilt libraries and the Android.bp files
     * in the top-level `libs` folder to reflect that.
     * You can copy these libraries from ~/.gradle/caches/modules-2/files-2.1
     */
    // later versions than 2.1.1 require newer kotlin version
//    implementation "io.insert-koin:koin-core-jvm:3.1.2"
//    implementation "io.insert-koin:koin-android:3.1.2"
    implementation fileTree(include: ['*.jar'], dir: "${rootProject.rootDir}/libs/koin-android")
    implementation fileTree(include: ['*.aar'], dir: "${rootProject.rootDir}/libs/koin-android")

//    implementation "cash.z.ecc.android:kotlin-bip39:1.0.2"
    implementation fileTree(include: ['kotlin-bip39-1.0.2.jar'], dir: "${rootProject.rootDir}/libs")

    /**
     * Test Dependencies (do not concern the AOSP build)
     */
    lintChecks rootProject.ext.lint_libs.exceptions

    // anything less than 'implementation' fails tests run with gradlew
    testImplementation rootProject.ext.aosp_libs
    testImplementation 'androidx.test.ext:junit:1.1.3'
    testImplementation('org.robolectric:robolectric:4.3.1') { // 4.4 has issue with non-idle Looper
        // https://github.com/robolectric/robolectric/issues/5245
        exclude group: "com.google.auto.service", module: "auto-service"
    }
    testImplementation "org.junit.jupiter:junit-jupiter-api:$junit5_version"
    testImplementation "org.junit.jupiter:junit-jupiter-params:$junit5_version"
    testImplementation "io.mockk:mockk:$mockk_version"
    testImplementation 'org.bitcoinj:bitcoinj-core:0.15.10'
    testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5_version"
    testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$junit5_version"

    androidTestImplementation 'androidx.test:runner:1.4.0'
    androidTestImplementation 'androidx.test:rules:1.4.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation "io.mockk:mockk-android:$mockk_version"
}

apply from: "${rootProject.rootDir}/gradle/ktlint.gradle"

gradle.projectsEvaluated {
    tasks.withType(JavaCompile) {
        if (JavaVersion.current() >= JavaVersion.VERSION_1_9) {
            options.compilerArgs.addAll(['--release', '8'])
        }
        options.compilerArgs.add('-Xbootclasspath/p:app/libs/android.jar:app/libs/libcore.jar')
    }
}

configurations {
    all {
        resolutionStrategy {
            failOnNonReproducibleResolution()
        }
    }
}
