apply plugin: 'com.android.application'
apply plugin: 'jacoco'
apply plugin: "com.jaredsburrows.spoon"
apply plugin: "kotlin-android"

android {

    compileSdkVersion 29
    buildToolsVersion '29.0.3'


    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    lintOptions {
        abortOnError false
    }

    testOptions {
        unitTests {
            includeAndroidResources = true
        }
    }
    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 29
        multiDexEnabled true
        applicationId "cucumber.cukeulator"
        testApplicationId "cucumber.cukeulator.test"
        testInstrumentationRunner "cucumber.cukeulator.test.CukeulatorAndroidJUnitRunner"
        versionCode 1
        versionName '1.0'
        //testInstrumentationRunnerArguments = [
            // cucumberUseAndroidJUnitRunner: getProperty("cucumberUseAndroidJUnitRunner"),
            // uncomment this to clear app data before each test when running with orchestrator
            // clearPackageData: 'true'
        //]
    }


    buildTypes {
        release {
            minifyEnabled false
        }

        debug {}
    }

    packagingOptions {
        exclude 'LICENSE.txt'
    }

    // With the following option we does not have to mock everything,
    // e.g. super calls cannot be mocked with Mockito only (just with Powermock).
    testOptions {
        unitTests.returnDefaultValues = true
        animationsDisabled true
//        uncomment this to run tests with orchestrator
//        execution 'ANDROIDX_TEST_ORCHESTRATOR'
    }

}

// ==================================================================
// Project dependencies
// ==================================================================

dependencies {
    //
    // The following dependency works, if you build Cucumber-JVM on your local machine:
    //
    // androidTestImplementation 'io.cucumber:cucumber-android:2.3.2-SNAPSHOT'
    //
    // (If you enable it, you must disable the dependency to the stable Cucumber version above.)
    //
    // If you have not yet built Cucumber-JVM on your local machine, build it with:
    //
    //                   cd <cucumber-jvm-source-root>
    //                   mvn clean install
    //
    // Hint: you find the Cucumber-JVM source root under a parent directory of this file.
    //
    // If you only change the Android source, you also can do:
    //
    //                   cd <cucumber-jvm-source-root>/android
    //                   mvn install
    //
    // Now, after you have been built Cucumber-JVM with one of the commands above, it is published
    // to your local Maven repository and may be used by other projects on your local machine.
    //
    // For our example project, that means you can execute the feature files, with the just built
    // Cucumber-JVM library by using the following command (press Alt+F12 in Android Studio):
    //
    //                   gradlew connectedCheck --refresh-dependencies
    //
    // The --refresh-dependencies option seems not to be required anymore for recent Android Studio
    // and Gradle versions. But, if your Cucumber-JVM snapshot dependency is not updated
    // automatically by Gradle, the flag always bypasses any caching of dependencies.


    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

//    testImplementation 'junit:junit:4.12'
//    testImplementation 'org.mockito:mockito-core:2.10.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    androidTestImplementation 'androidx.test:rules:1.3.0'
    androidTestUtil 'androidx.test:orchestrator:1.3.0'

    // Use the stable Cucumber version
    androidTestImplementation project(":cucumber_sample_app::cucumber-android")
    androidTestImplementation "io.cucumber:cucumber-picocontainer:4.8.1"

}

// ==================================================================
// Custom tasks
// ==================================================================


task runInstrumentationTests {
    group "verification"
    mustRunAfter "deleteExistingCucumberReports"
    dependsOn "deleteExistingCucumberReports","spoonDebugAndroidTest"
    finalizedBy "downloadCucumberReports"
}

spoon {
    debug = true
    //this is faster but can be set to false
    singleInstrumentationCall = true
    grantAll = true
    shard = true
}


/*
 * Downloads all Cucumber reports from the connected device.
 */
task downloadCucumberReports {
    group "Verification"
    description "Downloads the rich Cucumber report files (HTML, XML, JSON) from the connected device"

    doLast {
        def deviceSourcePath = getCucumberDevicePath()
        def localReportPath = new File(buildDir, "reports/cucumber")
        if (!localReportPath.exists()) {
            localReportPath.mkdirs()
        }
        if (!localReportPath.exists()) {
            throw new GradleException("Could not create $localReportPath")
        }
        def adb = getAdbPath()
        def files = getCucumberReportFileNames()
        files.each { fileName ->
            println fileName
            exec {
                commandLine adb, 'pull', "$deviceSourcePath/$fileName", localReportPath
            }
        }
    }
}

/**
 * Deletes existing Cucumber reports on the device.
 */
task deleteExistingCucumberReports {
    group "Verification"
    description "Removes the rich Cucumber report files (HTML, XML, JSON) from the connected device"
    doLast {
        def deviceSourcePath = getCucumberDevicePath()
        def files = getCucumberReportFileNames()
        files.each { fileName ->
            def deviceFileName = deviceSourcePath + '/' + fileName
            def output2 = executeAdb('if [ -d "' + deviceFileName + '" ]; then rm -r "' + deviceFileName + '"; else rm -r "' + deviceFileName + '" ; fi')
            println output2
        }
    }
}

/**
 * Sets the required permissions for Cucumber to write on the internal storage.
 */
task grantPermissions(dependsOn: 'installDebug') {
    doLast {
        def adb = getAdbPath()
        // We only set the permissions for the main application
        def mainPackageName = android.defaultConfig.applicationId
        def readPermission = "android.permission.READ_EXTERNAL_STORAGE"
        def writePermission = "android.permission.WRITE_EXTERNAL_STORAGE"
        exec { commandLine adb, 'shell', 'pm', 'grant', mainPackageName, readPermission }
        exec { commandLine adb, 'shell', 'pm', 'grant', mainPackageName, writePermission }
    }
}


// ==================================================================
// Utility methods
// ==================================================================

/**
 * Utility method to get the full ADB path
 * @return the absolute ADB path
 */
String getAdbPath() {
    def adb = android.getAdbExecutable().toString()
    if (adb.isEmpty()) {
        throw new GradleException("Could not detect adb path")
    }
    return adb
}

/**
 * Sometime adb returns '\r' character multiple times.
 * @param s the original string returned by adb
 * @return the fixed string without '\r'
 */
static def fixAdbOutput(String s) {
    return s.replaceAll("[\r\n]+", "\n").trim()
}

/**
 * Runs the adb tool
 * @param program the program which is executed on the connected device
 * @return the output of the adb tool
 */
def executeAdb(String program) {
    def process = new ProcessBuilder(getAdbPath(), "shell", program).redirectErrorStream(true).start()
    String text = new BufferedReader(new InputStreamReader(process.inputStream)).text
    return fixAdbOutput(text)
}

/**
 * The path which is used to store the Cucumber files.
 * @return
 */
def getCucumberDevicePath() {
    return 'sdcard/Android/data/cucumber.cukeulator/files/reports'
}

/**
 * @return the known Cucumber report files/directories
 */
static def getCucumberReportFileNames() {
    return ['cucumber.xml', 'cucumber.html']
}
