buildscript {
    repositories {
        jcenter()
        google()
        maven { url "https://jitpack.io" }
        maven { url 'https://maven.fabric.io/public' }
        maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
    }

    dependencies {
        classpath "com.android.tools.build:gradle:$versions.androidPlugin"
        classpath "com.jakewharton:butterknife-gradle-plugin:$versions.butterknife"
        classpath "com.github.triplet.gradle:play-publisher:$versions.playPublisherPlugin"
        classpath "com.getkeepsafe.dexcount:dexcount-gradle-plugin:$versions.dexCountPlugin"
        classpath "io.fabric.tools:gradle:$versions.fabricPlugin"
        classpath "com.vanniktech:gradle-android-apk-size-plugin:$versions.apkSizePlugin"
        classpath "com.airbnb.okreplay:gradle-plugin:$versions.okReplayFakeServerResponses"
        classpath "com.stanfy.spoon:spoon-gradle-plugin:$versions.spoonGradlePlugin"
    }

}

apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
apply plugin: 'com.github.triplet.play' // Plugin to publish apk to play store.
apply plugin: 'com.getkeepsafe.dexcount'
apply plugin: 'com.vanniktech.android.apk.size'
apply plugin: 'okreplay' // See https://github.com/airbnb/okreplay
apply plugin: 'spoon' // See https://github.com/stanfy/spoon-gradle-plugin

apply from: '../config/gradle/static_analysis_java.gradle'
apply from: 'config/gradle/lint.gradle'
apply from: 'config/gradle/jacoco.gradle'
apply from: 'config/gradle/grant_animation_permission.gradle'

repositories {
    maven { url 'https://maven.fabric.io/public' }
    maven { url "https://jitpack.io" }
    flatDir {
        dirs 'libs'
    }
    maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
}

android {
    compileSdkVersion 27

    defaultConfig {
        // Speed hack to decrease development environment build times. See gradle.properties file for more details about enabling this.
        minSdkVersion increaseMinSdkForDev.toBoolean() ? 21 : 16
        targetSdkVersion 27
        applicationId 'com.justanotherandroidapp'
        versionName version // Comes from gradle.properties
        versionCode buildVersionCode() // Comes from versioning.gradle
        vectorDrawables.useSupportLibrary true
        testApplicationId 'com.justanotherandroidapp.test'
        testInstrumentationRunner 'com.example.util.runner.EspressoTestRunner'

        // Fetch fabric api key from relevant properties file and place it in android manifest.
        def keystorePropertiesFile = file("src/main/assets/project.properties")
        def keystoreProperties = new Properties()
        keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
        manifestPlaceholders = [fabric_api_key: keystoreProperties['fabricApiKey']]

        // Speed up the build by fetching min. number of resources required for dev builds, and no extra languages overall than the ones
        // supported in the project. See https://developer.android.com/studio/build/shrink-code.html for more details.
        if (decreaseAmountOfResourcesForDev.toBoolean()) {
            resConfigs "en"
        } else {
            resConfigs("en", "hdpi")
        }
    }

    // Speed up the build by disabling the cruncher that optimizes pngs
    if (disableAaptCruncherForDev.toBoolean()) {
        aaptOptions.cruncherEnabled = false
    }

    signingConfigs {
        release {
            // Fetch signing config from relevant properties file
            def keystorePropertiesFile = file("config/signing/signing.properties")
            def keystoreProperties = new Properties()
            keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storePassword keystoreProperties['storePassword']
            storeFile file('config/signing/release.keystore')
        }

        flavorDimensions "app" // This is mandatory since android gradle plugin 3.0

        buildTypes {
            debug {
                resValue 'string', 'app_name', 'Example.debug'
                applicationIdSuffix '.develop'
                // These 2 lines allow incremental builds to work properly
                buildConfigField "String", "GIT_SHA", "\"DEBUG\""
                buildConfigField "String", "BUILD_TIME", "\"DEBUG\""
                debuggable true
                minifyEnabled false
                // Enable jacoco for espresso tests. For espresso and mixed see jacoco.gradle file.
                testCoverageEnabled true
                multiDexEnabled true
            }

            qa.initWith debug
            qa {
                resValue 'string', 'app_name', 'Example.qa'
                applicationIdSuffix ".qa"
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }

            release {
                resValue 'string', 'app_name', 'Example'
                def gitSha = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim()
                def buildTime = new GregorianCalendar().format("MM-dd-yyyy' 'h:mm:ss a z")
                // Gather build information for release builds and propagate to fabric.
                buildConfigField "String", "GIT_SHA", "\"${gitSha}\""
                buildConfigField "String", "BUILD_TIME", "\"${buildTime}\""
                minifyEnabled true
                signingConfig signingConfigs.release
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }

    }

    variantFilter { variant ->
        def buildType = variant.buildType.name;
        // Speed hack to decrease dev build times. See gradle.properties file for more details about enabling this.
        if (disableSomeBuildTypes.toBoolean() && !buildType.equals(disableAllBuildTypesApartFrom)) {
            variant.setIgnore(true);
        }
    }

    sourceSets {
        def CODE_SHARED_BY_DEBUG_AND_QA_BUILD_TYPES = 'src/debugAndQa/java'
        def RES_SHARED_BY_DEBUG_AND_QA_BUILD_TYPES = 'src/debugAndQa/res'
        def UNIT_TESTS_LOCATION = 'src/unitTests/java'
        def INTEGRATION_TESTS_LOCATION = 'src/integrationTests/java'
        def HELPERS_SHARED_ACROSS_ALL_TESTS = 'src/testHelpers/java'
        def RESOURCES_SHARED_ACROSS_ALL_TESTS = 'src/testHelpers/resources'
        def DEBUG_ONLY_BUILD_TYPE_UNIT_TESTS = 'src/unitTestsDebug/java'
        def QA_ONLY_BUILD_TYPE_UNIT_TESTS = 'src/unitTestsQa/java'
        def RELEASE_ONLY_BUILD_TYPE_UNIT_TESTS = 'src/unitTestsRelease/java'
        def ESPRESSO_TESTS_LOCATION = 'src/espressoTests/java'
        def ESPRESSO_INTEGRATION_TESTS_LOCATION = 'src/espressoIntegrationTests/java'
        def ESPRESSO_ASSETS_LOCATION_1 = 'src/espressoTests/assets'
        def ESPRESSO_ASSETS_LOCATION_2 = 'src/espressoIntegrationTests/assets'

        // Code related source sets
        debug.java.srcDirs += [CODE_SHARED_BY_DEBUG_AND_QA_BUILD_TYPES]
        qa.java.srcDirs += [CODE_SHARED_BY_DEBUG_AND_QA_BUILD_TYPES]
        debug.res.srcDirs += [RES_SHARED_BY_DEBUG_AND_QA_BUILD_TYPES]
        qa.res.srcDirs += [RES_SHARED_BY_DEBUG_AND_QA_BUILD_TYPES]

        // Test related source sets
        test.java.srcDirs += [UNIT_TESTS_LOCATION, INTEGRATION_TESTS_LOCATION, HELPERS_SHARED_ACROSS_ALL_TESTS]
        test.resources.srcDirs += [RESOURCES_SHARED_ACROSS_ALL_TESTS]
        testDebug.java.srcDirs += [DEBUG_ONLY_BUILD_TYPE_UNIT_TESTS]
        testQa.java.srcDirs += [QA_ONLY_BUILD_TYPE_UNIT_TESTS]
        testRelease.java.srcDirs += [RELEASE_ONLY_BUILD_TYPE_UNIT_TESTS]

        // Espresso test related source sets
        androidTest.java.srcDirs += [ESPRESSO_TESTS_LOCATION, ESPRESSO_INTEGRATION_TESTS_LOCATION, HELPERS_SHARED_ACROSS_ALL_TESTS]
        androidTest.resources.srcDirs += [RESOURCES_SHARED_ACROSS_ALL_TESTS]
        androidTest.assets.srcDirs += [ESPRESSO_ASSETS_LOCATION_1, ESPRESSO_ASSETS_LOCATION_2]
    }

    testOptions {
        unitTests {
            all {
                systemProperty 'robolectric.logging.enabled', 'true'
                systemProperty 'robolectric.logging', 'stdout'
                // Print test details in the terminal (or CI).
                testLogging {
                    events 'passed', 'skipped', 'failed', 'standardOut', 'standardError'
                    exceptionFormat 'full'
                }
            }
            includeAndroidResources = true // So that robolectric has access to resources
        }
    }

    compileOptions {
        encoding 'UTF-8'
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    dexOptions {
        preDexLibraries isRunningInCI.toBoolean()
        javaMaxHeapSize dexMemoryAllocation
        dexInProcess true
    }

    // Grant all runtime permissions when installing an apk from the command line or android studio. For now this is only required for
    // the OkReplay library (https://github.com/airbnb/okreplay) as it requires the EXTERNAL STORAGE permission to record the server
    // responses.
    if (grantAllRuntimePermissions.toBoolean()) {
        adbOptions.installOptions "-g"
    }

}

// Plugin to manage automated publishing to the playstore. See https://github.com/Triple-T/gradle-play-publisher
play {
    serviceAccountEmail = '560654334828-compute@developer.gserviceaccount.com'
    pk12File = file(pk12FileLocation) // See gradle.properties for details
    track = releaseTrack // See gradle.properties for details
    uploadImages = true
    userFraction = 0.05 // Only necessary for 'rollout'. This means that a rollout for 5% of the users is performed.
    untrackOld = true // will remove the 'alpha' release when a new higher version code 'beta' is uploaded.
}

// Settings for the dexcount gradle plugin. See https://github.com/KeepSafe/dexcount-gradle-plugin
// When running the plugin results appear both in the command line as well as in the "build/outputs/dexcount/" folder
dexcount {
    format = "list"
    includeClasses = false
    includeFieldCount = true
    includeTotalMethodCount = true
    orderByMethodCount = false
    verbose = true
    maxTreeDepth = Integer.MAX_VALUE
    runOnEachPackage = false
}

// Fail the build when the release APK is more than the number defined in the gradle.properties file via 'maxReleaseApkSizeInBytes' property.
gradle.taskGraph.whenReady { taskGraph ->
    if (taskGraph.hasTask(":app:assembleRelease")) {
        apkSize.maxApkSize = maxReleaseApkSizeInBytes.toInteger()
    }
}

dependencies {
    // MODULE DEPENDENCIES *********************************************************************************************
    // Import the common module into this module
    implementation project(':common')

    // DIRECT JAR/AAR DEPENDENCIES *************************************************************************************
    // Screenshots in firebase cloud testing
    androidTestImplementation(name: 'cloudtestingscreenshotter_lib', ext: 'aar')

    // MAIN DEPENDENCIES ***********************************************************************************************
    implementation projectDependencies.supportLibsAppCompat
    implementation projectDependencies.supportLibsAnnotations
    implementation projectDependencies.supportLibsRecyclerview
    implementation projectDependencies.supportLibsConstraintLayout
    implementation projectDependencies.supportLibsMultiDex
    implementation projectDependencies.crashlytics
    implementation projectDependencies.answersAnalytics
    annotationProcessor projectDependencies.daggerAnnotationProcessor
    implementation projectDependencies.dagger
    implementation projectDependencies.daggerAndroid
    annotationProcessor projectDependencies.daggerAndroidAnnotationProcessor
    implementation projectDependencies.timber
    implementation projectDependencies.mosbyMvp
    implementation projectDependencies.mosbyViewState
    implementation projectDependencies.mosbyNullPresenter
    implementation projectDependencies.nullabilityAnnotations
    androidTestImplementation projectDependencies.nullabilityAnnotations //fixes version conflict
    implementation projectDependencies.butterknife
    annotationProcessor projectDependencies.butterknifeAnnotationProcessor
    implementation projectDependencies.retrofit
    implementation projectDependencies.retrofitGson
    implementation projectDependencies.okhttpLoggingInterceptor
    implementation projectDependencies.retrofitRxJava2Adapter
    implementation projectDependencies.rxAndroid
    implementation projectDependencies.rxJava2
    implementation projectDependencies.glideImageLoading
    compileOnly projectDependencies.autoValue
    annotationProcessor projectDependencies.autoValue
    // Synchronizing app with espresso. We could have added this only for debug/qa build types and hidden it behind a no-op interface (like
    // Stetho), but it's tiny. No point.
    implementation projectDependencies.espressoIdlingResource
    implementation projectDependencies.jodaTimeDanLew
    implementation projectDependencies.appShortcutsLibrary
    annotationProcessor projectDependencies.appShortcutsLibraryAnnotationProcessor
    implementation projectDependencies.lottieAnimations
    // This is 'compileOnly' as it's not really needed at runtime. The generated code is the only thing needed (and this happens to have a
    // dependency on guava).
    compileOnly projectDependencies.autoFactory
    annotationProcessor projectDependencies.autoFactory
    implementation projectDependencies.permissionsDispatcher
    annotationProcessor projectDependencies.permissionsDispatcherAnnotationProcessor
    compileOnly projectDependencies.findbugsAnnotations

    // DEBUG DEPENDENCIES **********************************************************************************************
    debugImplementation(projectDependencies.stetho) {
        exclude module: 'jsr305'
    }
    debugImplementation(projectDependencies.stethoOkHttp) {
        exclude module: 'jsr305'
    }
    qaImplementation(projectDependencies.stetho) {
        exclude module: 'jsr305'
    }
    qaImplementation(projectDependencies.stethoOkHttp) {
        exclude module: 'jsr305'
    }
    debugImplementation projectDependencies.rxLint
    debugImplementation projectDependencies.retrofitMockMode
    qaImplementation projectDependencies.retrofitMockMode
    debugImplementation projectDependencies.chuckNetworkInterceptor
    qaImplementation projectDependencies.chuckNetworkInterceptor
    releaseImplementation projectDependencies.chuckNetworkInterceptorNoOp
    debugImplementation projectDependencies.traceurRxJavaLogging
    qaImplementation projectDependencies.traceurRxJavaLogging
    debugImplementation projectDependencies.sherlockLibrary
    qaImplementation projectDependencies.sherlockLibrary
    releaseImplementation projectDependencies.sherlockLibraryNoOp
    debugImplementation projectDependencies.okReplayFakeServerResponses
    qaImplementation projectDependencies.okReplayFakeServerResponses
    releaseImplementation projectDependencies.okReplayFakeServerResponsesNoOp

    // TEST DEPENDENCIES ***********************************************************************************************
    testImplementation projectDependencies.jUnit
    testImplementation projectDependencies.assertJJava8
    testImplementation projectDependencies.mockito
    testImplementation projectDependencies.robolectric
    testImplementation projectDependencies.robolectricProblemFix
    testImplementation projectDependencies.robolectricMultiDex
    testImplementation projectDependencies.okhttpMockWebServer
    testImplementation projectDependencies.jodaTimeDanLew
    testImplementation projectDependencies.burstTesting
    testCompileOnly projectDependencies.findbugsAnnotations

    // INSTRUMENTATION TESTS DEPENDENCIES ******************************************************************************
    androidTestImplementation projectDependencies.okReplayFakeServerResponsesEspresso
    androidTestImplementation projectDependencies.cappucinoAnimationDisabling
    androidTestImplementation projectDependencies.espresso
    androidTestImplementation projectDependencies.espressoIntents
    androidTestImplementation projectDependencies.espressoTestRunner
    androidTestImplementation projectDependencies.espressoTestRules
    androidTestImplementation(projectDependencies.espressoContrib) {
        exclude module: 'support-annotations'
        exclude module: 'support-v4'
        exclude module: 'support-v13'
        exclude module: 'recyclerview-v7'
        exclude module: 'design'
    }
    // Force specific library version for instrumentation tests. Fixes version conflict issue.
    androidTestImplementation projectDependencies.supportLibsAnnotations
    // For instrumentation tests the java 7 compiled library is used to avoid dex errors.
    androidTestImplementation projectDependencies.assertJJava7
    androidTestImplementation projectDependencies.okhttpMockWebServer
    androidTestImplementation projectDependencies.spoonEspressoTests
    androidTestCompileOnly projectDependencies.findbugsAnnotations
}
