apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply from: '../rninfo.gradle'

def _kotlinMinVersion = '1.8.0'
def _materialMinVersion = '1.11.0'

def _ext = rootProject.ext
def _compileSdkVersion = _ext.has('compileSdkVersion') ? _ext.compileSdkVersion : 31
def _targetSdkVersion = _ext.has('targetSdkVersion') ? _ext.targetSdkVersion : 31
def _buildToolsVersion = _ext.has('buildToolsVersion') ? _ext.buildToolsVersion : '31.0.0'
def _minSdkVersion = _ext.has('minSdkVersion') ? _ext.minSdkVersion : 21
def _kotlinVersion = _ext.has('detoxKotlinVersion') ? _ext.detoxKotlinVersion : _kotlinMinVersion
def _kotlinStdlib = _ext.has('detoxKotlinStdlib') ? _ext.detoxKotlinStdlib : 'kotlin-stdlib-jdk8'

// RN native code comes from either maven-central (in which case, need the *exact* version),
// or otherwise from node_modules/, where the version is already aligned, by definition.
// noinspection GradleDynamicVersion
def _rnNativeArtifact = rnInfo.isRN71OrHigher
        ? "com.facebook.react:react-android:${rnInfo.version}"
            : 'com.facebook.react:react-native:+'

println "[$project] Resorted to RN native artifact $_rnNativeArtifact"

android {
    def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0].toInteger()
    if (agpVersion >= 7) {
        namespace "com.wix.detox"
    }
    compileSdk _compileSdkVersion
    buildToolsVersion = _buildToolsVersion

    defaultConfig {
        minSdkVersion _minSdkVersion
        targetSdkVersion _targetSdkVersion
        versionCode 1
        versionName '1.0'

        consumerProguardFiles 'proguard-rules.pro'
    }

    flavorDimensions = ['detox']
    productFlavors {
        full {
            dimension 'detox'
        }
        coreNative {
            dimension 'detox'
        }
    }

    testOptions {
        unitTests.includeAndroidResources = true
        unitTests.returnDefaultValues = true
        unitTests.all { t ->
            reports {
                html.required = true
            }
            testLogging {
                events "passed", "skipped", "failed", "standardOut", "standardError"
            }
            afterSuite { desc, result ->
                if (!desc.parent) { // will match the outermost suite
                    def output = "      ${result.resultType} (${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)     "
                    def repeatLength = output.length()
                    println '\n' + ('-' * repeatLength) + '\n' + output + '\n' + ('-' * repeatLength) + '\n'

                    println "see report at file://${t.reports.html.outputLocation}/index.html"
                }
            }
        }
    }

    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }

    lintOptions {
        abortOnError false
    }

    if (rnInfo.isRN72OrHigher) {
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_17
            targetCompatibility JavaVersion.VERSION_17
        }

        kotlinOptions {
            jvmTarget = '17'
        }
    } else {
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_11
            targetCompatibility JavaVersion.VERSION_11
        }

        kotlinOptions {
            jvmTarget = '11'
        }
    }
}

// In a nutshell:
// "The api configuration should be used to declare dependencies which are exported by the library API, whereas the
//  implementation configuration should be used to declare dependencies which are internal to the component."
// --> https://docs.gradle.org/5.5/userguide/java_library_plugin.html

// Fundamental deps.
dependencies {
    api "org.jetbrains.kotlin:$_kotlinStdlib:$_kotlinVersion"

    compileOnly "${_rnNativeArtifact}"
}

// androidx.test deps.
// All are aligned with this release: https://developer.android.com/jetpack/androidx/releases/test#1.4.0
dependencies {

    // Versions are in-sync with the 'androidx-test-1.4.0' release/tag of the android-test github repo,
    // used by the Detox generator. See https://github.com/android/android-test/releases/tag/androidx-test-1.4.0
    // Important: Should remain so when generator tag is replaced!
    api('androidx.test.espresso:espresso-core:3.7.0') {
        because 'Needed all across Detox but also makes Espresso seamlessly provided to Detox users with hybrid apps/E2E-tests.'
    }
    api('androidx.test.espresso:espresso-web:3.7.0') {
        because 'Web-View testing'
    }
    api('androidx.test.espresso:espresso-contrib:3.7.0') {
        because 'Android datepicker support'
        exclude group: "org.checkerframework", module: "checker"
    }
    api('org.hamcrest:hamcrest:2.2') {
        because 'See https://github.com/wix/Detox/issues/3920. Need to force hamcrest 2.2 win in battle of 2.2 vs. 1.3 (specified by Espresso).'
    }
    api('androidx.test:rules:1.7.0') {
        because 'of ActivityTestRule. Needed by users *and* internally used by Detox.'
    }
    api('androidx.test.ext:junit:1.3.0') {
        because 'Needed so as to seamlessly provide AndroidJUnit4 to Detox users. Depends on junit core.'
    }
    // Version is the latest; Cannot sync with the Github repo (e.g. android/android-test) because the androidx
    // packaging version of associated classes is simply not there...
    api('androidx.test.uiautomator:uiautomator:2.3.0') {
        because 'Needed by Detox but also makes UIAutomator seamlessly provided to Detox users with hybrid apps/E2E-tests.'
    }
    api('androidx.test:core-ktx:1.7.0') {
        because 'Needed by Detox but also makes AndroidX test core seamlessly provided to Detox users with hybrid apps/E2E-tests.'
    }
    implementation("org.jetbrains.kotlin:kotlin-reflect:$_kotlinVersion") {
        because('Needed by Detox for kotlin reflection')
    }
}

// Third-party/extension deps.
dependencies {
    implementation('org.apache.commons:commons-lang3:3.7') {
        because 'Needed by invoke. Warning: Upgrading to newer versions is not seamless.'
    }
    implementation 'com.github.anrwatchdog:anrwatchdog:1.4.0'

    implementation fileTree(dir: '../libs', includes: ['*.jar']) // Includes: Genymotion SDK
}

// Unit-testing deps.
dependencies {
    testImplementation "${_rnNativeArtifact}"
    testImplementation 'org.json:json:20230227'

// https://github.com/spekframework/spek/issues/232#issuecomment-610732158
    testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.7.2'

    testImplementation 'org.assertj:assertj-core:3.16.1'
    testImplementation "org.jetbrains.kotlin:kotlin-test:$_kotlinVersion"
    testImplementation 'org.apache.commons:commons-io:1.3.2'
    testImplementation 'org.mockito.kotlin:mockito-kotlin:5.2.1'
    testImplementation 'org.robolectric:robolectric:4.11.1'

    testImplementation("com.google.android.material:material:$_materialMinVersion") {
        because 'Material components are mentioned explicitly (e.g. Slider in get-attributes handler)'
    }
}

// Spek (https://spekframework.org/setup-android)
if (rootProject.hasProperty('isOfficialDetoxLib') ||
    rootProject.hasProperty('isOfficialDetoxApp')) {

    apply plugin: 'de.mannodermaus.android-junit5'

    android {
        testOptions {
            junitPlatform {
                filters {
                    engines {
                        include 'spek2', 'junit-vintage'
                    }
                }
            }
        }
    }

    dependencies {
        testImplementation 'org.spekframework.spek2:spek-dsl-jvm:2.0.15'
        testImplementation 'org.spekframework.spek2:spek-runner-junit5:2.0.15'
    }
}

// Enable publishing
if (rootProject.hasProperty('isOfficialDetoxLib')) {
    apply from: './publishing.gradle'
}

